Permalink
Browse files

CB-2415 On iOS the ajax error/fail callback is not called after serve…

…r returns error code 401/unauthorized
  • Loading branch information...
tripodsan committed Nov 27, 2015
1 parent 3618162 commit 5f0133c026d6e21c93ab1ca0e146e125dfbe8f7e
@@ -0,0 +1,21 @@
/*
* ADOBE CONFIDENTIAL
* __________________
*
* Copyright 2015 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
*/
#import <Foundation/Foundation.h>
@interface CDVURLProtocolHttp : NSURLProtocol<NSURLConnectionDelegate, NSURLConnectionDataDelegate>
@end
@@ -0,0 +1,187 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
#import "CDVURLProtocolHttp.h"
@interface CDVURLProtocolHttp()
@property (nonatomic, strong) NSURLConnection *connection;
@end
/**
* Generic protocol to handle http and https requests.
* Currently only used to suppress the "www-authenticate" response header, in order to avoid the
* authentication pop-up to show up (see CB-2415).
*/
@implementation CDVURLProtocolHttp
#define KEY_BYPASS_OWN_PROTOCOL @"cdv-no-http-protocol"
/**
* We handle the request for http and https, but only if we not already initialized the connection.
*/
+ (BOOL) canInitWithRequest:(NSURLRequest*) request {
if (![request.URL.scheme isEqualToString:@"http"] && ![request.URL.scheme isEqualToString:@"https"]) {
return NO;
}
static NSUInteger requestCount = 0;
if ([NSURLProtocol propertyForKey:KEY_BYPASS_OWN_PROTOCOL inRequest:request]) {
NSLog(@"NO Request #%u: URL = %@", requestCount++, request);
return NO;
}
// TODO: only handle for ajax request, i.e. if 'x-requested-with' == 'XMLHttpRequest'
NSLog(@"YES Request #%u: URL = %@", requestCount++, request);
return YES;
}
+ (NSURLRequest*) canonicalRequestForRequest:(NSURLRequest*) request {
return request;
}
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
return [super requestIsCacheEquivalent:a toRequest:b];
}
- (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id <NSURLProtocolClient>)client
{
self = [super initWithRequest:request cachedResponse:cachedResponse client:client];
NSLog(@"initWithRequest self=%@, req=%@ resp=%@", self, request, cachedResponse);
return self;
}
/**
* Start loading the request.
*
* We use our own connection to load the request, so that we can intercept the response headers.
*/
- (void) startLoading {
NSLog(@"start loading %@", self.request.URL);
// mark the request as handled
NSMutableURLRequest* request = self.request.mutableCopy;
[NSURLProtocol setProperty:@YES forKey:KEY_BYPASS_OWN_PROTOCOL inRequest:request];
// create connection
self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
[self.connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[self.connection start];
}
/**
* Stop loading the request.
*/
- (void) stopLoading {
NSLog(@"stop loading %@", self.request.URL);
[self.connection cancel];
self.connection = nil;
}
#pragma mark NSURLConnection Delegate Methods
- (void) connection:(NSURLConnection*) connection didReceiveData:(NSData*) data {
NSLog(@"did receive data self=%@ %@", self, self.request.URL);
[self.client URLProtocol:self didLoadData:data];
}
- (void) connection:(NSURLConnection*) connection didFailWithError:(NSError*) error {
NSLog(@"did didFailWithError self=%@ error=%@ %@", self, error, self.request.URL);
[self.client URLProtocol:self didFailWithError:error];
}
/**
* Handles the response by altering response headers for 401 responses. It removes the
* 'www-authenticate' header so that the webview will no open the credentials prompt.
*/
- (void) connection:(NSURLConnection*) connection didReceiveResponse:(NSURLResponse*) response {
NSLog(@"did didReceiveResponse self=%@ resp=%@ %@", self, response, self.request.URL);
NSURLCacheStoragePolicy policy = NSURLCacheStorageAllowed;
if ([response isKindOfClass:NSHTTPURLResponse.class]) {
NSHTTPURLResponse* resp = (NSHTTPURLResponse*) response;
if (resp.statusCode == 401) {
// // remove www-authenticate header
// NSMutableDictionary* headers = [resp allHeaderFields].mutableCopy;
// [headers removeObjectForKey:@"WWW-Authenticate"];
// response = [[NSHTTPURLResponse alloc] initWithURL:resp.URL
// statusCode:resp.statusCode
// HTTPVersion:@"1.1"
// headerFields:headers
// expecte];
policy = NSURLCacheStorageNotAllowed;
}
}
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:policy];
}
- (void) connectionDidFinishLoading:(NSURLConnection*) connection {
[self.client URLProtocolDidFinishLoading:self];
}
- (NSURLRequest*) connection:(NSURLConnection*) connection willSendRequest:(NSURLRequest*) request redirectResponse:(NSURLResponse*) response {
NSLog(@"willSendRequest self=%@ request=%@ response=%@", self, request, response);
return request;
}
- (NSInputStream*) connection:(NSURLConnection*) connection needNewBodyStream:(NSURLRequest*) request {
NSLog(@"needNewBodyStream self=%@ request=%@", self, request);
return nil;
}
- (void) connection:(NSURLConnection*) connection didSendBodyData:(NSInteger) bytesWritten totalBytesWritten:(NSInteger) totalBytesWritten totalBytesExpectedToWrite:(NSInteger) totalBytesExpectedToWrite {
NSLog(@"didSendBodyData self=%@ ", self);
}
- (NSCachedURLResponse*) connection:(NSURLConnection*) connection willCacheResponse:(NSCachedURLResponse*) cachedResponse {
NSLog(@"willCacheResponse self=%@ resp=%@", self, cachedResponse);
return cachedResponse;
}
- (BOOL) connectionShouldUseCredentialStorage:(NSURLConnection*) connection {
return NO;
}
- (BOOL) connection:(NSURLConnection*) connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace*) protectionSpace {
NSLog(@"canAuthenticateAgainstProtectionSpace self=%@ space=%@", self, protectionSpace);
return NO;
}
- (void) connection:(NSURLConnection*) connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge*) challenge {
NSLog(@"didReceiveAuthenticationChallenge self=%@ challange=%@", self, challenge);
}
- (void) connection:(NSURLConnection*) connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge*) challenge {
NSLog(@"willSendRequestForAuthenticationChallenge self=%@ challange=%@", self, challenge);
}
- (void) connection:(NSURLConnection*) connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge*) challenge {
NSLog(@"didCancelAuthenticationChallenge self=%@ challange=%@", self, challenge);
}
@end
@@ -27,6 +27,8 @@ Licensed to the Apache Software Foundation (ASF) under one
#import "NSDictionary+CordovaPreferences.h"
#import "CDVLocalStorage.h"
#import "CDVCommandDelegateImpl.h"
#import "CDVURLProtocolHttp.h"
#import "CustomHTTPProtocol.h"
@interface CDVViewController () {
NSInteger _userAgentLockToken;
@@ -261,7 +263,7 @@ - (void)viewDidLoad
backupWebStorageType = backupWebStorage;
}
[self.settings setCordovaSetting:backupWebStorageType forKey:@"BackupWebStorage"];
[CDVLocalStorage __fixupDatabaseLocationsWithBackupType:backupWebStorageType];
// // Instantiate the WebView ///////////////
@@ -273,6 +275,10 @@ - (void)viewDidLoad
// register this viewcontroller with the NSURLProtocol, only after the User-Agent is set
[CDVURLProtocol registerViewController:self];
// register our http protocol
// [NSURLProtocol registerClass:[CDVURLProtocolHttp class]];
[CustomHTTPProtocol start];
// /////////////////
/*
@@ -502,7 +508,7 @@ - (BOOL)defaultResourcePolicyForURL:(NSURL*)url
else if ([[url scheme] isEqualToString:@"about"]) {
return NO;
}
/*
* all data: scheme urls are handled
*/
@@ -62,6 +62,16 @@
7EDCF3001B17D9DF00F7019F /* CDVURLRequestFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EDCF2FF1B17D9DF00F7019F /* CDVURLRequestFilter.h */; settings = {ATTRIBUTES = (Public, ); }; };
A3B082D41BB15CEA00D8DC35 /* CDVGestureHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = A3B082D21BB15CEA00D8DC35 /* CDVGestureHandler.h */; settings = {ASSET_TAGS = (); }; };
A3B082D51BB15CEA00D8DC35 /* CDVGestureHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = A3B082D31BB15CEA00D8DC35 /* CDVGestureHandler.m */; settings = {ASSET_TAGS = (); }; };
CC6A00933C6D8B696716D707 /* CDVURLProtocolHttp.h in Headers */ = {isa = PBXBuildFile; fileRef = CC6A0B281FED70F30F69C054 /* CDVURLProtocolHttp.h */; };
CC6A00FF91BA47BF1DDAFAF2 /* CDVURLProtocolHttp.m in Sources */ = {isa = PBXBuildFile; fileRef = CC6A02F5F6938DB83F9294F2 /* CDVURLProtocolHttp.m */; };
CC6A03640D81E69351F86EEC /* QNSURLSessionDemux.m in Sources */ = {isa = PBXBuildFile; fileRef = CC6A0CE177A98C93C09C055D /* QNSURLSessionDemux.m */; };
CC6A07CCC9FDE1611BA4C273 /* QNSURLSessionDemux.h in Headers */ = {isa = PBXBuildFile; fileRef = CC6A0F254F5E55716EB374C0 /* QNSURLSessionDemux.h */; };
CC6A07D5A6E1A8BFF940EAB4 /* CacheStoragePolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = CC6A05B402E3325BEE1737F7 /* CacheStoragePolicy.m */; };
CC6A09885549A3FB00304BD7 /* CanonicalRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CC6A066FB8399E02C7ECEA17 /* CanonicalRequest.h */; };
CC6A0A1A3CDCF55357DCF9DA /* CustomHTTPProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = CC6A026E14976CB2A985F196 /* CustomHTTPProtocol.m */; };
CC6A0C5C2034AEE7D251E67D /* CacheStoragePolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = CC6A0EFB5438A6BAC52EBE76 /* CacheStoragePolicy.h */; };
CC6A0C7D2EEA183C2438F82E /* CustomHTTPProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = CC6A0BD40A676D21BCD94B62 /* CustomHTTPProtocol.h */; };
CC6A0FE73532331A0E2136C5 /* CanonicalRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CC6A012E6B6B1FBA2581CF6E /* CanonicalRequest.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -123,6 +133,16 @@
A3B082D21BB15CEA00D8DC35 /* CDVGestureHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVGestureHandler.h; sourceTree = "<group>"; };
A3B082D31BB15CEA00D8DC35 /* CDVGestureHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVGestureHandler.m; sourceTree = "<group>"; };
AA747D9E0F9514B9006C5449 /* CordovaLib_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CordovaLib_Prefix.pch; sourceTree = SOURCE_ROOT; };
CC6A012E6B6B1FBA2581CF6E /* CanonicalRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CanonicalRequest.m; sourceTree = "<group>"; };
CC6A026E14976CB2A985F196 /* CustomHTTPProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CustomHTTPProtocol.m; sourceTree = "<group>"; };
CC6A02F5F6938DB83F9294F2 /* CDVURLProtocolHttp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVURLProtocolHttp.m; sourceTree = "<group>"; };
CC6A05B402E3325BEE1737F7 /* CacheStoragePolicy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CacheStoragePolicy.m; sourceTree = "<group>"; };
CC6A066FB8399E02C7ECEA17 /* CanonicalRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CanonicalRequest.h; sourceTree = "<group>"; };
CC6A0B281FED70F30F69C054 /* CDVURLProtocolHttp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVURLProtocolHttp.h; sourceTree = "<group>"; };
CC6A0BD40A676D21BCD94B62 /* CustomHTTPProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomHTTPProtocol.h; sourceTree = "<group>"; };
CC6A0CE177A98C93C09C055D /* QNSURLSessionDemux.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QNSURLSessionDemux.m; sourceTree = "<group>"; };
CC6A0EFB5438A6BAC52EBE76 /* CacheStoragePolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CacheStoragePolicy.h; sourceTree = "<group>"; };
CC6A0F254F5E55716EB374C0 /* QNSURLSessionDemux.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QNSURLSessionDemux.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -261,6 +281,9 @@
7ED95D331AB9029B008C4574 /* NSMutableArray+QueueAdditions.h */,
7ED95D341AB9029B008C4574 /* NSMutableArray+QueueAdditions.m */,
7EDCF2FF1B17D9DF00F7019F /* CDVURLRequestFilter.h */,
CC6A02F5F6938DB83F9294F2 /* CDVURLProtocolHttp.m */,
CC6A0B281FED70F30F69C054 /* CDVURLProtocolHttp.h */,
CC6A0382F004931C3998509D /* Core Code */,
);
name = Public;
path = Classes/Public;
@@ -275,6 +298,21 @@
path = CDVGestureHandler;
sourceTree = "<group>";
};
CC6A0382F004931C3998509D /* Core Code */ = {
isa = PBXGroup;
children = (
CC6A066FB8399E02C7ECEA17 /* CanonicalRequest.h */,
CC6A012E6B6B1FBA2581CF6E /* CanonicalRequest.m */,
CC6A0EFB5438A6BAC52EBE76 /* CacheStoragePolicy.h */,
CC6A05B402E3325BEE1737F7 /* CacheStoragePolicy.m */,
CC6A0BD40A676D21BCD94B62 /* CustomHTTPProtocol.h */,
CC6A026E14976CB2A985F196 /* CustomHTTPProtocol.m */,
CC6A0F254F5E55716EB374C0 /* QNSURLSessionDemux.h */,
CC6A0CE177A98C93C09C055D /* QNSURLSessionDemux.m */,
);
path = "Core Code";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@@ -314,6 +352,11 @@
7E7F69B81ABA368F007546F4 /* CDVUIWebViewEngine.h in Headers */,
7E7F69B91ABA3692007546F4 /* CDVHandleOpenURL.h in Headers */,
30193A511AE6350A0069A75F /* CDVUIWebViewNavigationDelegate.h in Headers */,
CC6A00933C6D8B696716D707 /* CDVURLProtocolHttp.h in Headers */,
CC6A09885549A3FB00304BD7 /* CanonicalRequest.h in Headers */,
CC6A0C5C2034AEE7D251E67D /* CacheStoragePolicy.h in Headers */,
CC6A0C7D2EEA183C2438F82E /* CustomHTTPProtocol.h in Headers */,
CC6A07CCC9FDE1611BA4C273 /* QNSURLSessionDemux.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -394,6 +437,11 @@
7ED95D461AB9029B008C4574 /* CDVPlugin.m in Sources */,
7ED95D091AB9028C008C4574 /* CDVLocalStorage.m in Sources */,
3093E2241B16D6A3003F381A /* CDVSystemSchemes.m in Sources */,
CC6A00FF91BA47BF1DDAFAF2 /* CDVURLProtocolHttp.m in Sources */,
CC6A0FE73532331A0E2136C5 /* CanonicalRequest.m in Sources */,
CC6A07D5A6E1A8BFF940EAB4 /* CacheStoragePolicy.m in Sources */,
CC6A0A1A3CDCF55357DCF9DA /* CustomHTTPProtocol.m in Sources */,
CC6A03640D81E69351F86EEC /* QNSURLSessionDemux.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

0 comments on commit 5f0133c

Please sign in to comment.