使用带有UIWebView和POST请求的自定义NSURLProtocol

在我的iOS应用程序中,我使用的是UIWebView和自定义协议(使用我自己的NSURLProtocol实现)。 我一直非常小心确保每当我加载一个url时,我将这样的内容加载到我的UIWebView中:

myprotocol:// MYSERVER / mypath中

在我的NSURLProtocol实现中,我获取NSURLRequest的可变副本,将URL转换为http:并将其发送到我的服务器。

一切都适用于HTTP GET请求。 我遇到的问题是POST请求。 如果请求使用我的自定义协议,似乎UIWebView不能正确编码HTTPBody中的表单数据。

一个解决方法,因为我使用HTTPS来处理我的服务器请求,就是我注册我的协议处理程序来拦截http:而不是myprotocol:我可以将所有调用转换为https:这个其他问题, 在这里 ,我指向了解:

但我想知道是否有任何替代和/或更好的方式来实现我想要的东西。

不是试图使用POST请求,而是继续使用myprotocol:// URL的GET请求,但是使用请求查询字符串将NSURLProtocol实现中的它们转换为http:// POST请求到服务器POST的主体。

使用GET请求发送大量数据的担忧是在请求链的某个地方,请求行可能会被截断。 然而,这似乎不是一个问题,使用本地实现的协议。

我写了一个简短的Cordova测试应用程序进行实验,我发现我能够毫不费力地向HTTP请求回送服务发送超过1 MiB的数据http://http-echo.jgate.de/

这是我的startLoading实现:

 - (void)startLoading { NSURL *url = [[self request] URL]; NSString *query = [url query]; // Create a copy of `url` without the query string. url = [[[NSURL alloc] initWithScheme:@"http" host:@"http-echo.jgate.de" path:[url path]] autorelease]; NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:url]; [newRequest setHTTPMethod:@"POST"]; [newRequest setAllHTTPHeaderFields:[[self request] allHTTPHeaderFields]]; [newRequest addValue:@"close" forHTTPHeaderField:@"Connection"]; [newRequest addValue:@"application/x-www-form-urlencoded;charset=UTF-8" forHTTPHeaderField:@"Content-Type"]; [newRequest setHTTPBody:[query dataUsingEncoding:NSUTF8StringEncoding]]; urlConnection = [[NSURLConnection alloc] initWithRequest:newRequest delegate:self]; if (urlConnection) { receivedData = [[NSMutableData data] retain]; } } 

然后我实现了NSURLConnection协议方法以转发到适当的NSURLProtocolClient方法,但是在Transfer-Encoding:chunked的情况下构建响应数据Transfer-Encoding:chunked (来自http://http-echo.jgate.de/的响应的情况) )。

不幸的是,看起来http:https: scheme请求的处理方式与Foundation Framework的其他(包括自定义)方案略有不同。 显然,相关NSURLRequest上的HTTPBodyHTTPBodyStream调用对于前者来说总是返回nil 。 这是先前调用[NSURLProtocol canInitWithRequest]决定的,因此自定义NSURLProtocol实现无法影响它(为时已晚)。

似乎不同的NSURLRequest类用于http:https:不是’默认值’。 此类的默认GnuStep实现始终HTTPBodyHTTPBodyStream调用返回nil 。 因此,特定的实现(例如PhoneGap下的一个,可能是Foundation Framework的一部分)根据NSURLProtocol方案事先咨询选择NSURLRequest类的类。 对于自定义方案,您将获得NSURLRequest ,它为HTTPBodyHTTPBodyStream返回nil ,这有效地禁用了在自定义URI方案处理程序中使用POST方法(以及使用body的其他方法)。

也许有一种方法如何影响实际使用哪个NSURLRequest类的决定,但目前我不知道。

作为解决方法,您仍然可以使用http:https: scheme并根据其他条件(例如主机名)决定[NSURLProtocol canInitWithRequest]