1

問題: NSURLProtocol のサブクラスがありますが、NSURLRequest返された+canonicalRequestForRequest:または返された要求-connection:willSendRequest:redirectResponse:が URL プロトコル インスタンスに渡されません。

詳細: のサブクラスでリクエストに HTTP ヘッダーを追加するNSURLProtocolメソッドを実装し+canonicalRequestForRequest:ヘッダーは正常に追加されましたが-startLoading、URL プロトコルで呼び出されself.request、そのヘッダーが含まれていません。

さらに、connection:willSendRequest:redirectResponse:のデリゲートで が呼び出された場合NSURLConnection、そのメソッドによって返された要求が何であれ、URL プロトコル インスタンスにも到達しません。

initWithRequest:cachedResponse:client:問題は、呼び出される前+canonicalRequestForRequest:または呼び出されることにあると思います。これらの 2 つのメソッドからの結果のリクエストは、 /connection:willSendRequest:redirectResponse:になった後に URL プロトコル インスタンスに渡されません。allocinit

これは Apple の URL 読み込みシステムのバグですか? 回避策はありますか? 私は何か間違ったことをしていますか?


2014 年 4 月 6 日の更新

ここにいくつかのサンプルコードがあります。2 つのヘッダーを設定しました。1 つは-[APViewController connection:willSendRequest:redirectResponse:]呼び出されX-WillSendRequestTest、もう 1 つは+[APURLProtocol canonicalRequestForRequest:]. どちらもwithinNSURLRequestを呼び出してフェッチされません。self.request-[APURLProtocol startLoading]

APViewController.m (NSURLProtocol のデリゲート)

- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse {
    NSLog(@"Will send request: %@", request);

    NSMutableURLRequest *newRequest = [request mutableCopy];

    // This header will not be in self.request when fetched within the -[APURLProtocol start loading] method.
    [newRequest setValue:@"12345" forHTTPHeaderField:@"X-WillSendRequestTest"];

    NSLog(@"New request: %@", newRequest);

    return newRequest;
}

APURLProtocol.m

@interface APURLProtocol () <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
// Private properties
@property (nonatomic, strong) NSURLConnection *connection;
@end




@implementation APURLProtocol

#pragma mark -
#pragma mark Init methods

- (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id<NSURLProtocolClient>)client {
    NSLog(@"%@", NSStringFromSelector(_cmd));

    if ((self = [super initWithRequest:request cachedResponse:cachedResponse client:client])) {

    }

    return self;
}



#pragma mark -
#pragma mark dealloc

- (void)dealloc {
    NSLog(@"%@", NSStringFromSelector(_cmd));

    [_connection cancel];
}



#pragma mark -
#pragma mark Inherited class methods

+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
    NSLog(@"%@ %@", NSStringFromSelector(_cmd), request);

    id requestIsHandled = [self propertyForKey:kAPURLProtocolHandledRequest inRequest:request];

    if (requestIsHandled == nil
            && ([request.URL.scheme caseInsensitiveCompare:@"http"] == NSOrderedSame
                    || [request.URL.scheme caseInsensitiveCompare:@"https"] == NSOrderedSame
                    || [request.URL.scheme caseInsensitiveCompare:@"ftp"] == NSOrderedSame)) {
                NSLog(@"YES");
                return YES;
            }

    NSLog(@"NO");
    return NO;
}


+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
    NSLog(@"%@", NSStringFromSelector(_cmd));

    NSMutableURLRequest *newRequest = [request mutableCopy];
    // This header will not be in self.request when fetched within the -[APURLProtocol start loading] method.
    [newRequest setValue:@"12345" forHTTPHeaderField:@"X-CanonicalRequestTest"];

    return newRequest;
}


+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)aRequest toRequest:(NSURLRequest *)bRequest {
    NSLog(@"Request is cache equivalent:");
    NSLog(@"Request 1: %@", aRequest);
    NSLog(@"Request 2: %@", bRequest);

    return YES;
}



#pragma mark -
#pragma mark Inherited instance methods

- (void)startLoading {
    NSLog(@"%@. Request: %@", NSStringFromSelector(_cmd), self.request);

    NSMutableURLRequest *newRequest = [[self request] mutableCopy];
    [[self class] setProperty:@"" forKey:kAPURLProtocolHandledRequest inRequest:newRequest];

    [self.connection cancel];

    self.connection = [[NSURLConnection alloc] initWithRequest:newRequest
                                                                                                        delegate:self
                                                                                        startImmediately:YES];
}
@end

NSURLRequest+test.m (NSURLRequestの記述を拡張するカテゴリ)

警告: 自宅でこれを行わないでください。カテゴリを使用してメソッドまたはプロパティをオーバーライドしないでください。これは、迅速なデバッグのみを目的としています。

@implementation NSURLRequest (test)

- (NSString *)description {
    NSString *dataString = [[NSString alloc] initWithData:self.HTTPBody encoding:NSUTF8StringEncoding];

    return [NSString stringWithFormat:@"%@: %p {URL: %@, Method: %@, Headers: %@, Data: %@",
                    NSStringFromClass([self class]), self, self.URL, self.HTTPMethod, [self allHTTPHeaderFields], dataString];
}

@end
4

0 に答える 0