Nsurlprotocol Isn't Asked to Load After Yes Response to Caninitwithrequest

NSURLProtocol isn't asked to load after YES response to canInitWithRequest

I was able to workaround this issue by cache-busting the UIWebView cache, while not busting the NSURLCache.

  1. Add a unique param to the query params of the original request. I chose 'key=000000' where the value is zero-led six digit random number.
  2. In the protocol, strip the key in canonicalRequestForRequest: and in initWithRequest:cachedResponse:client

My stripping code looks like this (there might be a cleaner way to strip the param, but this works):

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
{
NSURLRequest *canonicalRequest = request;
BOOL myProtocolRequest = [[NSURLProtocol propertyForKey:kMYProtocolRequest inRequest:request] boolValue];
if (myProtocolRequest)
{
NSMutableURLRequest *mutableRequest = [request mutableCopyWorkaround];
NSString *originalURLString = mutableRequest.URL.absoluteString;
NSString *regexString = [NSString stringWithFormat:@"(?:[?&])(key=[[:digit:]]{%d}&*)", kMYKeyLength];

NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexString options:0 error:0];
NSTextCheckingResult *result = [regex firstMatchInString:originalURLString options:0 range:NSMakeRange(0, originalURLString.length)];
if (result.numberOfRanges > 1)
{
NSRange keyRange = [result rangeAtIndex:1];
NSLog(@"Removing '%@' from request", [originalURLString substringWithRange:keyRange]);
NSString *replacementURLString = [originalURLString stringByReplacingCharactersInRange:keyRange withString:@""];
mutableRequest.URL = [NSURL URLWithString:replacementURLString];
canonicalRequest = mutableRequest;
}
}

return canonicalRequest;
}

My init code looks like this:

- (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id<NSURLProtocolClient>)client
{
self = [super initWithRequest:[MYURLProtocol canonicalRequestForRequest:request] cachedResponse:cachedResponse client:client];
return self;
}

I don't like that I have to do this, but I'm finally getting exactly the behavior I want. Hopefully it helps someone out there.

NSURLProtocol - startLoading not invoked

I had the same issue. In my case, I was adding an iframe to the page dynamically using JavaScript and loading my custom protocol content in that. In iOS 9.1 the WebView refuses to load the iframe content when the main document is accessed over https, but it works fine over http. This looks like a new security control, to avoid loading insecure resources over a secure session.

The fix I went with was to change my scheme to use https. For example, use https://imsweb/... instead of imsweb://. It's a bit of a hack but the best solution I could find.

Something like:

+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
if ([request.URL.scheme isEqualToString:@"https"] &&
[request.URL.host isEqualToString:@"imsweb"]) {
NSLog(@"%@", @"YES");
return YES;
}
return NO;
}

and of course you need to reconstruct the correct URL in startLoading.

NSURLProtocol canInitWithRequest: called multiple times

I'm not expert, but AFAIK this is normal behavior. [NSURLPRotocol canInitWithRequest:] may be called multiple times for the same request. If you want to be notified just once per request, you should catch it in -startLoading method. I found this tutorial helpful to construct simple NSURLProtocol subclass which will do just that: http://www.raywenderlich.com/59982/nsurlprotocol-tutorial

iOS: passing custom NSURL to NSURLProtocol

If there's some way to get your original NSURL used as mainDocumentURL that would be ideal. If there's no way to prevent it being copied, I thought of the following hack as an alternative:

Before the creation of each UIWebView, set the user agent string to a unique value. Supposedly this change only affects UIWebView objects that are created subsequently, so each view will end up with its own distinctive user agent string.

In the NSURLProtocol implementation, you can check the user agent string to identify the associated UIWebView and pass it through to the real protocol handler using the actual user agent string (so the server will see nothing different).

All this depends on the views really ending up with different UA strings. Let me know if you manage to get it to work!

Should a custom NSURLProtocol follow redirects itself, or let its client worry about that?

To answer this question, I simply removed the code in my URL protocol implementation that follows the link given in the redirect response. It should be pretty obvious if the connection client follows creates a new connection to load the new URL. As it turns out, nothing happened -- the client never creates a new connection, and the redirect isn't followed. From this I have to conclude that the URL protocol itself should attempt to load URL given in the redirect response.



Related Topics



Leave a reply



Submit