Aim
To write a PHP script that checks whether the page is called from https or http.
Theory
HTTP and HTTPS differ by one layer: HTTPS is ordinary HTTP tunnelled through TLS, which adds encryption (nobody on the path can read credentials, cookies or form data), integrity (nothing can be altered in transit) and authentication (the certificate proves the server's identity). HTTP defaults to port 80, HTTPS to port 443. Detecting the scheme matters in practice — to redirect insecure requests, build absolute URLs with the right prefix, or mark cookies secure.
PHP has no single "scheme" variable; it must be inferred from what the web server put into $_SERVER:
$_SERVER["HTTPS"]is the primary signal — a non-empty value (normallyon) when TLS terminated at the server, absent or empty on plain HTTP. The trap: IIS sets it to the literal stringofffor HTTP, so the correct test is!empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] !== "off".$_SERVER["REQUEST_SCHEME"](Apache 2.4+) directly holdshttporhttps.$_SERVER["SERVER_PORT"]equal to 443 is a strong secondary hint.
Behind a proxy or load balancer TLS usually terminates at the proxy, so PHP receives plain HTTP and all three checks say http; the original scheme then arrives in the X-Forwarded-Proto: https request header ($_SERVER["HTTP_X_FORWARDED_PROTO"]) — trusted only when set by your own proxy, since clients can forge it. In a CLI/compiler run there is no request at all, so these $_SERVER keys are simply absent — the snippet fills them in itself to keep the detection logic demonstrable.
Requirements
- XAMPP/WAMP with Apache and PHP 8.x (Apache's SSL on port 443 enabled to test the https branch)
- Code editor (VS Code); browser or terminal
Procedure
- Start Apache from the XAMPP Control Panel.
- Save the snippet as
p28_https_check.phpinC:\xampp\htdocs\wbplab. - Open
http://localhost/wbplab/p28_https_check.php— the plain-HTTP request printshttp. - XAMPP's Apache also listens on 443 with a self-signed certificate: open
https://localhost/wbplab/p28_https_check.php, accept the browser's certificate warning, and the page printshttps. - Run
php p28_https_check.phpin a terminal — the CLI branch simulates an HTTPS request, so it also printshttps.
Explanation of the Code
- The
php_sapi_name() === "cli"guard detects a terminal/compiler run, where no web server populated$_SERVER; it pre-fillsHTTPS = "on",REQUEST_SCHEME = "https"andSERVER_PORT = 443so the detection logic has real values to inspect. $isHttpsORs three independent signals:!empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] !== "off"(the canonical test, tolerant of IIS'soff),REQUEST_SCHEME === "https", and(int) $_SERVER["SERVER_PORT"] === 443.- The
(int)cast matters:SERVER_PORTarrives as a string, and the strict===comparison against the integer 443 would otherwise always fail. - The
isset()/!empty()guards keep the expression warning-free when a key is missing, and||short-circuits — any one positive signal settles the answer. - The final
echouses a ternary to print the detected scheme.
Expected Output
In the compiler/CLI the simulated values make all three tests true, so the script prints Protocol used: https. Under XAMPP the answer follows the URL used: http://localhost/... prints Protocol used: http (no HTTPS key, scheme http, port 80), while https://localhost/... prints Protocol used: https.
🎯 Viva Questions
- What does HTTPS add over HTTP? TLS — encryption of the whole exchange, integrity against tampering, and server authentication via a certificate.
- What values can
$_SERVER["HTTPS"]take? Absent/empty on plain HTTP, a non-empty value (usuallyon) under TLS — and the literaloffon IIS over plain HTTP. - Why test
!== "off"as well as!empty()? Because IIS'soffis a non-empty string; without the extra test, plain HTTP on IIS would be misreported as secure. - Why cast
SERVER_PORTtoint?$_SERVERvalues are strings;"443" === 443is false under strict comparison, so the cast makes the port check reliable. - How is HTTPS detected behind a load balancer? TLS ends at the proxy, so PHP inspects the
X-Forwarded-Protoheader — trusting it only from the known proxy, as clients can forge it. - Which default ports do HTTP and HTTPS use? 80 for HTTP and 443 for HTTPS.
CO Mapping
CO1, CO2