Bugs php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login

go to bug id or search bugs for

Bug #79718 header_register_callback behaves differently for requests with no output
Submitted: 2020年06月19日 17:48 UTC Modified: 2020年06月19日 18:04 UTC
Votes:2
Avg. Score:4.0 ± 1.0
Reproduced:2 of 2 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (50.0%)
From: brianlmoon@php.net Assigned:
Status: Open Package: Output Control
PHP Version: 7.4.7 OS: Linux
Private report: No CVE-ID: None
[2020年06月19日 17:48 UTC] brianlmoon@php.net
Description:
------------
When a request has no output (a redirect or 204 no content for example), or the request method is HEAD (even if the request would have generated output normally), autoloading inside the callback provided to header_register_callback fails. For requests with output, autoloading works as expected. 
Test script:
---------------
<?php
error_reporting(-1);
ini_set("display_errors", true);
header("Location: /foo");
header("X-Bar: 2");
spl_autoload_register(function($class) {
 include __DIR__."/Foo.php";
});
header_register_callback(function() {
 header("X-Baz: 3");
 header("X-Foo: ".Foo::BAR);
});
if(!empty($_GET["output"])) {
 echo "test";
}
/* Foo.php
<?php
class Foo {
 const BAR = 1;
}
*/
Expected result:
----------------
The following headers are returned for all requests regardless if there is output or not.
X-Bar: 2
X-Baz: 3
X-Foo: 1
For example, with output: 
< HTTP/1.1 302 Found
< Server: nginx/1.17.10
< Date: 2020年6月19日 17:45:39 GMT
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Location: /foo
< X-Bar: 2
< X-Baz: 3
< X-Foo: 1
< Strict-Transport-Security: max-age=31536000; includeSubdomains
< 
* Connection #0 to host labs.moonspot.net left intact
test
Actual result:
--------------
< HTTP/1.1 302 Found
< Server: nginx/1.17.10
< Date: 2020年6月19日 17:46:28 GMT
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Location: /foo
< X-Bar: 2
< X-Baz: 3
< Strict-Transport-Security: max-age=31536000; includeSubdomains
< 
<br />
<b>Fatal error</b>: Uncaught Error: Class 'Foo' not found in /xxx/public/test.php:16
Stack trace:
#0 [internal function]: {closure}()
#1 {main}
 thrown in <b>/xxx/public/test.php</b> on line <b>16</b><br />

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
[2020年06月19日 18:04 UTC] requinix@php.net
Given that the callback is running when output is being flushed after script execution and when autoloading is no longer available (?), this makes sense. If there is output then what that means is you started output while the script was still running and thus autoloading was available.
Which leads to an easy solution: have your script flush at the end.
After all, shutdown callbacks happen when the engine is in the process of shutting down, so it's hard to know exactly what capabilities will still be available.
[2020年10月10日 00:02 UTC] gtisza at wikimedia dot org
At a minimum this should be mentioned in the method documentation, it is surprising behavior and invalidates some basic correctness assumptions when one e.g. uses the header callback for fixing certain issues with the headers. By the point where autoloading is unavailable, logging will probably also not be functional, so the operator might never learn about the issue.
FWIW, PHP 8 seems not to have this behavior.
PHP Copyright © 2001-2025 The PHP Group
All rights reserved. Last updated: Thu Oct 16 03:00:01 2025 UTC

AltStyle によって変換されたページ (->オリジナル) /