9

私の iOS アプリでは、UIWebView とカスタム プロトコルを使用しています (独自の NSURLProtocol 実装を使用)。URL をロードするたびに、次のようなものを UIWebView にロードするように、かなり注意を払ってきました。

myprotocol://myserver/mypath

私の NSURLProtocol 実装では、NSURLRequest の変更可能なコピーを取得し、URL を http: に変換してサーバーに送信します。

HTTP GET リクエストではすべてが機能します。私が遭遇する問題は、POST リクエストに関するものです。リクエストがカスタム プロトコルを使用している場合、UIWebView が HTTPBody のフォーム データを適切にエンコードしていないようです。

サーバー要求に HTTPS を使用しているため、回避策の 1 つは、myprotocol: の代わりに http: をインターセプトするようにプロトコル ハンドラーを登録することです。すべての呼び出しを https: に変換できます解決:

しかし、私が望むものを達成するための代替および/またはより良い方法があるかどうか疑問に思っています。

4

2 に答える 2

6

POSTリクエストを使用する代わりに、回避策の1つは、URLに対してGETリクエストを引き続き使用することですが、実装では、リクエストクエリ文字列をPOSTの本文として使用して、サーバーへPOSTリクエストにmyprotocol://変換します。NSURLProtocolhttp://

GETリクエストを使用して大量のデータを送信する場合の懸念は、リクエストチェーンのどこかで、リクエスト行が切り捨てられる可能性があることです。ただし、ローカルで実装されたプロトコルでは、これは問題ではないようです。

実験用に短いCordovaテストアプリを作成しましたが、HTTPリクエストエコーサービスhttp://http-echo.jgate.de/に問題なく1MiBを少し超えるデータを送信できることがわかりました。

これが私の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次に、適切なメソッドに転送するためのプロトコルメソッドを実装しましたが、( http://http-echo.jgate.de/からの応答の場合のように)NSURLProtocolClientの場合は応答データを構築します。Transfer-Encoding:chunked

于 2012-06-30T13:53:59.593 に答える
4

残念ながら、そのスキーム要求は、Foundation Framework による他の (カスタムを含む) スキームとは少し異なる方法で処理されるようhttp:ですhttps:。明らかに、以前のものに対して常に関連するリターンHTTPBodyHTTPBodyStream呼び出します。これは の呼び出し前にすでに決定されているため、カスタム実装はそれに影響を与える方法がありません (手遅れです)。NSURLRequestnil[NSURLProtocol canInitWithRequest]NSURLProtocol

「デフォルトのもの」とは異なるNSURLRequestクラスがhttp:andに使用されているようです。https:このクラスのデフォルトの GnuStep 実装は、常に nilからHTTPBodyおよびHTTPBodyStream呼び出しを返します。したがって、特定の実装 (たとえば、PhoneGap の下にあるもの、おそらく Foundation Framework の一部) は、を参照NSURLRequestする前に、スキームに基づいてクラスのタイプを選択しますNSURLProtocol。カスタム スキームの場合、カスタム URI スキーム ハンドラーでの POST メソッド (および本文を含むその他のメソッド) の使用を効果的に無効にするとの両方NSURLRequestを返すことができます。nilHTTPBodyHTTPBodyStream

NSURLRequest実際に使用されるクラスの決定に影響を与える方法があるかもしれませんが、現在のところ不明です。

回避策として、引き続きhttp:orhttps:スキームを使用し[NSURLProtocol canInitWithRequest]て、他の基準 (ホスト名など) に基づいて決定することができます。

于 2014-01-01T14:21:47.983 に答える