NSURLRequest:如何处理重定向的帖子?

时间:2012-05-28 10:57:57

标签: ios redirect nsurlrequest

我对NSURLRequest(和伴奏)实现进行了久经考验,这对于GET和给定URL的POST非常有用。

但是,我现在想要移动URL的目标而不更改应用程序使用的URL,所以我打算通过我的DNS提供程序使用webhop重定向。

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

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

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

根据Apple的(handling redirects)文档,

如果委托没有实现连接: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 - '永久移动。

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

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

2 个答案:

答案 0 :(得分:13)

保留原始请求,然后提供您自己的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时,此行为将更好地为您提供服务。

另见:

答案 1 :(得分:1)

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

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

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