Page MenuHomeDevCentral

D1636.diff
No OneTemporary

D1636.diff

diff --git a/src/HTTP/Requests/Request.php b/src/HTTP/Requests/Request.php
--- a/src/HTTP/Requests/Request.php
+++ b/src/HTTP/Requests/Request.php
@@ -7,5 +7,6 @@
use WithAcceptedLanguages;
use WithRemoteAddress;
+ use WithURL;
}
diff --git a/src/HTTP/Requests/WithURL.php b/src/HTTP/Requests/WithURL.php
new file mode 100644
--- /dev/null
+++ b/src/HTTP/Requests/WithURL.php
@@ -0,0 +1,87 @@
+<?php
+
+namespace Keruald\OmniTools\HTTP\Requests;
+
+use Keruald\OmniTools\Strings\Multibyte\StringUtilities;
+
+trait WithURL {
+
+ ///
+ /// Main methods
+ ///
+
+ public static function getServerURL () : string {
+ $scheme = self::getScheme();
+ $name = self::getServerName();
+ $port = self::getPort();
+
+ // If we forward for a proxy, trust the scheme instead of standard :80
+ $fixToHTTPS = $port === 80 && $scheme === "https";
+
+ if ($port === 443 || $fixToHTTPS) {
+ return "https://$name";
+ }
+
+ if ($port === 80) {
+ return "http://$name";
+ }
+
+ return "$scheme://$name:$port";
+ }
+
+ ///
+ /// Helper methods
+ ///
+
+ public static function getPort () : int {
+ return (int)($_SERVER['SERVER_PORT'] ?? 80);
+ }
+
+ public static function getServerName () : string {
+ return $_SERVER['SERVER_NAME'] ?? "localhost";
+ }
+
+ public static function getScheme () : string {
+ return $_SERVER['REQUEST_SCHEME']
+ ?? $_SERVER['HTTP_X_FORWARDED_PROTO']
+ ?? $_SERVER['HTTP_X_FORWARDED_PROTOCOL']
+ ?? $_SERVER['HTTP_X_URL_SCHEME']
+ ?? self::guessScheme();
+ }
+
+ private static function guessScheme () : string {
+ return self::isHTTPS() ? "https" : "http";
+ }
+
+ public static function isHTTPS () : bool {
+ // Legacy headers have been documented at MDN:
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto
+
+ $headers = self::getHTTPSHeadersTable();
+ foreach ($headers as $header => $value) {
+ if (isset($_SERVER[$header]) && $_SERVER[$header] === $value) {
+ return true;
+ }
+ }
+
+ if (isset($_SERVER['HTTP_FORWARDED'])) {
+ return StringUtilities::contains($_SERVER['HTTP_FORWARDED'], "proto=https");
+ }
+
+ return false;
+ }
+
+ private static function getHTTPSHeadersTable () : array {
+ return [
+ "HTTPS" => "on",
+ "REQUEST_SCHEME" => "https",
+ "SERVER_PORT" => "443",
+ "HTTP_X_FORWARDED_PROTO" => "https",
+ "HTTP_FRONT_END_HTTPS" => "on",
+ "HTTP_X_FORWARDED_PROTOCOL" => "https",
+ "HTTP_X_FORWARDED_SSL" => "on",
+ "HTTP_X_URL_SCHEME" => "https",
+ ];
+ }
+
+}
diff --git a/src/Strings/Multibyte/StringUtilities.php b/src/Strings/Multibyte/StringUtilities.php
--- a/src/Strings/Multibyte/StringUtilities.php
+++ b/src/Strings/Multibyte/StringUtilities.php
@@ -53,4 +53,8 @@
return $length === 0 || mb_substr($string, -$length) === $end;
}
+ public static function contains (string $string, string $needle) : bool {
+ return strpos($string, $needle) !== false;
+ }
+
}
diff --git a/tests/HTTP/Requests/RequestTest.php b/tests/HTTP/Requests/RequestTest.php
--- a/tests/HTTP/Requests/RequestTest.php
+++ b/tests/HTTP/Requests/RequestTest.php
@@ -8,6 +8,10 @@
class RequestTest extends TestCase {
+ ///
+ /// Tests
+ ///
+
/**
* @covers \Keruald\OmniTools\HTTP\Requests\Request::getRemoteAddress
* @backupGlobals enabled
@@ -45,4 +49,69 @@
);
}
+ /**
+ * @backupGlobals enabled
+ * @dataProvider provideServerURLs
+ */
+ public function testGetServerURL (array $server, string $url) : void {
+ $_SERVER = $server;
+
+ $this->assertEquals($url, Request::getServerURL());
+ }
+
+ ///
+ /// Data providers
+ ///
+
+ public function provideServerURLs () : iterable {
+ yield [[], "http://localhost"];
+ yield [["UNRELATED" => "ANYTHING"], "http://localhost"];
+
+ yield [
+ [
+ "SERVER_PORT" => "80",
+ "SERVER_NAME" => "acme.tld",
+ ],
+ "http://acme.tld"
+ ];
+
+ yield [
+ [
+ "SERVER_PORT" => "443",
+ "SERVER_NAME" => "acme.tld",
+ ],
+ "https://acme.tld"
+ ];
+
+ yield [
+ [
+ "SERVER_PORT" => "80",
+ "SERVER_NAME" => "acme.tld",
+ "HTTP_X_FORWARDED_PROTO" => "https",
+ ],
+ "https://acme.tld"
+ ];
+
+ yield [
+ [
+ "SERVER_PORT" => "80",
+ "SERVER_NAME" => "acme.tld",
+ "HTTP_FORWARDED" => "for=192.0.2.43, for=\"[2001:db8:cafe::17]\", proto=https, by=203.0.113.43",
+ ],
+ "https://acme.tld"
+ ];
+
+ yield [
+ [
+ "SERVER_PORT" => "8443",
+ "SERVER_NAME" => "acme.tld",
+ "HTTPS" => "on",
+ ],
+ "https://acme.tld:8443"
+ ];
+
+
+ }
+
+
}

File Metadata

Mime Type
text/plain
Expires
Fri, Dec 20, 13:07 (18 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2308094
Default Alt Text
D1636.diff (5 KB)

Event Timeline