HTTP リクエストをプロキシするために登録された UIWebView とカスタム NSURLProtocol クラスがあります。github.com の読み込みに問題があります。https://github.comを参照すると、ページとそのコンテンツが正常に読み込まれます。ただし、http://github.comを参照すると、HTML は正しく読み込まれますが、画像や CSS は読み込まれません。https バージョンをロードすると、次のようになります。
http バージョンをロードすると、次のようになります。
この問題を再現するために使用した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 ページのコンテンツを要求しないのはなぜですか?