Objective c NSURL协议未获取完整的NSURL请求
问题:我有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:之前被调用,并且来自这两个方法的结果请求在alloc/init之后永远不会传递到我的URL协议实例 这是苹果URL加载系统中的一个错误吗?有解决办法吗?我做错什么了吗 更新日期:2014年4月6日 下面是一些示例代码。我设置了两个头:一个在-[APViewController连接:willSendRequest:redirectResponse:]中调用X-WillSendRequestTest,另一个在+[APURLProtocol canonicalRequestForRequest:]中。通过在-[APURLProtocol-startLoading]内调用self.request获取的NSURLRequest中没有一个 APViewController.m是NSURL协议的代表Objective c NSURL协议未获取完整的NSURL请求,objective-c,nsurlconnection,nsurlprotocol,Objective C,Nsurlconnection,Nsurlprotocol,问题:我有NSURLProtocol的子类,但由+canonicalRequestForRequest:返回的NSURLRequest或由-connection:willSendRequest:redirectResponse:返回的请求从未传递到我的URL协议实例 详细信息:在NSURLProtocol的子类中,我实现了方法+canonicalRequestForRequest:向请求添加HTTP头。头添加成功,但在我的URL协议上调用-startLoading时,self.request不包
- (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
首先一件事:为什么要在+canonicalRequestForRequest:中添加头?我不会这么做的。使用这种方法很容易引入bug。请查看有关此方法的文档以及canonical的含义。没有说这是问题所在,但是您是否尝试过在这个方法中返回相同的请求,并在-starting方法中添加您的头?方法+canonicalRequestForRequest:是您应该规范化请求的地方。从文档来看:定义“规范”的含义取决于每个具体的协议实现。协议应该保证相同的输入请求总是产生相同的规范形式。事实上,在苹果的iOS示例CustomHTTPProtocol中,他们通过在该方法中添加Accept、Accept Encoding和Accept Language头来规范化请求。是的,+canonicalRequestForRequest:,这就是我提到它的原因。我之所以这么说,是因为根据实现,您可能会通过实际创建一个不规范的请求来引入bug。这就是为什么我不确定这是问题的原因,但它可能是。我看过苹果的例子,但不久前我也看到过这个例子,它工作得很好,它以惊人的加载方法设置了标题。因此,我试图帮助减少错误的可能性。你有没有试过将它们放在令人震惊的加载方法中?如果不查看代码,就很难调查错误是什么,但至少如果我们排除一些可能性,就可以更容易地发现您可能存在的任何错误。@rocir我添加了一些示例代码。是的,我当前在+canonicalRequestForRequest:中添加的头可以移动到-startLoading。但是,我关心的是,为什么方法+canonicalRequestForRequest:或连接:willSendRequest:redirectResponse:NSURLConnectionDataDelegate协议返回的NSURLRequest被完全忽略,而没有转发到处理连接的NSURLProtocol子类?
@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
@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