【问题标题】:NSURLRequest: How to handle a redirected post?NSURLRequest:如何处理重定向的帖子?
【发布时间】:2012-06-02 18:04:13
【问题描述】:

我已经对 NSURLRequest(和伴奏)实现进行了尝试和测试,这对于给定 URL 的 GET 和 POST 非常有效。

但是,我现在想在不更改应用使用的 URL 的情况下移动 URL 的目标,因此我打算通过我的 DNS 提供商使用 webhop 重定向。

这适用于 GET 请求,但 POST 只是挂起...没有收到连接响应。

处理重定向的相关iOS方法是,

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

根据 Apple 的 (handling redirects) 文档,

如果委托未实现 connection:willSendRequest:redirectResponse:,则允许所有规范更改和服务器重定向。

嗯,这不是我的经验,因为不使用这种方法对我不起作用。请求只是挂起而没有响应。

Apple 还建议了 willSendRequest 的实现(请参阅上面链接的 Apple 文档),这对我也不起作用。我看到了调用,但结果请求只是挂起。

我当前的 willSendRequest 实现如下(见下文)。这遵循重定向,但处理请求就像它是一个 GET,而不是一个 POST。

我认为问题在于重定向丢失了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提取header字段,看到他原来提交的请求有header

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";
}

...看起来不像原始请求的副本,甚至不是超集。

【问题讨论】:

    标签: ios redirect nsurlrequest


    【解决方案1】:

    保留您的原始请求,然后提供您自己的willSendRequest:redirectResponse: 来自定义请求,而不是使用 Apple 为您提供的请求。

    - (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 时,这种行为会更好地为您服务。

    另见:

    【讨论】:

    • 嗯,我想你可能是对的。我有很多重叠的请求,所以这需要一些排序(和测试),但我认为这是要走的路。谢谢史蒂文。
    • 是的,快速测试表明此解决方案有效。谢谢大家!
    • 可能能从connection得到原始请求,我不记得了。不过值得一看。
    • 这个方法在 iOS 4.3 之后被指定为弃用。 bit.ly/RqbRn5 那可以实现吗? (我确实尝试过这个解决方案并且它有效!)
    • originalRequest 应重命名为 request 以通过复制和粘贴来使用此示例。苹果也提供了很好的解释Apple Developer
    【解决方案2】:

    处理 3xx 类状态码的 HTTP 规范对 GET 和 HEAD 以外的协议非常不友好。它期望在重定向的中间步骤进行某种用户交互,这导致了大量不兼容的客户端和服务器实现,以及让 Web 服务开发人员非常头疼的问题。

    从 iOS NSURL 的角度来看,您可能想要验证的一件事是原始 POST 正文是否包含在新的重定向请求中。

    根据您对我原始答案的 cmets 以及对您问题的修改,您尝试访问的 URL 似乎已永久更新(301 状态代码)。在这种情况下,您实际上可以通过使用新 URL 完全避免重定向。

    【讨论】:

    • 感谢您的回复,但恐怕不是这样。实际上,“请求”包含重定向的 URL(正如我之前的 NSLog 所证实的那样)。我也觉得这违反直觉,但事实就是如此。
    • 那很奇怪。如果是这样的话,你不应该克隆和(重新)发送请求。你还在坚持使用 NSURL 类吗?
    • 我觉得我被 NSURL 卡住了,有更好的选择吗?
    • 你可以试试 MKNetworkingKit。同时,您能否运行您的代码并在问题中添加您获得的确切 HTTP 状态代码?
    • 感谢您回到这里并尝试提供帮助。我在原始问题下方添加了一些额外信息。
    猜你喜欢
    • 2011-03-16
    • 1970-01-01
    • 2011-03-02
    • 1970-01-01
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-30
    相关资源
    最近更新 更多