HTTP context 选项 — HTTP context 的选项列表
提供给 http:// 和 https:// 传输协议的 context 选项。
transports.
method
string
远程服务器支持的 GET,POST 或其它 HTTP 方法。
默认值是 GET。
header
array 或 string
请求期间发送的附加 header 。此选项中的值将覆盖其他值
(如 User-agent:, Host: 和
Authentication:),
即使在执行 Location: 重定向时也是如此。
所以,如果启用了 follow_location
就不建议设置 Host: header。
字符串值是以 \r\n 分隔的 Key: value,例如 "Content-Type:
application/json\r\nConnection: close"。数组值应为 Key: value
的列表,例如 ["Content-Type: application/json", "Connection: close"]。
user_agent
string
要发送的 header User-Agent: 的值。如果在上面的
header context 选项中没有指定 user-agent,此值将被使用。
默认使用 php.ini 中设置的 user_agent。
content
string
在 header 后面要发送的额外数据。通常使用POST或PUT请求。
proxy
string
URI 指定的代理服务器的地址(例如:
tcp://proxy.example.com:5100)。
request_fulluri
bool
当设置为 true 时,在构建请求时将使用整个 URI(例如:
GET http://www.example.com/path/to/file.html HTTP/1.0)。
虽然这是一个非标准的请求格式,但某些代理服务器需要它。
默认值是 false .
follow_location
int
跟随 Location header 的重定向。设置为 0 以禁用。
默认值是 1。
max_redirects
int
跟随重定向的最大次数。值为 1 或更少则意味不跟随重定向。
默认值是 20。
protocol_version
float
HTTP 协议版本。
PHP 8.0.0 起默认值是 1.1。在此之前默认值是 1.0。
timeout
float
读取超时时间,单位为秒(s),用 float 指定(例如:10.5)。
默认使用 php.ini 中设置的 default_socket_timeout。
ignore_errors
bool
即使是故障状态码依然获取内容。
默认值为 false .
示例 #1 获取一个页面并发送 POST 数据
<?php
$postdata = http_build_query(
[
'var1' => 'some content',
'var2' => 'doh',
]
);
$opts = [
'http' => [
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $postdata,
]
];
$context = stream_context_create($opts);
$result = file_get_contents('http://example.com/submit.php', false, $context);
?>
示例 #2 忽略重定向并获取 header 和内容
<?php
$url = "http://www.example.org/header.php";
$opts = [
'http' => [
'method' => 'GET',
'max_redirects' => '0',
'ignore_errors' => '1',
]
];
$context = stream_context_create($opts);
$stream = fopen($url, 'r', false, $context);
// header 信息和 stream 的元数据一样
var_dump(stream_get_meta_data($stream));
// $url 的实际数据
var_dump(stream_get_contents($stream));
fclose($stream);
?>注意: 底层 socket stream 上下文选项
底层传输可能支持额外的上下文选项。对于http://流,请参阅tcp://传输的上下文选项。对于https://流,请参阅ssl://传输的上下文选项。
注意: HTTP 状态行
当此流包装器跟随重定向时,stream_get_meta_data() 返回的wrapper_data中索引0处不一定包含实际适用于内容数据的 HTTP 状态行。第一个请求返回array ( 'wrapper_data' => array ( 0 => 'HTTP/1.0 301 Moved Permanently', 1 => 'Cache-Control: no-cache', 2 => 'Connection: close', 3 => 'Location: http://example.com/foo.jpg', 4 => 'HTTP/1.1 200 OK', ...301(永久重定向), 因此 stream 包装器自动跟随重定向到获得200响应(index =4)。
Note that if you set the protocol_version option to 1.1 and the server you are requesting from is configured to use keep-alive connections, the function (fopen, file_get_contents, etc.) will "be slow" and take a long time to complete. This is a feature of the HTTP 1.1 protocol you are unlikely to use with stream contexts in PHP.
Simply add a "Connection: close" header to the request to eliminate the keep-alive timeout:
<?php
// php 5.4 : array syntax and header option with array value
$data = file_get_contents('http://www.example.com/', null, stream_context_create([
'http' => [
'protocol_version' => 1.1,
'header' => [
'Connection: close',
],
],
]));
?>note that for both http and https protocols require the same 'http' context keyword:
<?php
// CORRECT example:
// this will work as expected
// note the url with https but context with http
$correct_data = file_get_contents('https://example.com', false, stream_context_create(array('http' => array(...))));
// INVALID example:
// this will not work, the context will be ignored
// note the url with https also context with https
$correct_data = file_get_contents('https://example.com', false, stream_context_create(array('https' => array(...))));With the default of
'follow_location' => 1
be certain NEVER include a "Host:" header in the 'header' array.
If the host is set to "mydomain.com", and that web site has a (quite common) redirect to "www.mydomain.com", then the initial request to "http://mydomain.com" will get the expected response of:
HTTP/1.1 301 Moved Permanently
Location: http://www.mydomain.com/
However, the follow-up request does NOT replace the original "host" header with the new "location" value, as one would expect. Consequently each "follow-location" request will again be served by the original host of "http://mydomain.com", and continue the redirect loop until 'max_redirects' has been exhausted.
(For details: https://bugs.php.net/bug.php?id=77889)note that both http and https transports require the same context name http
// OK example:
// this will work as expected
// note the url with https but context with http
$correct_data = file_get_contents('https://example.com', false, stream_context_create(array('http' => array(...))));
// INVALID example:
// this will not work, the context will be ignored
// note the url with https also context with https
$correct_data = file_get_contents('https://example.com', false, stream_context_create(array('https' => array(...))));watch your case when using methods (POST and GET)...it must be always uppercase. in case of you write it in lower case it wont work.Note that setting request_fulluri to true will *change* the value of $_SERVER['REQUEST_URI] on the receiving end (from /abc.php to http://domain.com/abc.php).If you want to use Basic Auth while using get_headers(), use stream_context options below.
I am using HEAD method here, but please feel free to use GET also.
<?php
$targetUrl = 'http or https target url here';
$basicAuth = base64_encode('username:password');
stream_context_set_default(
[
'http' => [
'method' => 'HEAD',
'header' => 'Authorization: Basic ' . $basicAuth
]
]
);
$result = get_headers($targetUrl);
print_r($result);If you use the proxy server and encounter an error "fopen(http://example.com): failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request" note that in many situations you need also set the parameter "request_fulluri" to "true" in your stream options. Without this option the php script sends the empty request to the server as "GET / HTTP/0.0" and the proxy server replies to it with the "HTTP 400" error.
For example (working sample):
<?php
$stream = stream_context_create(Array("http" => Array("method" => "GET",
"timeout" => 20,
"header" => "User-agent: Myagent",
"proxy" => "tcp://my-proxy.localnet:3128",
'request_fulluri' => True /* without this option we get an HTTP error! */
)));
if ( $fp = fopen("http://example.com", 'r', false, $stream) ) {
print "well done";
}
?>
P>S> PHP 5.3.17It's worth noting that the `header` array seems to only want an array of strings, not an associative array.
I just spent a chunk of time debugging something not working as expected (no errors though) which was fixed by converting an associative array of headers into a simple array of strings.Remember to match content with Content-type:
<?php
$data = array(
'var1' => 'some content',
'var2' => 'doh'
);
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/json', // here...
'content' => json_encode($data) // and here.
)
);
. . .
?>I had quite a bit of trouble trying to make a request with fopen through a proxy to a secure url. I kept getting a 400 Bad Request back from the remote host. It was receiving the proxy url as the SNI host. In order to get around this I had to explicity set the SNI host to the domain I was trying to reach. It's apparently the issue outlined in this bug:
https://bugs.php.net/bug.php?id=63519
<?php
$domain = parse_url($file, PHP_URL_HOST);
$proxy_string = "tcp://" . WP_PROXY_HOST . ":" . WP_PROXY_PORT;
$opts = array(
'http' => array( 'proxy' => $proxy_string ),
'ssl' => array( 'SNI_enabled' => true, 'SNI_server_name' => $domain));
$context = stream_context_create($opts);
$handle = fopen( $file, 'r', false, $context );
?>If you pass the 'header' option as a string and you have multiple headers, they must be separated by "\r\n".