Skip to content

Commit c7ead31

Browse files
committed
Add http_(get|clear)_last_reponse_headers() functions
This is to provide an alternative to the $http_response_header magic variable
1 parent 48ebe58 commit c7ead31

15 files changed

+202
-1
lines changed

ext/standard/basic_functions.c

+6
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,9 @@ PHP_RINIT_FUNCTION(basic) /* {{{ */
419419
BASIC_RINIT_SUBMODULE(dir)
420420
BASIC_RINIT_SUBMODULE(url_scanner_ex)
421421

422+
/* Initialize memory for last http headers */
423+
ZVAL_UNDEF(&BG(last_http_headers));
424+
422425
/* Setup default context */
423426
FG(default_context) = NULL;
424427

@@ -483,6 +486,9 @@ PHP_RSHUTDOWN_FUNCTION(basic) /* {{{ */
483486
BASIC_RSHUTDOWN_SUBMODULE(user_filters)
484487
BASIC_RSHUTDOWN_SUBMODULE(browscap)
485488

489+
/* Free last http headers */
490+
zval_ptr_dtor(&BG(last_http_headers));
491+
486492
BG(page_uid) = -1;
487493
BG(page_gid) = -1;
488494
return SUCCESS;

ext/standard/basic_functions.h

+3
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ typedef struct _php_basic_globals {
7373

7474
zval active_ini_file_section;
7575

76+
/* http_fopen_wrapper.c */
77+
zval last_http_headers;
78+
7679
/* pageinfo.c */
7780
zend_long page_uid;
7881
zend_long page_gid;

ext/standard/basic_functions.stub.php

+4
Original file line numberDiff line numberDiff line change
@@ -2991,6 +2991,10 @@ function pfsockopen(string $hostname, int $port = -1, &$error_code = null, &$err
29912991
/** @refcount 1 */
29922992
function http_build_query(array|object $data, string $numeric_prefix = "", ?string $arg_separator = null, int $encoding_type = PHP_QUERY_RFC1738): string {}
29932993

2994+
function http_get_last_response_headers(): ?array {}
2995+
2996+
function http_clear_last_response_headers(): void {}
2997+
29942998
/* image.c */
29952999

29963000
/**

ext/standard/basic_functions_arginfo.h

+9-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/standard/http.c

+18
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "php_http.h"
1818
#include "php_ini.h"
1919
#include "url.h"
20+
#include "basic_functions.h"
2021

2122
static void php_url_encode_scalar(zval *scalar, smart_str *form_str,
2223
int encoding_type, zend_ulong index_int,
@@ -235,3 +236,20 @@ PHP_FUNCTION(http_build_query)
235236
RETURN_STR(smart_str_extract(&formstr));
236237
}
237238
/* }}} */
239+
240+
PHP_FUNCTION(http_get_last_response_headers)
241+
{
242+
zend_parse_parameters_none();
243+
244+
if (!Z_ISUNDEF(BG(last_http_headers))) {
245+
ZVAL_COPY(return_value, &BG(last_http_headers));
246+
}
247+
}
248+
249+
PHP_FUNCTION(http_clear_last_response_headers)
250+
{
251+
zend_parse_parameters_none();
252+
253+
zval_ptr_dtor(&BG(last_http_headers));
254+
ZVAL_UNDEF(&BG(last_http_headers));
255+
}

ext/standard/http_fopen_wrapper.c

+6
Original file line numberDiff line numberDiff line change
@@ -982,13 +982,19 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, const char *pa
982982
{
983983
php_stream *stream;
984984
zval headers;
985+
985986
ZVAL_UNDEF(&headers);
986987

988+
zval_ptr_dtor(&BG(last_http_headers));
989+
ZVAL_UNDEF(&BG(last_http_headers));
990+
987991
stream = php_stream_url_wrap_http_ex(
988992
wrapper, path, mode, options, opened_path, context,
989993
PHP_URL_REDIRECT_MAX, HTTP_WRAPPER_HEADER_INIT, &headers STREAMS_CC);
990994

991995
if (!Z_ISUNDEF(headers)) {
996+
ZVAL_COPY(&BG(last_http_headers), &headers);
997+
992998
if (FAILURE == zend_set_local_var_str(
993999
"http_response_header", sizeof("http_response_header")-1, &headers, 0)) {
9941000
zval_ptr_dtor(&headers);

ext/standard/tests/http/bug75535.phpt

+10
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,27 @@ $responses = array(
1414

1515
['pid' => $pid, 'uri' => $uri] = http_server($responses, $output);
1616

17+
var_dump(http_get_last_response_headers());
18+
1719
var_dump(file_get_contents($uri));
1820
var_dump($http_response_header);
21+
var_dump(http_get_last_response_headers());
1922

2023
http_server_kill($pid);
2124

2225
?>
2326
--EXPECT--
27+
NULL
2428
string(0) ""
2529
array(2) {
2630
[0]=>
2731
string(15) "HTTP/1.0 200 Ok"
2832
[1]=>
2933
string(14) "Content-Length"
3034
}
35+
array(2) {
36+
[0]=>
37+
string(15) "HTTP/1.0 200 Ok"
38+
[1]=>
39+
string(14) "Content-Length"
40+
}

ext/standard/tests/http/bug80838.phpt

+12
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,26 @@ $options = [
2323

2424
$ctx = stream_context_create($options);
2525

26+
var_dump(http_get_last_response_headers());
27+
2628
$fd = fopen($uri, 'rb', false, $ctx);
2729
fclose($fd);
2830
var_dump($http_response_header);
31+
var_dump(http_get_last_response_headers());
2932

3033
http_server_kill($pid);
3134

3235
?>
3336
--EXPECT--
37+
NULL
38+
array(3) {
39+
[0]=>
40+
string(32) "HTTP/1.1 101 Switching Protocols"
41+
[1]=>
42+
string(15) "Header1: Value1"
43+
[2]=>
44+
string(15) "Header2: Value2"
45+
}
3446
array(3) {
3547
[0]=>
3648
string(32) "HTTP/1.1 101 Switching Protocols"

ext/standard/tests/http/gh9316.phpt

+31
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,52 @@ $responses = array(
1616
['pid' => $pid, 'uri' => $uri] = http_server($responses, $output);
1717

1818
for ($i = 0; $i < count($responses); ++$i) {
19+
echo 'http_get_last_response_headers() before stream layer call:', PHP_EOL;
20+
var_dump(http_get_last_response_headers());
21+
1922
$f = @fopen($uri, "r");
23+
echo '$http_response_header', PHP_EOL;
2024
var_dump($http_response_header);
25+
echo 'http_get_last_response_headers() after stream layer call:', PHP_EOL;
26+
var_dump(http_get_last_response_headers());
2127
fclose($f);
2228
}
2329

2430
http_server_kill($pid);
2531

2632
?>
2733
--EXPECT--
34+
http_get_last_response_headers() before stream layer call:
35+
NULL
36+
$http_response_header
37+
array(2) {
38+
[0]=>
39+
string(126) "HTTP/1.1 200 Some very long reason-phrase to test that this is properly handled by our code without adding a new header like "
40+
[1]=>
41+
string(12) "Good: Header"
42+
}
43+
http_get_last_response_headers() after stream layer call:
2844
array(2) {
2945
[0]=>
3046
string(126) "HTTP/1.1 200 Some very long reason-phrase to test that this is properly handled by our code without adding a new header like "
3147
[1]=>
3248
string(12) "Good: Header"
3349
}
50+
http_get_last_response_headers() before stream layer call:
51+
array(2) {
52+
[0]=>
53+
string(126) "HTTP/1.1 200 Some very long reason-phrase to test that this is properly handled by our code without adding a new header like "
54+
[1]=>
55+
string(12) "Good: Header"
56+
}
57+
$http_response_header
58+
array(2) {
59+
[0]=>
60+
string(13) "HTTP/1.1 200 "
61+
[1]=>
62+
string(12) "Good: Header"
63+
}
64+
http_get_last_response_headers() after stream layer call:
3465
array(2) {
3566
[0]=>
3667
string(13) "HTTP/1.1 200 "
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
Verify that http_clear_last_response_headers() clears the headers.
3+
--SKIPIF--
4+
<?php require 'server.inc'; http_server_skipif(); ?>
5+
--INI--
6+
allow_url_fopen=1
7+
--FILE--
8+
<?php
9+
require 'server.inc';
10+
11+
$responses = array(
12+
"data://text/plain,HTTP/1.0 200 Ok\r\nSome: Header\r\nSome: Header\r\n\r\nBody",
13+
);
14+
15+
['pid' => $pid, 'uri' => $uri] = http_server($responses, $output);
16+
17+
$f = file_get_contents($uri);
18+
var_dump($f);
19+
var_dump(http_get_last_response_headers());
20+
21+
// Clear headers
22+
http_clear_last_response_headers();
23+
var_dump(http_get_last_response_headers());
24+
25+
http_server_kill($pid);
26+
27+
?>
28+
--EXPECT--
29+
string(4) "Body"
30+
array(3) {
31+
[0]=>
32+
string(15) "HTTP/1.0 200 Ok"
33+
[1]=>
34+
string(12) "Some: Header"
35+
[2]=>
36+
string(12) "Some: Header"
37+
}
38+
NULL

ext/standard/tests/http/http_response_header_01.phpt

+12
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,18 @@ $responses = array(
1414

1515
['pid' => $pid, 'uri' => $uri] = http_server($responses, $output);
1616

17+
var_dump(http_get_last_response_headers());
18+
1719
$f = file_get_contents($uri);
1820
var_dump($f);
1921
var_dump($http_response_header);
22+
var_dump(http_get_last_response_headers());
2023

2124
http_server_kill($pid);
2225

2326
?>
2427
--EXPECT--
28+
NULL
2529
string(4) "Body"
2630
array(3) {
2731
[0]=>
@@ -31,3 +35,11 @@ array(3) {
3135
[2]=>
3236
string(12) "Some: Header"
3337
}
38+
array(3) {
39+
[0]=>
40+
string(15) "HTTP/1.0 200 Ok"
41+
[1]=>
42+
string(12) "Some: Header"
43+
[2]=>
44+
string(12) "Some: Header"
45+
}

ext/standard/tests/http/http_response_header_02.phpt

+16
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,18 @@ $responses = array(
1616

1717
['pid' => $pid, 'uri' => $uri] = http_server($responses, $output);
1818

19+
var_dump(http_get_last_response_headers());
20+
1921
$f = file_get_contents($uri);
2022
var_dump($f);
2123
var_dump($http_response_header);
24+
var_dump(http_get_last_response_headers());
2225

2326
http_server_kill($pid);
2427

2528
?>
2629
--EXPECT--
30+
NULL
2731
string(4) "Body"
2832
array(5) {
2933
[0]=>
@@ -37,3 +41,15 @@ array(5) {
3741
[4]=>
3842
string(12) "Some: Header"
3943
}
44+
array(5) {
45+
[0]=>
46+
string(18) "HTTP/1.0 302 Found"
47+
[1]=>
48+
string(12) "Some: Header"
49+
[2]=>
50+
string(20) "Location: /try-again"
51+
[3]=>
52+
string(15) "HTTP/1.0 200 Ok"
53+
[4]=>
54+
string(12) "Some: Header"
55+
}

ext/standard/tests/http/http_response_header_03.phpt

+17
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,19 @@ $responses = array(
1616

1717
['pid' => $pid, 'uri' => $uri] = http_server($responses, $output);
1818

19+
var_dump(http_get_last_response_headers());
20+
1921
$f = file_get_contents($uri);
2022
var_dump($f);
2123
var_dump($http_response_header);
24+
var_dump(http_get_last_response_headers());
2225

2326
http_server_kill($pid);
2427

2528
?>
2629
--EXPECTF--
30+
NULL
31+
2732
Warning: file_get_contents(http://%s:%d): Failed to open stream: HTTP request failed! HTTP/1.0 404 Not Found%a
2833
bool(false)
2934
array(5) {
@@ -38,3 +43,15 @@ array(5) {
3843
[4]=>
3944
string(12) "Some: Header"
4045
}
46+
array(5) {
47+
[0]=>
48+
string(18) "HTTP/1.0 302 Found"
49+
[1]=>
50+
string(12) "Some: Header"
51+
[2]=>
52+
string(20) "Location: /try-again"
53+
[3]=>
54+
string(22) "HTTP/1.0 404 Not Found"
55+
[4]=>
56+
string(12) "Some: Header"
57+
}

0 commit comments

Comments
 (0)