В моем программном обеспечении PHP у меня есть функция самообновления, которая отправляет HTTP-запрос с методом POST на определенный URL (в PHP-скрипт). Теперь этот URL-адрес изменился (я переместил скрипт в другой каталог), но чтобы оставаться обратно совместимым, я хочу использовать скрипт по старому URL-адресу, чтобы перенаправить запрос POST в новое место. Я пытался использовать код статуса HTTP 307, но второй раз, когда PHP делает запрос, он меняет метод из POST на GET, хотя он не должен этого делать (по крайней мере, хотя это и есть код 307). Я использую PHP 5.4.29 в Windows 7 как модуль 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. Я делаю свой запрос сам и вручную, хотя мое программное обеспечение и я хочу перенаправить его на новое место. Это не имеет никакого отношения к теме, связанной с безопасностью.
Спецификация W3C HTTP/1.1 для 307 состояний:
Если код статуса 307 принимается в ответ на запрос, отличный от GET или HEAD, пользовательский агент НЕ ДОЛЖЕН автоматически перенаправлять запрос, если он не может быть подтвержден пользователем, поскольку это может изменить условия, в которых был отправлен запрос.
Дело в том, что серверу небезопасно указывать клиенту POST на другой URL-адрес, поскольку это может быть вредоносная попытка заставить клиента отправлять данные где-то, чего пользователь не намеревался, поэтому перенаправления POST невозможны.
Похоже, что file_get_contents
не передает данные, возможно, по причине, выделенной @daiscog.
Curl, однако, отправит перенаправленный URL:
$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);
Однако было бы разумнее либо обрабатывать это на уровне сервера (например, переписывать URL-адрес Apache), либо просто включать новый файл в старый:
//old.php
include('path/to/new.php');
"include only works locally"
почему это проблема? Старый URL находится на другом сервере, чем новый? У меня сложилось впечатление, что вы просто изменили URL-адрес обновления на одном сайте, поэтому old.php
и new.php
будут находиться на одном сервере