3

curl を使用して post http リクエストを実行し、出力を返すコードがあります。投稿リクエストを行っている Web サイトには、http から https へのリダイレクトがあります。

https ポートへの投稿リクエストを行うと、すべて正常に動作します。http ポートに対して同じ要求を行う (そして https ポートにリダイレクトされる) と、空の文字列が返されます。なぜ機能しないのか、正しく行う方法を誰か教えてください。

投稿リクエストを行う関数:

function curl_query($url, $username, $password, $payload) {
    $additionalHeaders = "";
    $process = curl_init($url);
    curl_setopt($process, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded',$additionalHeaders));
    curl_setopt($process, CURLOPT_HEADER, false);
    curl_setopt($process, CURLOPT_USERPWD, $username . ":" . $password);
    curl_setopt($process, CURLOPT_TIMEOUT, 30);
    curl_setopt($process, CURLOPT_POST, 1);
    curl_setopt($process, CURLOPT_POSTFIELDS, $payload);
    curl_setopt($process, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($process, CURLOPT_MAXREDIRS, 4);
    curl_setopt($process, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($process, CURLOPT_SSL_VERIFYPEER, false);
    $return = curl_exec($process);
    return $return;
}

クエリをポート 80 からポート 443 にリダイレクトする .htaccess エントリ:

RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

更新 いくつかのデバッグの後、最初の POST の後、新しい場所にリダイレクトされた後、curl が GET 要求を送信していることがわかりました。最初の POST を新しい場所に再送信することは可能ですか?

4

2 に答える 2

2

今日同じ問題に遭遇し、最初はcurlのバグだと思いました. しかし、もう少し掘り下げた後、RFC 2616 が POST リクエストのリダイレクトについて次のように述べていることがわかりました。

301 - 恒久的に移動:

GET または HEAD 以外のリクエストへの応答として 301 ステータス コードを受信した場合、ユーザーが確認できない限り、ユーザー エージェントはリクエストを自動的にリダイレクトしてはなりません。これにより、リクエストが発行された条件が変更される可能性があるためです。

注: 301 ステータス コードを受け取った後に POST リクエストを自動的にリダイレクトする場合、一部の既存の HTTP/1.0 ユーザー エージェントはそれを誤って GET リクエストに変更します。


302 - 見つかった: > GET または HEAD 以外のリクエストへの応答として 302 ステータス コードを受信した場合、ユーザー エージェントは、ユーザーが確認できない限り、リクエストを自動的にリダイレクトしてはなりません。要求が出されました。> >> 注: RFC 1945 および RFC 2068 では、クライアントがリダイレクトされた要求のメソッドを変更することは許可されていないと規定されています。ただし、ほとんどの既存のユーザー エージェント実装は、302 を 303 応答であるかのように扱い、元の要求メソッドに関係なく、Location フィールド値に対して GET を実行します。ステータス コード 303 および 307 は、クライアントに期待される反応の種類を明確に明らかにしたいサーバー用に追加されました。
303 - その他を参照: > リクエストへのレスポンスは別の URI で見つけることができ、そのリソースで GET メソッドを使用して取得する必要があります。このメソッドは主に、POST でアクティブ化されたスクリプトの出力がユーザー エージェントを選択したリソースにリダイレクトできるようにするために存在します。新しい URI は、最初に要求されたリソースの代替参照ではありません。
307 - 一時的なリダイレクト > GET または HEAD 以外のリクエストへの応答として 307 ステータス コードを受信した場合、ユーザー エージェントは、ユーザーが確認できない限り、リクエストを自動的にリダイレクトしてはなりません。要求が出されました。
ソース: https://www.rfc-editor.org/rfc/rfc2616#section-10.3.2 (62-65 ページ)

したがって、curl がユーザーに何も尋ねることができないことを知っているので、301 および 302 リダイレクトの場合、POST が GET に変換されるのは合理的と思われます (RFC によれば、これは 100% ではありませんが)。

幸いなことに、curl 7.19.1 (php 5.3.2) 以降、curl にリダイレクト用の POST メソッドを強制的に保持させるオプションがあります。

CURLOPT_POSTERDIR

CURLOPT_FOLLOWLOCATION が設定され、特定のタイプのリダイレクトが発生したときに HTTP POST メソッドを維持する必要がある場合は、1 (301 Moved Permanently)、2 (302 Found)、および 4 (303 See Other) のビットマスク。

http://php.net/manual/en/function.curl-setopt.php

例:

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_POSTREDIR, 7);
$response = curl_exec($ch);
curl_close($ch);
于 2015-07-02T23:05:47.220 に答える