Bug #73936 [Asn->Fbk]: Certain special header() calls wrongly prevent connection from closing

From: Date: Fri, 05 Nov 2021 19:17:29 +0000
Subject: Bug #73936 [Asn->Fbk]: Certain special header() calls wrongly prevent connection from closing
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-237570@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=73936&edit=1

 ID:                 73936
 Updated by:         cmb@php.net
 Reported by:        markamery at btinternet dot com
 Summary:            Certain special header() calls wrongly prevent
                     connection from closing
-Status:             Assigned
+Status:             Feedback
 Type:               Bug
 Package:            Apache2 related
 Operating System:   Ubuntu
 PHP Version:        Irrelevant
 Assigned To:        cmb
 Block user comment: N
 Private report:     N

 New Comment:

Anyway, I cannot reproduce any difference between the three
scripts with PHP-7.4 on Windows using Apache 2.4.39.0.  The
response always has

    Connection: Keep-Alive
    Keep-Alive: timeout=5, max=100

and the connection is closed after ~ 5 seconds.

If I add

    Connection: close

to the request, the connection is immediately closed after the
response has been received.

So either the issue has been fixed in the meantime, or is specific
to some Apache versions or the operating system.

Can you still reproduce this with any of the actively supported
PHP versions[1]?  If so, what's your Apache version?

[1] <https://www.php.net/supported-versions.php>


Previous Comments:
------------------------------------------------------------------------
[2021-11-05 14:22:56] markamery at btinternet dot com

> > header('http/1.1 200 OK')

> This is not valid according to RFC 7230, since the HTTP-name needs
> to be upper case

It's valid according to PHP's own docs at https://www.php.net/manual/en/function.header.php,
which state that

> There are two special-case header calls. The first is a header that starts with the string
> "HTTP/" (case is not significant) ...

For whatever reason, the design decision has been made by PHP to let you pass such strings in
lowercase and then convert them to uppercase for you to make them spec-compliant. The really
mysterious thing is that invoking that case-conversion behaviour somehow prevents this bug from
exhibiting.

------------------------------------------------------------------------
[2021-11-04 14:03:49] cmb@php.net

> Unless Connection: keep-alive is specified in the request, the
> connection should close once the PHP script finishes.

For HTTP/1.1 requests, keep-alive is the default.  Only HTTP/1.0
defaults to close.[1]

> header('http/1.1 200 OK')

This is not valid according to RFC 7230, since the HTTP-name needs
to be upper case[2].

> http_response_code(200);

I tentatively agree that this should behave identically to
header('HTTP/1.1 200 OK').  I'll' have a closer look.

[1] <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection>
[2] <https://datatracker.ietf.org/doc/html/rfc7230#appendix-B>

------------------------------------------------------------------------
[2017-01-14 18:38:54] markamery at btinternet dot com

Description:
------------
Running under mod_php, calling

    header('HTTP/1.1 200 OK');

seems to prevent the connection from being closed once the PHP script finishes. This can be
demonstrated by, for instance, hitting the script with ab (the Apache benchmark tool), which (unlike
most HTTP clients, including browsers) only considers a request to have finished once the connection
is closed, rather than when Content-Length bytes have been received. http://stackoverflow.com/q/34367115/1709587
describes this case in more detail.

Bizarrely,

    header('http/1.1 200 OK');

does not have the same effect, despite producing a character-for-character identical HTTP response
(as can be observed with curl -i --raw).

Test script:
---------------
<?php

header('HTTP/1.1 200 OK');


Expected result:
----------------
Unless Connection: keep-alive is specified in the request, the connection should close
once the PHP script finishes. In particular, the behaviour should be identical to other calls with
the same meaning, like

    <?php
    
        http_response_code(200);

or

    <?php

        header('http/1.1 200 OK')

Actual result:
--------------
The connection does not close, and the alternate scripts suggested above have different behaviours
to the test script.


------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=73936&edit=1


Thread (6 messages)

« previous php.bugs (#237570) next »