NSURLRequest:如何处理redirect的post?

我有一个久经考验的使用NSURLRequest(和伴奏)的实现,这对于GETs很有效,而POSTs则是给定的URL。

不过,我现在想移动URL的目标,而不更改应用程序使用的URL,所以我打算通过我的DNS提供商使用networkingredirect。

这对GET请求正常工作,但POST只是挂起…没有连接响应收到。

处理redirect的相关iOS方法是,

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

根据苹果的文档( 处理redirect ),

如果委托没有实现连接:willSendRequest:redirectResponse :,所有规范的更改和服务器redirect都是允许的。

那么,这不是我的经验,因为离开这个方法不适合我。 请求只是挂起而没有回应。

苹果还build议实施willSendRequest(请参阅上面的链接苹果文档),这再也不适用于我。 我看到了调用,但结果请求只是挂起。

我目前的willSendRequest实现如下(见下文)。 这遵循redirect,但是将请求处理为GET,而不是POST。

我相信问题是redirect正在失去HTTP请求是一个POST的事实(可能还有更多的问题,比如向前移动请求Body?)。

我不确定我应该在这里做什么。 所以任何关于如何正确处理接收redirect的POST的build议将不胜感激。 谢谢。

 -(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 – “永久移动”。

使用所有的HTTPHeaderFields来提取头字段,我看到他请求我原来提交的头

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

…和复制/redirect的请求具有标题,

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

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

保留原始请求,然后提供自己的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规范的某些方面:redirect通常应该变成GET请求(取决于HTTP状态码)。 但是在实践中,这个行为会在从iOS应用程序发布时更好地为您服务。

也可以看看:

  • iOS开发库,URL加载系统编程指南:处理redirect和其他请求更改

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

从iOS NSURL的angular度来看,您可能需要validation的一件事是原始的POST正文包含在新的redirect请求中。

根据您对我的原始答案的评论以及对您的问题的编辑,看起来您尝试访问的URL已经被永久更新(301状态码)。 在这种情况下,您可以通过使用新的URL实际上避免redirect。