11

私は、特定の URL の GET および POST に最適な NSURLRequest (および付随するもの) 実装を試行錯誤して使用しています。

ただし、アプリが使用する URL を変更せずに URL のターゲットを移動したいので、DNS プロバイダー経由で Web ホップ リダイレクトを使用するつもりです。

これは GET リクエストに対しては正常に機能しますが、POST はハングするだけです...接続応答が受信されません。

リダイレクトを処理するための関連する iOS メソッドは、

-(NSURLRequest *)connection:(NSURLConnection *)connection
    willSendRequest:(NSURLRequest *)request
    redirectResponse:(NSURLResponse *)redirectResponse

(リダイレクトの処理)に関する Apple のドキュメントによると、

デリゲートが connection:willSendRequest:redirectResponse: を実装していない場合、すべての正規の変更とサーバー リダイレクトが許可されます。

このメソッドを除外してもうまくいかないので、それは私の経験ではありません。リクエストは応答なしでハングします。

Apple はまた、willSendRequest の実装を提案しています (上記のリンクされた Apple のドキュメントを参照)。呼び出しは表示されますが、結果のリクエストはハングします。

willSendRequest の現在の実装は次のとおりです (以下を参照)。これはリダイレクトに従いますが、 はリクエストを POST ではなく GET であるかのように処理します。

問題は、HTTP リクエストが POST であるという事実がリダイレクトによって失われていることだと思います (リクエスト Body も転送するなど、さらに問題がある可能性があります)。

ここで何をすべきかわかりません。したがって、リダイレクトを受け取る POST を正しく処理する方法についてのアドバイスをいただければ幸いです。ありがとう。

-(NSURLRequest *)connection:(NSURLConnection *)connection
   willSendRequest:(NSURLRequest *)request
  redirectResponse:(NSURLResponse *)redirectResponse
{

    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) redirectResponse;

    int statusCode = [httpResponse statusCode];


    NSLog (@"HTTP status %d", statusCode);

    // http statuscodes between 300 & 400 is a redirect ...
    if (httpResponse && statusCode >= 300 && statusCode < 400)
    {
        NSLog(@"willSendRequest (from %@ to %@)", redirectResponse.URL, request.URL);
    }

    if (redirectResponse)
    {
        NSMutableURLRequest *newRequest = [request mutableCopy]; // original request

       [newRequest setURL: [request URL]];

       NSLog (@"redirected");

       return newRequest;
    }
    else
    {
        NSLog (@"original");

       return request;
    }
}

追加情報 1

willSendRequest が受け取る HTTP コードは 301 - 'Moved Permanently.

allHTTPHeaderFields を使用してヘッダー フィールドを抽出すると、最初に送信したリクエストにヘッダーがあることがわかります

HTTP header {
  "Content-Length" = 244;
  "Content-Type" = "application/json";
}

...そして、コピー/リダイレクトされたリクエストにはヘッダーがあり、

Redirect HTTP header {
  Accept = "*/*";
  "Accept-Encoding" = "gzip, deflate";
  "Accept-Language" = "en-us";
  "Content-Type" = "application/json";
}

...元のリクエストのコピーやスーパーセットのようには見えません。

4

2 に答える 2

13

Appleが提供するものを使用するのではなく、元の要求を保持してから、そのwillSendRequest:redirectResponse:要求をカスタマイズするために独自の要求を提供します。

- (NSURLRequest *)connection: (NSURLConnection *)connection
             willSendRequest: (NSURLRequest *)request
            redirectResponse: (NSURLResponse *)redirectResponse;
{
    if (redirectResponse) {
        // The request you initialized the connection with should be kept as
        // _originalRequest.
        // Instead of trying to merge the pieces of _originalRequest into Cocoa
        // touch's proposed redirect request, we make a mutable copy of the
        // original request, change the URL to match that of the proposed
        // request, and return it as the request to use.
        //
        NSMutableURLRequest *r = [_originalRequest mutableCopy];
        [r setURL: [request URL]];
        return r;
    } else {
        return request;
    }
}

これを行うことで、HTTP仕様のいくつかの側面を明示的に無視することになります。リダイレクトは通常、GETリクエストに変換する必要があります(HTTPステータスコードによって異なります)。ただし、実際には、この動作はiOSアプリケーションからPOSTする場合に役立ちます。

参照:

于 2012-05-28T15:37:10.760 に答える
1

3xxクラスのステータスコードを処理するためのHTTP仕様は、GETおよびHEAD以外のプロトコルに対しては非常に不利です。リダイレクトの中間ステップでのある種のユーザーインタラクションが予想されます。これにより、互換性のないクライアントとサーバーの実装が大量に発生し、Webサービス開発者にとって深刻な頭痛の種になります。

iOS NSURLの観点から、確認したいことの1つは、元のPOST本文が新しいリダイレクト要求に含まれていることです。

私の元の回答に対するあなたのコメントとあなたの質問への編集に基づいて、あなたがアクセスしようとしているURLは永久に更新されているように見えます(301ステータスコード)。この場合、新しいURLを使用することで、実際にリダイレクトを完全に回避できます。

于 2012-05-28T11:24:19.987 に答える