Bug->Doc #77889 [Nab]: URL in Location header not used
| From: | ASchmidt at Anamera dot net | Date: | Tue, 16 Feb 2021 17:00:41 +0000 |
| Subject: | Bug->Doc #77889 [Nab]: URL in Location header not used | ||
| References: | 1 | Groups: | php.doc.bugs |
| Request: | Send a blank email to doc-bugs+get-18557@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=77889&edit=1
ID: 77889
User updated by: ASchmidt at Anamera dot net
Reported by: ASchmidt at Anamera dot net
Summary: URL in Location header not used
Status: Not a bug
-Type: Bug
+Type: Documentation Problem
Package: Streams related
Operating System: Windows x64
PHP Version: 7.2.17
Assigned To: cmb
Block user comment: N
Private report: N
New Comment:
Dear "rtrtrtrtrt@dfdfdfdf.dfd35", thatnk you for your comment.
>> there is no point to set a Host-Header and a Location-Header with different values <<
There appears to be confusion on how HTTP works. The "Host" header is a REQUEST header,
set by the application (the PHP script). The "Location" header is a RESPONSE header set by
the contacted host.
The whole POINT of a server's "Location" response is to advise the client of a
DIFFERENT URL (possibly involving a different "Host"!) that should be contacted. The
Location response being different from the originally requested is not "garbage in/out",
but intended behavior!?
A PHP script does not know in advance that it will receive a "Location" response. The net
effect of this issue is that the "Host" header and the "follow_location" option
are mutually exclusive, which should be explicitly stated.
Previous Comments:
------------------------------------------------------------------------
[2021-02-16 16:44:24] cmb@php.net
The documentation states[1]:
| Values in this option will override other values (such as
| User-agent:, Host:, and Authentication:).
In other words, as soon as you set any custom headers, it is your
responsibility that they are suitable.
[1] <https://www.php.net/manual/en/context.http.php#refsect1-context.http-options>
------------------------------------------------------------------------
[2021-02-16 16:40:15] rtrtrtrtrt at dfdfdfdf dot dfd35
> it would mean that PHP is responsible for replacing
> any previous, obsolete "Host" header, with the correct,
> valid Host header to match the "Location" response
no, it's a programming language
garbage in, garbage out
there is no point to set a Host-Header and a Location-Header with different values and a programming
language is expected to do what you say - even if it's wrong
------------------------------------------------------------------------
[2021-02-16 16:23:57] ASchmidt at Anamera dot net
Since this is not intuitive (and the default setting of follow-location=true effectively bars the
use of the "Host:" header), I have submitted a comment to the manual page https://www.php.net/manual/en/context.http.php.
However, as far as the PHP behavior NOT being a bug, HTTP 1.1 made "Host" headers
mandatory, and more than ONE Host header is explicitly disallowed
(https://tools.ietf.org/html/rfc7230#section-5.4). Standards further explicitly require that
"Host" headers are to be replaced, e.g., the original "Host" must NOT not be
forwarded (the example of Proxy servers is being cited.)
While I understand/appreciate the "explanation" (work-around), I believe the old PHP
behavior is both unexpected, and not consistent with the RFC:
- Since every HTTP 1.1 request must have exactly ONE, and VALID, "Host" header that
matches the intended target host, and
- since PHP creates the secondary HTTP request to "follow-location",
- it would mean that PHP is responsible for replacing any previous, obsolete "Host"
header, with the correct, valid Host header to match the "Location" response.
Otherwise the resulting "follow-location" request is not compliant with HTTP 1.1
standards.
------------------------------------------------------------------------
[2021-02-16 14:59:41] cmb@php.net
Since you're explicitly setting the Host, finecars.cc is used for
all requests, resulting in the undesired behavior. Just remove
that entry from the headers array.
------------------------------------------------------------------------
[2019-04-14 04:06:57] ASchmidt at Anamera dot net
Description:
------------
For $host = 'www.finecars.cc', the HTML content is correctly received.
For $host = 'finecars.cc', the initial response is:
HTTP/1.1 301 Moved Permanently
Location: http://www.finecars.cc/
However, after that, PHP does NOT actually retrieve "www.finecars.cc" as defined in the
Location header, but continues to retry the original URL "finecars.cc" until
'max_redirects' is exhausted.
Test script:
---------------
<?php
declare(strict_types=1);
$host = 'finecars.cc';
$headers = array(
'Host' => $host,
'User-Agent' => 'Anamera/2.0',
'Accept-Charset' => 'UTF-8',
'Referer' => ( '0' == $_SERVER['SERVER_PORT_SECURE']
? 'http' : 'https'
)."://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}",
'Connection' => 'close',
'Origin' => ( '0' == $_SERVER['SERVER_PORT_SECURE']
? 'http' : 'https' )."://{$_SERVER['SERVER_NAME']}",
);
$header_lines = [];
foreach ( $headers as $name => $entry )
$header_lines[] = "{$name}: {$entry}";
$http_options = array(
'http' => array(
'protocol_version' => 1.1,
'timeout' => 30, // float: seconds.
'follow_location' => 1,
'max_redirects' => 5,
'ignore_errors' => true, // fetch content even on failure status codes.
'method' => 'GET',
'header' => $header_lines,
// 'user_agent' => '', // use:
'header'['User-Agent'].
// 'content' => '', // for POST and PUT.
),
);
$http_context = stream_context_create( $http_options );
$file = file_get_contents( "http://{$host}", false,
$http_context );
var_dump( $http_options, $http_response_header );
die( 'Current PHP version: ' . phpversion() );
?>
Expected result:
----------------
0 => string 'HTTP/1.1 301 Moved Permanently' (length=30)
1 => string 'Content-Type: text/html; charset=UTF-8' (length=38)
2 => string 'Location: http://www.finecars.cc/' (length=33)
3 => string 'Connection: close' (length=17)
4 => string 'Content-Length: 146' (length=19)
5 => string 'HTTP/1.1 200 OK' (length=15)
6 => string 'Content-Type: text/html;charset=iso-8859-1' (length=42)
7 => string 'Connection: close' (length=17)
8 => string 'Content-Length: 87608' (length=21)
Actual result:
--------------
0 => string 'HTTP/1.1 301 Moved Permanently' (length=30)
1 => string 'Content-Type: text/html; charset=UTF-8' (length=38)
2 => string 'Location: http://www.finecars.cc/' (length=33)
3 => string 'Connection: close' (length=17)
4 => string 'Content-Length: 146' (length=19)
5 => string 'HTTP/1.1 301 Moved Permanently' (length=30)
6 => string 'Content-Type: text/html; charset=UTF-8' (length=38)
7 => string 'Location: http://www.finecars.cc/' (length=33)
8 => string 'Connection: close' (length=17)
9 => string 'Content-Length: 146' (length=19)
10 => string 'HTTP/1.1 301 Moved Permanently' (length=30)
11 => string 'Content-Type: text/html; charset=UTF-8' (length=38)
12 => string 'Location: http://www.finecars.cc/' (length=33)
13 => string 'Connection: close' (length=17)
14 => string 'Content-Length: 146' (length=19)
etc.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=77889&edit=1