在我的PHP软件中,我有一个自我更新功能,它使用POST方法将HTTP请求发送到某个URL(到PHP脚本)。现在这个URL已经更改(我将脚本移动到另一个目录),但为了保持向后兼容,我想使用旧URL处的脚本将POST请求重定向到新位置。我尝试使用HTTP 307状态代码,但PHP第二次发出请求,它将方法从POST更改为GET,尽管它不能这样做(至少我虽然这是307代码的用途)。我在Windows 7上使用PHP 5.4.29作为Apache(2.2.27)模块,我嗅探流量以确保在请求和响应中使用HTTP 1.1。
这是我发布POST请求的方式:
<?php
$requestData = http_build_query(
array(
"param1" => "value1",
// and so on...
)
);
$requestOptions = array("http"=>
array
(
"protocol_version"=>"1.1",
"method"=>"POST",
"header"=>array(
"Content-type: application/x-www-form-urlencoded",
"Connection: close",
),
"content"=>$requestData,
)
);
$requestContext = stream_context_create($requestOptions);
$serverResponse = @file_get_contents("http://localhost/old/long/path/update.php", false, $requestContext);
?>
我尝试通过PHP手动和自动重定向:
<?php
// Redirect manually
header("HTTP/1.1 307 Temporary Redirect");
header("Location: http://localhost/update.php");
// or redirect automatically
header("Location: http://localhost/update.php", true, 307);
?>
根据嗅探的数据,一切看起来都很正常。 HTTP 1.1用于请求和响应,并使用代码307。但是第二次PHP发送请求(到新位置,仍然使用HTTP 1.1,..)它只是将方法更改为GET并且我的POST有效负载丢失。
再次:这不是用户/浏览器重定向 - 我重定向PHP。我自己通过我的软件手动提出请求,我想将其重定向到新位置。这与安全相关的主题无关。
答案 0 :(得分:0)
307州的W3C HTTP/1.1 specification:
如果收到307状态代码以响应除以外的请求 GET或HEAD,用户代理不得自动重定向 除非可以由用户确认,否则请求,因为这可能 改变发出请求的条件。
这背后的一点是,服务器告诉客户端POST到不同的URL是不安全的,因为这可能是恶意企图让客户端在用户不想要的地方发送数据,因此POST重定向是不可能。
答案 1 :(得分:0)
看起来file_get_contents
没有重新发布数据,可能出于@daiscog强调的原因。
然而,Curl将重新发布到重定向的网址:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://localhost/old/long/path/update.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $requestData);
$serverResponse = curl_exec($ch);
然而,在服务器级别处理此问题(例如,Apache url重写)或者只是将新文件包含在旧文件中会更有意义:
//old.php
include('path/to/new.php');