11

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

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

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

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

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

根据 Apple 的文档(处理重定向),

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

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

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

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

我认为问题在于重定向丢失了HTTP请求是POST的事实(可能还有更多问题,例如也将请求正文转发?)。

我不确定我应该在这里做什么。因此,任何有关如何正确处理接收重定向的 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

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

也可以看看:

于 2012-05-28T15:37:10.760 回答
1

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

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

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

于 2012-05-28T11:24:19.987 回答