@@ -39,13 +39,16 @@ class_exists(ServerBag::class);
39
39
*/
40
40
class Request
41
41
{
42
- const HEADER_FORWARDED = 0b00001 ; // When using RFC 7239
43
- const HEADER_X_FORWARDED_FOR = 0b00010 ;
44
- const HEADER_X_FORWARDED_HOST = 0b00100 ;
45
- const HEADER_X_FORWARDED_PROTO = 0b01000 ;
46
- const HEADER_X_FORWARDED_PORT = 0b10000 ;
47
- const HEADER_X_FORWARDED_ALL = 0b11110 ; // All "X-Forwarded-*" headers
48
- const HEADER_X_FORWARDED_AWS_ELB = 0b11010 ; // AWS ELB doesn't send X-Forwarded-Host
42
+ const HEADER_FORWARDED = 0b000001 ; // When using RFC 7239
43
+ const HEADER_X_FORWARDED_FOR = 0b000010 ;
44
+ const HEADER_X_FORWARDED_HOST = 0b000100 ;
45
+ const HEADER_X_FORWARDED_PROTO = 0b001000 ;
46
+ const HEADER_X_FORWARDED_PORT = 0b010000 ;
47
+ const HEADER_X_FORWARDED_PREFIX = 0b100000 ;
48
+
49
+ const HEADER_X_FORWARDED_ALL = 0b011110 ; // All "X-Forwarded-*" headers sent by "usual" reverse proxy
50
+ const HEADER_X_FORWARDED_AWS_ELB = 0b011010 ; // AWS ELB doesn't send X-Forwarded-Host
51
+ const HEADER_X_FORWARDED_TRAEFIK = 0b111110 ; // All "X-Forwarded-*" headers sent by Traefik reverse proxy
49
52
50
53
const METHOD_HEAD = 'HEAD ' ;
51
54
const METHOD_GET = 'GET ' ;
@@ -237,6 +240,7 @@ class Request
237
240
self ::HEADER_X_FORWARDED_HOST => 'X_FORWARDED_HOST ' ,
238
241
self ::HEADER_X_FORWARDED_PROTO => 'X_FORWARDED_PROTO ' ,
239
242
self ::HEADER_X_FORWARDED_PORT => 'X_FORWARDED_PORT ' ,
243
+ self ::HEADER_X_FORWARDED_PREFIX => 'X_FORWARDED_PREFIX ' ,
240
244
];
241
245
242
246
/**
@@ -894,6 +898,24 @@ public function getBasePath()
894
898
* @return string The raw URL (i.e. not urldecoded)
895
899
*/
896
900
public function getBaseUrl ()
901
+ {
902
+ $ trustedPrefix = '' ;
903
+
904
+ // the proxy prefix must be prepended to any prefix being needed at the webserver level
905
+ if ($ this ->isFromTrustedProxy () && $ trustedPrefixValues = $ this ->getTrustedValues (self ::HEADER_X_FORWARDED_PREFIX )) {
906
+ $ trustedPrefix = rtrim ($ trustedPrefixValues [0 ], '/ ' );
907
+ }
908
+
909
+ return $ trustedPrefix .$ this ->getBaseUrlReal ();
910
+ }
911
+
912
+ /**
913
+ * Returns the real base URL received by the webserver from which this request is executed.
914
+ * The URL does not include trusted reverse proxy prefix.
915
+ *
916
+ * @return string The raw URL (i.e. not urldecoded)
917
+ */
918
+ private function getBaseUrlReal ()
897
919
{
898
920
if (null === $ this ->baseUrl ) {
899
921
$ this ->baseUrl = $ this ->prepareBaseUrl ();
@@ -1910,7 +1932,7 @@ protected function preparePathInfo()
1910
1932
$ requestUri = '/ ' .$ requestUri ;
1911
1933
}
1912
1934
1913
- if (null === ($ baseUrl = $ this ->getBaseUrl ())) {
1935
+ if (null === ($ baseUrl = $ this ->getBaseUrlReal ())) {
1914
1936
return $ requestUri ;
1915
1937
}
1916
1938
@@ -2014,7 +2036,7 @@ private function getTrustedValues(int $type, string $ip = null): array
2014
2036
}
2015
2037
}
2016
2038
2017
- if ((self ::$ trustedHeaderSet & self ::HEADER_FORWARDED ) && $ this ->headers ->has (self ::$ trustedHeaders [self ::HEADER_FORWARDED ])) {
2039
+ if ((self ::$ trustedHeaderSet & self ::HEADER_FORWARDED ) && ( isset ( self :: $ forwardedParams [ $ type ])) && $ this ->headers ->has (self ::$ trustedHeaders [self ::HEADER_FORWARDED ])) {
2018
2040
$ forwarded = $ this ->headers ->get (self ::$ trustedHeaders [self ::HEADER_FORWARDED ]);
2019
2041
$ parts = HeaderUtils::split ($ forwarded , ',;= ' );
2020
2042
$ forwardedValues = [];
0 commit comments