Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Better logging if change tracker fails HTTP auth

If TDSocketChangeTracker gets a 401 or 407 and can't find a credential, or the credential is rejected,
it now logs a message of the form
    TDSocketChangeTracker[...]: HTTP auth failed; sent Authorization: %@  ;  got WWW-Authenticate: %@
showing the Authorization header it sent (if any, else null) and the WWW-Authenticate response header.
These headers are also returned in the NSError as keys "HTTPAuthorization" and "HTTPAuthenticateHeader"
(although this is of limited use since this info won't make it all the way up to the public replication API, yet.)
This should help in diagnosing issue #242.
  • Loading branch information...
commit 9296c47cc822f4d8a7f4b513603b4f623c4a3b8f 1 parent ec50437
@snej snej authored
View
41 Source/ChangeTracker/TDSocketChangeTracker.m
@@ -68,7 +68,8 @@ - (BOOL) start {
// .hasPassword when setting _credential earlier. (See #195.) Keychain bug??
// If this happens, try looking up the credential again:
LogTo(ChangeTracker, @"Huh, couldn't get password of %@; trying again", _credential);
- _credential = [self credentialForResponse: _unauthResponse];
+ _credential = [self credentialForAuthHeader:
+ [self authHeaderForResponse: _unauthResponse]];
password = _credential.password;
}
if (password) {
@@ -171,13 +172,17 @@ - (BOOL) checkSSLCert {
}
-- (NSURLCredential*) credentialForResponse: (CFHTTPMessageRef)response {
+- (NSString*) authHeaderForResponse: (CFHTTPMessageRef)response {
+ return CFBridgingRelease(CFHTTPMessageCopyHeaderFieldValue(response,
+ CFSTR("WWW-Authenticate")));
+}
+
+
+- (NSURLCredential*) credentialForAuthHeader: (NSString*)authHeader {
NSString* realm;
NSString* authenticationMethod;
// Basic & digest auth: http://www.ietf.org/rfc/rfc2617.txt
- NSString* authHeader = CFBridgingRelease(CFHTTPMessageCopyHeaderFieldValue(response,
- CFSTR("WWW-Authenticate")));
if (!authHeader)
return nil;
@@ -214,25 +219,33 @@ - (BOOL) readResponseHeader {
kCFStreamPropertyHTTPResponseHeader);
Assert(response);
_gotResponseHeaders = true;
+ NSDictionary* errorInfo = nil;
// Handle authentication failure (401 or 407 status):
CFIndex status = CFHTTPMessageGetResponseStatusCode(response);
LogTo(ChangeTracker, @"%@ got status %ld", self, status);
- if ((status == 401 || status == 407) && !_credential
- && ![_requestHeaders objectForKey: @"Authorization"]) {
- _credential = [self credentialForResponse: response];
- LogTo(ChangeTracker, @"%@: Auth challenge; credential = %@", self, _credential);
- if (_credential) {
- // Recoverable auth failure -- try again with _credential:
- _unauthResponse = response;
- [self errorOccurred: TDStatusToNSError((TDStatus)status, self.changesFeedURL)];
- return NO;
+ if (status == 401 || status == 407) {
+ NSString* authorization = [_requestHeaders objectForKey: @"Authorization"];
+ NSString* authResponse = [self authHeaderForResponse: response];
+ if (!_credential && !authorization) {
+ _credential = [self credentialForAuthHeader: authResponse];
+ LogTo(ChangeTracker, @"%@: Auth challenge; credential = %@", self, _credential);
+ if (_credential) {
+ // Recoverable auth failure -- close socket but try again with _credential:
+ _unauthResponse = response;
+ [self errorOccurred: TDStatusToNSError((TDStatus)status, self.changesFeedURL)];
+ return NO;
+ }
}
+ Log(@"%@: HTTP auth failed; sent Authorization: %@ ; got WWW-Authenticate: %@",
+ self, authorization, authResponse);
+ errorInfo = $dict({@"HTTPAuthorization", authorization},
+ {@"HTTPAuthenticateHeader", authResponse});
}
CFRelease(response);
if (status >= 300) {
- self.error = TDStatusToNSError(status, self.changesFeedURL);
+ self.error = TDStatusToNSErrorWithInfo(status, self.changesFeedURL, errorInfo);
[self stop];
return NO;
}
View
1  Source/TDStatus.h
@@ -49,3 +49,4 @@ static inline bool TDStatusIsError(TDStatus status) {return status >= 300;}
int TDStatusToHTTPStatus( TDStatus status, NSString** outMessage );
NSError* TDStatusToNSError( TDStatus status, NSURL* url );
+NSError* TDStatusToNSErrorWithInfo( TDStatus status, NSURL* url, NSDictionary* extraInfo );
View
13 Source/TDStatus.m
@@ -61,11 +61,18 @@ int TDStatusToHTTPStatus( TDStatus status, NSString** outMessage ) {
}
-NSError* TDStatusToNSError( TDStatus status, NSURL* url ) {
+NSError* TDStatusToNSErrorWithInfo( TDStatus status, NSURL* url, NSDictionary* extraInfo ) {
NSString* reason;
status = TDStatusToHTTPStatus(status, &reason);
- NSDictionary* info = $dict({NSURLErrorKey, url},
+ NSMutableDictionary* info = $mdict({NSURLErrorKey, url},
{NSLocalizedFailureReasonErrorKey, reason},
{NSLocalizedDescriptionKey, $sprintf(@"%i %@", status, reason)});
- return [NSError errorWithDomain: TDHTTPErrorDomain code: status userInfo: info];
+ if (extraInfo)
+ [info addEntriesFromDictionary: extraInfo];
+ return [NSError errorWithDomain: TDHTTPErrorDomain code: status userInfo: [info copy]];
+}
+
+
+NSError* TDStatusToNSError( TDStatus status, NSURL* url ) {
+ return TDStatusToNSErrorWithInfo(status, url, nil);
}
Please sign in to comment.
Something went wrong with that request. Please try again.