Question about permanent error in Couchbase Lite iOS from CBLMisc

74 views
Skip to first unread message

Rustam Yuzmukhametov

unread,
Jul 30, 2014, 9:36:20 AM7/30/14
to mobile-c...@googlegroups.com
In my application I use a pull replication with external CouchDB database and when my application send invalid credentials the pull replication still remains active and try reconnect. After some researches I found that change tracker use CBLIsPermanentError method for checking received error. It considered an invalid credential error as permanent. Here CBLIsPermanentError implementation:

BOOL CBLIsPermanentError( NSError* error ) {
   
NSString* domain = error.domain;
   
NSInteger code = error.code;
   
if ($equal(domain, NSURLErrorDomain)) {
       
return code == NSURLErrorBadURL || code == NSURLErrorUnsupportedURL;
   
} else if ($equal(domain, CBLHTTPErrorDomain)) {
       
return code >= 400 && code <= 499;
   
} else {
       
return NO;
   
}
}

My question is why CBLHTTPErrorDomain error with code 401 (kCBLStatusUnauthorized)  considered as permanent error and NSURLErrorDomain error with code -1013 (kCFURLErrorUserAuthenticationRequired) didn't consider as permanent error although both errors have common meaning.

I use 1.0.1 release version.

Thanks!

Jens Alfke

unread,
Jul 30, 2014, 1:17:51 PM7/30/14
to mobile-c...@googlegroups.com

On Jul 30, 2014, at 6:36 AM, Rustam Yuzmukhametov <ryuzmuk...@gmail.com> wrote:

My question is why CBLHTTPErrorDomain error with code 401 (kCBLStatusUnauthorized)  considered as permanent error and NSURLErrorDomain error with code -1013 (kCFURLErrorUserAuthenticationRequired) didn't consider as permanent error although both errors have common meaning.

It’s just because I’ve never seen the second error occur before — I thought all HTTP auth failures would result in a 401.
I can definitely add that error to CBLIsPermanentError, but I’m curious where it’s coming from. What sort of auth are you performing?

—Jens

Jens Alfke

unread,
Jul 30, 2014, 1:23:53 PM7/30/14
to mobile-c...@googlegroups.com
I’ve now added that error code, in commit e719050.

—Jens

Rustam Yuzmukhametov

unread,
Jul 31, 2014, 4:44:58 AM7/31/14
to mobile-c...@googlegroups.com
In my app I use HTTP Basic Auth. I recreated this behaviour in 'Grocery Sync iOS Demo'. For simplicity I left only one pull replication. I specified syncpoint as CouchDB database in my local network and I inserted credentials in URL string representation. In my case it looked like this:
Password "admin1" isn't correct. I used Sync, SyncVerbose, ChangeTracker, RemoteRequest log channels.  Below You can find attached log file.

From logs I understood following: 

The pull replication tried fetch last sequence and got unauthorized error.
01:16:28.959 Sync: CBL_Puller[http://admin:*****@192.168.20.103:5984/startup_layer7]: Error fetching last sequence: 401 unauthorized

It decided retry  in 60 sec
01:16:28.961 Sync: CBL_Puller[http://admin:*****@192.168.20.103:5984/startup_layer7]: Failed to xfer 0 revisions; will retry in 60 sec

Change tracker is started:
01:17:28.969 SyncVerbose: CBLSocketChangeTracker[0x14e8fda0 startup_layer7]: GET //admin:adm...@192.168.20.103:5984/startup_layer7/_changes?feed=normal&heartbeat=300000&style=all_docs

It got error and this error the replication didn't consider as permanent. So it tried to establish connection after 2, 4, 8 ... seconds.
01:17:35.190 CBLSocketChangeTracker[0x14e8fda0 startup_layer7]: Connection error #1, retrying in 2.0 sec: The operation couldn’t be completed. (NSURLErrorDomain error -1013.)
01:17:37.233 CBLSocketChangeTracker[0x14e8fda0 startup_layer7]: Connection error #2, retrying in 4.0 sec: The operation couldn’t be completed. (NSURLErrorDomain error -1013.)
01:17:41.287 CBLSocketChangeTracker[0x14e8fda0 startup_layer7]: Connection error #3, retrying in 8.0 sec: The operation couldn’t be completed. (NSURLErrorDomain error -1013.)


среда, 30 июля 2014 г., 23:17:51 UTC+6 пользователь Jens Alfke написал:
log.txt

Jens Alfke

unread,
Jul 31, 2014, 12:56:09 PM7/31/14
to mobile-c...@googlegroups.com

> On Jul 31, 2014, at 1:44 AM, Rustam Yuzmukhametov <ryuzmuk...@gmail.com> wrote:
>
> In my app I use HTTP Basic Auth. I recreated this behaviour in 'Grocery Sync iOS Demo'. For simplicity I left only one pull replication. I specified syncpoint as CouchDB database in my local network and I inserted credentials … Password "admin1" isn't correct.

Thanks. This, embarrassingly, reveals several bugs, even though it’s such a simple test. We do have a unit test to check auth failures, but it’s too low-level to catch this situation.

I’m adding higher-level tests now, and fixing the bugs.

—Jens

Jens Alfke

unread,
Jul 31, 2014, 7:19:45 PM7/31/14
to mobile-c...@googlegroups.com
I’ve added some commits that fix the auth problems, and new unit tests that exercise auth failures.
Not mentioned in the commit logs is that a continuous replication now stops completely if it gets a 401 error.

—Jens


commit 5e8b5c79346ee0d9020ed63e28bae2117b621eda
Author: Jens Alfke <je...@couchbase.com>
Date: Thu Jul 31 11:42:26 2014 -0700

Added unit tests that force replicator auth failures

commit 3f90b97d9cd9c3e609cf9e9ca799c3cb737f6d34
Author: Jens Alfke <je...@couchbase.com>
Date: Thu Jul 31 11:16:52 2014 -0700

ChangeTracker should map NSURLErrorUserAuthenticationRequired to 401

The HTTPLogic class returns the lower-level code, but everywhere else
we use 401.

commit 3ff9c7a7213b59646dcfec489ef8d86a7bdfebf5
Author: Jens Alfke <je...@couchbase.com>
Date: Thu Jul 31 11:15:10 2014 -0700

When retrying a replication, make sure to get session & checkpoint

Especially important if the replication initially failed to create a
session or fetch the remote checkpoint, because then we don't have one
at all. (This could have been causing checkpoint conflict errors.)

Reply all
Reply to author
Forward
0 new messages