3

HTTP リクエストをプロキシするために登録された UIWebView とカスタム NSURLProtocol クラスがあります。github.com の読み込みに問題があります。https://github.comを参照すると、ページとそのコンテンツが正常に読み込まれます。ただし、http://github.comを参照すると、HTML は正しく読み込まれますが、画像や CSS は読み込まれません。https バージョンをロードすると、次のようになります。

HTTPS GitHub

http バージョンをロードすると、次のようになります。

HTTP GitHub

この問題を再現するために使用したView Controllerのコードは次のとおりです。

@interface ViewController ()
{
    UIWebView *aWebView;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [NSURLProtocol registerClass:[WebViewProxyURLProtocol class]];

    aWebView = [[UIWebView alloc] initWithFrame:self.view.frame];
    aWebView.delegate = self;
    [self.view addSubview:aWebView];

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://github.com"]];
    [aWebView loadRequest:request];
}

@end

NSURLProtocol の実装は次のとおりです。

@interface WebViewProxyURLProtocol : NSURLProtocol <NSURLConnectionDataDelegate>

@end

@implementation WebViewProxyURLProtocol {
    NSMutableURLRequest* correctedRequest;
}

+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
    return ([[request allHTTPHeaderFields] objectForKey:@"X-WebViewProxy"] == nil);
}

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
    return request;
}

+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
    return NO;
}

- (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id<NSURLProtocolClient>)client {
    if (self = [super initWithRequest:request cachedResponse:cachedResponse client:client]) {
        // Add header to prevent loop in proxy
        correctedRequest = request.mutableCopy;
        [correctedRequest addValue:@"True" forHTTPHeaderField:@"X-WebViewProxy"];
    }
    return self;
}

- (void)startLoading {
    [NSURLConnection connectionWithRequest:correctedRequest delegate:self];
}

- (void)stopLoading {
    correctedRequest = nil;
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.client URLProtocol:self didLoadData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    [self.client URLProtocolDidFinishLoading:self];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    [self.client URLProtocol:self didFailWithError:error];
}

- (NSURLRequest *)connection:(NSURLConnection *)connection
             willSendRequest:(NSURLRequest *)request
            redirectResponse:(NSURLResponse *)redirectResponse
{
    return request;
}

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
                  willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
    return nil;
}

@end

カスタム NSURLProtocol クラスを無効にすると、正常に動作します。Charles を使用して HTTP 要求と応答を調べたところ、NSURLProtocol の有無にかかわらず同じように見えます。

問題は、NSURLConnection を使用してページ データを取得するときに、UIWebView が Web ページのコンテンツを要求しないのはなぜですか?

4

3 に答える 3

5

リダイレクトは機能しましたが、コンテンツは読み込まれませんでした。

Apple docに従って、リダイレクトは NSURLProtocol サブクラスの connection:willSendRequest:redirectResponse デリゲート メソッドを使用して処理する必要があると述べています。

私たちのソリューションは次のようになりました。

- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response {
  if (response) {
    NSMutableURLRequest *redirect = [request mutableCopy];
    [NSURLProtocol removePropertyForKey:kFlagRequestHandled inRequest:redirect];
    [RequestHelper addWebViewHeadersToRequest:redirect];

    // THE IMPORTANT PART
    [self.client URLProtocol:self wasRedirectedToRequest:redirect redirectResponse:response];

    return redirect;
  }

return request;

}

于 2015-03-02T14:01:56.983 に答える