NSURLProtocol没有完成NSURLRequest
  问题 :我有我的NSURLProtocol的子类,但+canonicalRequestForRequest:返回的NSURLRequest或者-connection:willSendRequest:redirectResponse:返回的请求永远不会传递给我的URL协议实例。 
  详细信息 :在我的NSURLProtocol子类中,我实现了方法+canonicalRequestForRequest:将HTTP头添加到请求。  头添加成功,但当我的URL协议调用-startLoading时, self.request不包含该头。 
  另外,当在NSURLConnection的委托上调用connection:willSendRequest:redirectResponse: ,该方法返回的任何请求都不会到达我的URL协议实例。 
  我认为问题在于, initWithRequest:cachedResponse:client:以前被称为+canonicalRequestForRequest:或connection:willSendRequest:redirectResponse:被称为,并从这些2种方法所产生的请求不会传到我的URL协议实例之后,它一直alloc / init 。 
这是Apple的URL加载系统中的错误吗? 有没有解决方法? 难道我做错了什么?
2014年4月6日更新
  这里是一些示例代码。  我设置了2 -[APViewController connection:willSendRequest:redirectResponse:]文件:一个在-[APViewController connection:willSendRequest:redirectResponse:]调用X-WillSendRequestTest ,另一个在+[APURLProtocol canonicalRequestForRequest:] 。  通过在-[APURLProtocol startLoading]调用self.request获取NSURLRequest中的任何一个都-[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
上一篇: NSURLProtocol doesn't get complete NSURLRequest
下一篇: Using NSOutputStream outputStreamWithURL with a custom URLprotocol
