uiwebviewおよびpostリクエストを使用したカスタムnsurlprotocolを使用します
-
25-10-2019 - |
質問
私のiOSアプリでは、UIWebViewとカスタムプロトコル(独自のNSURLProtoColの実装を使用して)を使用しています。 URLをロードするたびに、このようなものをuiwebviewにロードすることを確認することにかなり注意していました。
myprotocol:// myserver/mypath
また、nsurlprotocolの実装では、nsurlrequestの可変コピーを取り、URLをHTTPに変換し、それをサーバーに送信します。
すべてがHTTP GETリクエストで機能します。私が遭遇する問題は、投稿リクエストです。リクエストがカスタムプロトコルを使用している場合、UIWebViewはHTTPBodyのフォームデータを適切にエンコードしないようです。
サーバーリクエストにHTTPSを使用しているため、1つの回避策は、プロトコルハンドラーを登録してHTTPをインターセプトすることです。MyProtoColの代わりに:すべての呼び出しをHTTPSに変換できます。 ここ, 、私をその解決策に向けました:
しかし、私が望むものを達成するための代替方法と/またはより良い方法があるかどうか疑問に思っています。
解決
POSTリクエストを使用しようとする代わりに、回避策の1つはGet Requestsを使用し続けることです。 myprotocol://
urls、しかしそれらをあなたの中に変換します NSURLProtocol
anへの実装 http://
と リクエストクエリ文字列を投稿の本文として使用して、サーバーにリクエストを投稿します。
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
(からの回答の場合のように http://http-echo.jgate.de/).
他のヒント
残念ながら、それはそのように見えます http:
と https:
スキーム要求は、Foundation Frameworkごとに他の(カスタムを含む)スキームとはわずかに異なって処理されます。明らかに HTTPBody
と HTTPBodyStream
関連する呼び出し NSURLRequest
常に戻ります nil
前者のために。これは、以前のコールのすでに決定されています [NSURLProtocol canInitWithRequest]
したがって、カスタム NSURLProtocol
実装にはそれに影響を与える方法はありません(手遅れです)。
違うようです NSURLRequest
クラスが使用されます http:
と https:
「デフォルトのもの」よりも。このクラスのデフォルトのGNUSTEP実装は返されます いつも nil
から HTTPBody
と HTTPBodyStream
電話。したがって、特定の実装(たとえば、PhoneGapの1つ、おそらく基礎フレームワークの一部)を選択します NSURLRequest
- スキームに基づくクラスのタイプは、 NSURLProtocol
. 。カスタムスキームの場合、あなたは取得します NSURLRequest
それは戻ります nil
両方のための HTTPBody
と HTTPBodyStream
カスタムURIスキームハンドラーでのPOSTメソッド(およびその他のメソッド)の使用を効果的に無効にします。
たぶん、どちらの決定に影響を与える方法があります NSURLRequest
クラスは実際に使用されていますが、現在私には知られていません。
回避策として、それでも使用できます http:
また https:
スキームと決定 [NSURLProtocol canInitWithRequest]
他の基準(ホスト名など)に基づいています。