2012-02-15 5 views
9

私のiOSアプリケーションでは、UIWebViewとカスタムプロトコル(独自のNSURLProtocol実装を使用しています)を使用しています。私は、URLをロードするたびに、私は私のUIWebViewにこのような何かをロードすることを確認することについてかなり慎重にしてきた:UIWebViewとPOSTリクエストでカスタムNSURLProtocolを使用する

myprotocol:// MYSERVER/mypathで

と私のNSURLProtocolの実装では、私は可変を取りますNSURLRequestのコピーをhttp:に変換し、それを私のサーバに送ります。

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

サーバーリクエストにHTTPSを使用しているので、回避策の1つは、プロトコルハンドラをmyprotocolの代わりにhttp:を傍受するように登録することです。これはhttpsへのすべての呼び出しを変換できます。この他の質問here

しかし、私が望むものを達成するための選択肢と方法があるかどうかは疑問だ。代わりに、POST要求を使用しようとしているの

答えて

5

は、1つの作業は周りのようにリクエストクエリ文字列を使用してmyprotocol:// URLのGET要求を使用し続けるが、あなたのサーバーにhttp:// POSTリクエストにお使いNSURLProtocol実装でそれらを変換することですPOSTの本体。

大量のデータを送信するためにGETリクエストを使用する場合の心配は、要求チェーンのどこかで要求ラインが切り捨てられる可能性があることです。しかし、これはローカルで実装されたプロトコルでは問題にはならないと思われる。

私は実験に短いコルドバのテストアプリケーションを書いて、私はここでhttp://http-echo.jgate.de/

サービスをエコーHTTPリクエストに問題なくデータの少しの1以上のMIB経由で送信することができたことがわかったが、私の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]; 
    } 
} 

Iは、次いで、適切なNSURLProtocolClient方法に転送するNSURLConnectionプロトコル方法を実施するが、(http://http-echo.jgate.de/からの応答の場合のように)Transfer-Encoding:chunkedの場合の応答データを構築します。

+0

すてきな提案。申し訳ありませんが、以前はあなたの回答に気付かなかった。 – bcholmes

2

残念ながら、http:https:のスキーム要求は、Foundation Frameworkによる他の(カスタムを含む)スキームとは多少異なる方法で処理されるようです。明らかにHTTPBodyHTTPBodyStreamの関連するNSURLRequestのコールは、前者の場合は常にnilを返します。これはすでに[NSURLProtocol canInitWithRequest]の前回の呼び出しが決定されているため、カスタムNSURLProtocolの実装には影響がありません(遅すぎます)。

http:https:には「default default」よりも異なるNSURLRequestクラスが使用されているようです。このクラスのデフォルトのGnuStep実装では、が常にnilとなり、HTTPBodyHTTPBodyStreamが呼び出されます。したがって、具体的な実装(例えば、PhoneGapの下のもの、Foundation Frameworkの可能性が高いもの)はNSURLRequestのタイプのクラスを前のコンサルティングに基づいてNSURLProtocolというスキームに基づいて選択します。カスタムスキームの場合、をHTTPBodyHTTPBodyStreamの両方に返すNSURLRequestがあり、カスタムURIスキームハンドラでPOSTメソッド(およびその他のメソッドの本体)の使用を実質的に無効にします。

NSURLRequestクラスが実際に使用されている決定に影響を与える方法があるかもしれませんが、現在は私には分かりません。

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

関連する問題