In my iOS app, I'm using a UIWebView and a custom protocol (with my own NSURLProtocol implementation). I've been fairly careful about making sure that whenever I load a url, I load something like this into my UIWebView:
myprotocol://myserver/mypath
and in my NSURLProtocol implementation, I take a mutable copy of the NSURLRequest, convert the URL to http: and send that to my server.
Everything works for HTTP GET requests. The problem I encounter is with POST requests. It seems like the UIWebView doesn't properly encode the form data in the HTTPBody if the request uses my custom protocol.
One work-around, since I'm using HTTPS for my server requests, is that I register my protocol handler to intercept http: instead of myprotocol: and I can convert all calls to https: This other question, here, pointed me toward that solution:
But I'm wondering if there's any alternative and/or better way of accomplishing what I want.
Instead of trying to use POST requests, one work around is to continue using GET requests for
myprotocol://
URLs, but transform them in yourNSURLProtocol
implementation to anhttp://
and POST request to your server using the request query string as the body of the POST.The worry with using GET requests to send large amounts of data is that somewhere along the request chain, the request line might get truncated. This appears to not be a problem, however, with locally-implemented protocols.
I wrote a short Cordova test app to experiment and I found that I was able to send through a little over 1 MiB of data without trouble to the HTTP request echoing service http://http-echo.jgate.de/
Here is my
startLoading
implementation:I then implemented the
NSURLConnection
protocol methods to forward to the appropriateNSURLProtocolClient
method, but building up the response data in the case ofTransfer-Encoding:chunked
(as is the case for responses from http://http-echo.jgate.de/).Unfortunately it looks like that
http:
andhttps:
scheme requests are handled slightly differently than other (including custom) schemes by Foundation Framework. ObviouslyHTTPBody
andHTTPBodyStream
calls on relevantNSURLRequest
returns alwaysnil
for former ones. This is decided already prior call of[NSURLProtocol canInitWithRequest]
therefore customNSURLProtocol
implementation has no way of influencing that (it is too late).It seems that different
NSURLRequest
class is used forhttp:
andhttps:
than 'a default one'. Default GnuStep implementation of this class returns alwaysnil
fromHTTPBody
andHTTPBodyStream
calls. Therefore particular implementations (e.g. one under PhoneGap, likely part of Foundation Framework) chooseNSURLRequest
-type of class based on scheme prior consulting that withNSURLProtocol
. For custom schemes, you getNSURLRequest
that returnsnil
for bothHTTPBody
andHTTPBodyStream
which effectively disables use of POST method (and other methods with body) in custom URI scheme handler.Maybe there is a way how to influence decision of which
NSURLRequest
class is actually used but it is currently unknown to me.As a workaround, you can still use
http:
orhttps:
scheme and decide in[NSURLProtocol canInitWithRequest]
based on other criteria (e.g. host name).