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

时间:2012-02-15 21:21:52

标签: iphone ios uiwebview nsurlprotocol

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

myprotocol:// MYSERVER / mypath中

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

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

因为我使用HTTPS来处理我的服务器请求,所以我注册了我的协议处理程序以拦截http:而不是myprotocol:我可以将所有调用转换为https:另一个问题,{{3 ,指出我的解决方案:

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

2 个答案:

答案 0 :(得分:6)

不是尝试使用POST请求,而是继续使用myprotocol://网址的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的情况下构建响应数据(就像来自{的响应一样) {3}})。

答案 1 :(得分:4)

不幸的是,http:https:方案请求的处理方式与Foundation Framework的其他(包括自定义)方案略有不同。显然HTTPBodyHTTPBodyStream对相关NSURLRequest的调用始终为nil。这是在事先调用[NSURLProtocol canInitWithRequest]时决定的,因此自定义NSURLProtocol实现无法影响(为时已晚)。

似乎NSURLRequesthttp:使用的不同https:类比'默认值'。此类的默认GnuStep实现从nilHTTPBody调用返回始终 HTTPBodyStream。因此,特定的实现(例如PhoneGap下的一个,可能是Foundation Framework的一部分)选择NSURLRequest - 基于方案的类型,事先咨询NSURLProtocol。对于自定义方案,NSURLRequestnilHTTPBody返回HTTPBodyStream,这有效地禁用了自定义URI方案处理程序中POST方法(以及其他方法与body)的使用

也许有一种方法可以影响我实际使用NSURLRequest类的决定,但我目前还不知道。

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