You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I use laragon for local development and running
I first noticed something like url('home.test')->getAbsoluteUrl() only returned the path (no scheme, no host)
After trying with request()->getUrl()->getAbsoluteUrl() the scheme showed here, but the host was empty
The above code produced this "https:///_manage/test/"
On inspection, i made this change in Pecee\Http\Request
$this->setHost($this->getHeader('http-host'));
// Check if special IIS header exist, otherwise use default.$url = $this->getHeader('unencoded-url');
if ($url !== null) {
$this->setUrl(newUrl($url));
} else {
$this->setUrl(newUrl(urldecode((string)$this->getHeader('request-uri'))));
}
$this->url->setHost($this->host); // change: since host has already been set$this->setContentType((string)$this->getHeader('content-type'));
Yup figured out the same, but I am afraid it is going to be a bit more complicated to fix than a simple setHost call.
The Url class has the following url-specific attributes: schema, host, port, username, password, path, params, fragment.
From all the mentioned attributes only the last 3 can be retrieved from the request_uri. The rest is more complicated as it may be found in several places (for example forewarding gives different headers than a direct request). Furthermore, when parsing an url malformed/illformed data should be considered as clients can put anything into any of the header fields of a request.
A quick googlesearch would reveal several attempts to 'reconstruct' an url-string from scratch, but I think it is better to make the Request class build an Url instance from the $_SERVER global with appropriate sanatization instead. It is simply faster and easier to manage the different components, as most of the parsing is already done.
Well, I took a quick stab at a more proper way of building the Url iinstance. It is not tested against all environments and php-engines, but as far as I could test it, it should do a decent job. It would be wonderfull if those with more experiance and test capabilities would perfect this for a PR.
/** * Create url from global $_SERVER data. * Note, this does not include validation so be carefull when using the returned result! * @param bool checkForwarded `true` to include forwarded headers when checking/obtaining fields. */staticfunction createUrl(bool $checkForwarded = true)
{
functions($name)
{
if (isset($_SERVER[$name]))
return$_SERVER[$name];
returnnull;
}
$url = newUrl(s('REQUEST_URI'));
// Checking if http(s) protocol is used, in that case try proper handling, otherwise hope for the best and take server protocol literallyif (stripos((s('SERVER_PROTOCOL') != null ? s('SERVER_PROTOCOL') : (s('REQUEST_SCHEME') != null ? s('REQUEST_SCHEME') : '')), 'http') !== false) {
if ((s('HTTPS') == 'on' || s('HTTPS') == 1) ||
$checkForwarded ? (s('HTTP_X_FORWARDED_PROTO') == 'https') : false
)
$url->setScheme('https');
else$url->setScheme('http');
} else$url->setScheme((s('SERVER_PROTOCOL') != null) ? s('SERVER_PROTOCOL') : s('REQUEST_SCHEME'));
// Setting the host from a request is messy, proper validstion or else substitution of internal/fixed variable is advised. $host = null;
if ($checkForwarded) {
if (s('HTTP_X_FORWARDED_HOST') != null)
$host = s('HTTP_X_FORWARDED_HOST');
}
if ($host == null && s('SERVER_NAME') != null)
$host = s('SERVER_NAME');
if ($host == null && s('HTTP_HOST') != null)
$host = s('HTTP_HOST');
// This is a default/fallback value as setting the hostname reliably requires environment/engine-dependent configuration. Handy quick-fix if all else fails.// if ($host == null)// $host = Config::$_HOST_NAME;// some systems and/or header-variants include the port, this would strip out the host in case it is presentif(stripos($host, ':') != false)
$host = parse_url($host, PHP_URL_HOST);
$url->setHost($host);
if (s('SERVER_PORT') != null)
$url->setPort(s('SERVER_PORT'));
// Reset query-string as soms system removes parameters when multiple are presentif (s('QUERY_STRING') != null)
$url->setQueryString(s('QUERY_STRING'));
// Following two properties may not be available with some php-engines, so don't rely on it being present with incomming requests. if (s('PHP_AUTH_USER') != null)
$url->setPassword(s('PHP_AUTH_USER'));
if (s('PHP_AUTH_PW') != null)
$url->setUsername(s('PHP_AUTH_PW'));
return$url;
}
The above can be used to generate an Url instance from the php-globals (i.e. $_SERVER). For a quick-fix the way you could use this is as follows:
// either one of following for obtaining the router instance$router = newRouter();
$router = SimpleRouter::router();
$router->getRequest()->setUrl(createUrl())
This will 'reset' the Url which I would advise to do close to / at the start of the routing/index script.
One side-note with obtaining the host property. Since http-host (which is used in the Request constructor) may include the port if non-standard, It may mess the workings of the Request class? I haven't done a deep-dive into where that host property is used. But I think it is safe to say it will mess with the workings of the Url class since everything is treating the host variable as if the port part is only set separately in its own designated variable. Hence the workaround prior to setting the host.
Activity
N247S commentedon Mar 11, 2024
Yup figured out the same, but I am afraid it is going to be a bit more complicated to fix than a simple
setHostcall.The
Urlclass has the following url-specific attributes:schema,host,port,username,password,path,params,fragment.From all the mentioned attributes only the last 3 can be retrieved from the
request_uri. The rest is more complicated as it may be found in several places (for example forewarding gives different headers than a direct request). Furthermore, when parsing an url malformed/illformed data should be considered as clients can put anything into any of the header fields of a request.A quick googlesearch would reveal several attempts to 'reconstruct' an url-string from scratch, but I think it is better to make the
Requestclass build anUrlinstance from the$_SERVERglobal with appropriate sanatization instead. It is simply faster and easier to manage the different components, as most of the parsing is already done.N247S commentedon Mar 18, 2024
Well, I took a quick stab at a more proper way of building the
Urliinstance. It is not tested against all environments and php-engines, but as far as I could test it, it should do a decent job. It would be wonderfull if those with more experiance and test capabilities would perfect this for a PR.The above can be used to generate an
Urlinstance from the php-globals (i.e.$_SERVER). For a quick-fix the way you could use this is as follows:This will 'reset' the
Urlwhich I would advise to do close to / at the start of the routing/index script.One side-note with obtaining the
hostproperty. Sincehttp-host(which is used in theRequestconstructor) may include theportif non-standard, It may mess the workings of the Request class? I haven't done a deep-dive into where thathostproperty is used. But I think it is safe to say it will mess with the workings of theUrlclass since everything is treating thehostvariable as if theportpart is only set separately in its own designated variable. Hence the workaround prior to setting thehost.michaelthedev commentedon Mar 19, 2024
Usually, I make fixes for things like this myself
But looks like it's going to cause one problem or the other that's why I created the issue for the author to look into