使用代码307的PHP重定向将方法从POST更改为GET

时间:2015-11-19 11:25:34

标签: php redirect post

在我的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。我自己通过我的软件手动提出请求,我想将其重定向到新位置。这与安全相关的主题无关。

2 个答案:

答案 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');