Hi all,
I ran into the following problem I would like to get an opinion on: We
noticed that our website returns a HTTP/1.1 chunked response even when
the request was a HTTP/1.0 request (e.g. php file_get_contents).
What happens:
- Wordpress (wrongly) set the result code with a hardcoded
@header("HTTP/1.1 $header $text", true, $header); - PHP 5.2.1 (IMHO wrongly) patches the protocol in
sapi/apache2handler/sapi_apache2.c function
php_apache_sapi_send_headers, probably because "force-response-1.1" does
not exist (at least not in any production version):
ctx->r->proto_num = 1000 + (sline[7]-'0'); - Apache thinks the request was 1.1 and under some circumstances decides
to switch to Transfer-Encoding chunked.
I think the following should be done:
- Ask Wordpress to use $_SERVER['SERVER_PROTOCOL'] when available
instead of a hardcoded HTTP/1.1 (I'll do that) - Update the PHP
header()
documentation to mention this. I was also
thinking that supporting/documenting header(null, true, 404); or the
like would be nice for people who only want to set the return code and
leave the HTTP type unchanged. - Maybe change php_apache_sapi_send_headers to not mess with proto_num.
This make it impossible to force the response to HTTP/1.1 but I don't
think that should be done anyway as the client might not expect it. For
the same reason I think the line
apr_table_set(ctx->r->subprocess_env, "force-response-1.1", "true");
should probably be removed as well...
Should I open a bug report on this?
Regards,
- Chris
Replying to a 1.0 request with a 1.1 response is perfectly fine.
It is the default for a fresh Apache install on a request for a
simple static file, for example.
-Rasmus
Christian Schneider wrote:
Hi all,
I ran into the following problem I would like to get an opinion on: We
noticed that our website returns a HTTP/1.1 chunked response even when
the request was a HTTP/1.0 request (e.g. php file_get_contents).What happens:
- Wordpress (wrongly) set the result code with a hardcoded
@header("HTTP/1.1 $header $text", true, $header);- PHP 5.2.1 (IMHO wrongly) patches the protocol in
sapi/apache2handler/sapi_apache2.c function
php_apache_sapi_send_headers, probably because "force-response-1.1" does
not exist (at least not in any production version):
ctx->r->proto_num = 1000 + (sline[7]-'0');- Apache thinks the request was 1.1 and under some circumstances decides
to switch to Transfer-Encoding chunked.I think the following should be done:
- Ask Wordpress to use $_SERVER['SERVER_PROTOCOL'] when available
instead of a hardcoded HTTP/1.1 (I'll do that)- Update the PHP
header()
documentation to mention this. I was also
thinking that supporting/documenting header(null, true, 404); or the
like would be nice for people who only want to set the return code and
leave the HTTP type unchanged.- Maybe change php_apache_sapi_send_headers to not mess with proto_num.
This make it impossible to force the response to HTTP/1.1 but I don't
think that should be done anyway as the client might not expect it. For
the same reason I think the line
apr_table_set(ctx->r->subprocess_env, "force-response-1.1", "true");
should probably be removed as well...Should I open a bug report on this?
Regards,
- Chris
Rasmus Lerdorf wrote:
Replying to a 1.0 request with a 1.1 response is perfectly fine.
It is the default for a fresh Apache install on a request for a
simple static file, for example.
This seems bogus to me.
Quoting from the very last line of the HTTP RFC 3.6 Transfer Codings:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6
"A server MUST NOT send transfer-codings to an HTTP/1.0 client."
Now if all the Apache requirements for chunked encoding match (apart
from the request originally being a HTTP/1.0 one) then this will lead to
a Transfer-Encoding: chunked being sent to the client. Which violates
the RFC and breaks clients like wget, php and other simple clients not
expecting a chunked response.
On top of that http://www.ietf.org/rfc/rfc2145.txt states in section 2.3
that "An HTTP server SHOULD send a response version equal to the highest
version for which the server is at least conditionally compliant, and
whose major version is less than or equal to the one received in the
request."
It doesn't seem to be a problem with static files as it won't send a
chunked response if it knows the length and hence can send a
Content-Length header. Still a violation of the RFCs IMHO though.
On the other hand I see no reason to upgrade a reponse to HTTP/1.1 when
HTTP/1.0 was requested.
Regards,
- Chris
Christian Schneider wrote:
version for which the server is at least conditionally compliant, and
whose major version is less than or equal to the one received in the
request."
Oops, missed the "major" version part there. Sorry for that, should read
things more carefully, especially at 1:30am :-)
I still think it breaks the other RFC though. And it definitely breaks
some HTTP/1.0 clients if chunked transfer is done because of upgrading
the response.
- Chris
Christian Schneider wrote:
Christian Schneider wrote:
version for which the server is at least conditionally compliant, and
whose major version is less than or equal to the one received in the
request."Oops, missed the "major" version part there. Sorry for that, should read
things more carefully, especially at 1:30am :-)I still think it breaks the other RFC though. And it definitely breaks
some HTTP/1.0 clients if chunked transfer is done because of upgrading
the response.
This came up many times on the Apache lists years ago, and Roy Fielding
who wrote that spec repeatedly said it was fine to reply with a 1.1
response to a 1.0 request.
-Rasmus
Am Dienstag, 1. Mai 2007 01:49 schrieb Rasmus Lerdorf:
This came up many times on the Apache lists years ago, and Roy Fielding
who wrote that spec repeatedly said it was fine to reply with a 1.1
response to a 1.0 request.
Did he give any rationale for his view?
Regards,
Oliver
Oliver Block wrote:
Am Dienstag, 1. Mai 2007 01:49 schrieb Rasmus Lerdorf:
This came up many times on the Apache lists years ago, and Roy Fielding
who wrote that spec repeatedly said it was fine to reply with a 1.1
response to a 1.0 request.Did he give any rationale for his view?
Go read the archives. And note that I only said it was fine to respond
with a 1.1 reply, that doesn't mean it is fine to send an encoding the
client doesn't support.
-Rasmus
Rasmus Lerdorf wrote:
Go read the archives. And note that I only said it was fine to respond
with a 1.1 reply, that doesn't mean it is fine to send an encoding the
client doesn't support.
That's why I think PHP shouldn't mess with the proto_num field or
otherwise upgrade the HTTP version of the response because it makes
Apache believe it is safe to send a chunked response if it wants to.
And I don't see any benefit in doing so. I'd be interested to learn why
this was done though. My assumption so far is that it's done "because
the PHP script asked for HTTP/1.1 so we should try to send that back"
without considering the danger of creating a chunked response as a side
effect.
Regards,
- Chris
Am Dienstag, 1. Mai 2007 02:22 schrieb Rasmus Lerdorf:
Oliver Block wrote:
And note that I only said it was fine to respond
with a 1.1 reply, that doesn't mean it is fine to send an encoding the
client doesn't support.
Well.
Regards,
Oliver
-----Original Message-----
From: Rasmus Lerdorf [mailto:rasmus@lerdorf.com]
Sent: Tuesday, May 01, 2007 2:22 AM
To: Oliver Block
Cc: internals@lists.php.net
Subject: Re: [PHP-DEV] Setting HTTP results code vs. HTTP typeOliver Block wrote:
Am Dienstag, 1. Mai 2007 01:49 schrieb Rasmus Lerdorf:
This came up many times on the Apache lists years ago, and Roy Fielding
who wrote that spec repeatedly said it was fine to reply with a 1.1
response to a 1.0 request.Did he give any rationale for his view?
Go read the archives. And note that I only said it was fine to respond
with a 1.1 reply, that doesn't mean it is fine to send an encoding the
client doesn't support.
And that's exactly what other web servers also do:
I come from Sun One Web Server 6.1 and 7.0), so I can tell what they do:
They respond always with HTTP/1.1 but if the request came in with HTTP/1.0
they do not use chunked encoding for the reply and use "Connection: close".
Uwe
Hello Rasmus,
Am Dienstag, 1. Mai 2007 01:05 schrieb Rasmus Lerdorf:
Replying to a 1.0 request with a 1.1 response is perfectly fine.
I doubt that it is standard conformant. HTTP/1.0 doesn't
even know chunked data (RFC1945).
Best Regards,
Oliver
- Update the PHP
header()
documentation to mention this. I was also
thinking that supporting/documenting header(null, true, 404); or the
like would be nice for people who only want to set the return code and
leave the HTTP type unchanged.
I think this would bet he best approach, to give the PHP a users a
consistent way (consistent through all SAPIs) to set the http response
code without changing protocols.
Your problem only occurs with apache, as apache gives PHP the possibility to
change the HTTP protocol version. Other SAPIs, like my NSAPI one, cannot do
this because the protocol is the servers task and modules are not allowed to
change it in a wrong way.
The problem with setting the response code is:
-
Some PHP scripts use header('Status: 301') to set response code. Problem
here: This only works with CGI and Apache. The problem here is in PHP SAPI
code: PHP only checks for ('HTTP/...') header strings and extracts status
code and protocol version from it. The string 'HTTP/..' is never send to the
SAPI. In case of 'Status: ', SAPI sends the header as a normal HTTP header
to the webserver -> Apache maps this, CGI also because specs want this. -
Some scripts use header('HTTP/1.0 301 Moved Permanently'). Problem here:
You must supply a HTTP version (this seems to be a problem in Apache), and
you must supply the textual representation (but most/all? SAPIs ignore the
textual representation). So header('HTTP/1.0 301 X') would be OK.
What we need is:
-
a consistent parsing of
header()
inputs before sending to the underlying
SAPI. This means also parsing for 'Status: XXX' and setting the status code.
The later SAPI then will generate the correct parameters to be sent to the
server (in case of CGI it will "regenerate" a Status:-header). -
a function to simply set the status code without changing anything other.
- supplies such a method with 'Status: 301' if it is correctly implemented.
If nobody is against it I would try to implement a consistent header parsing
for SAPI...
Uwe Schindler wrote:
- Some scripts use header('HTTP/1.0 301 Moved Permanently'). Problem here:
You must supply a HTTP version (this seems to be a problem in Apache), and
This is not necessarily a problem with Apache, it is just a problem in
the current implementation as far as I can tell. If the Apache2 SAPI
would not try to change the HTTP version of the Apache request structure
(or only downgrade it, never upgrade it) then no problem would arise.
Therefore I was hoping that this could be treated as a bug fix and be
done in 5.2.3 or even 5.2.2.
- Chris
Uwe Schindler wrote:
What we need is:
- a function to simply set the status code without changing anything other.
There's a (external) function:
http://php.net/manual/en/function.http-send-status.php
...and for the unlucky:
header("Dummy:", true, $status_code);
But if your patch makes sense, I'm all for it! ;)
Regards,
Michael