protected override HttpResponseMessage ProcessResponse(HttpResponseMessage response, CancellationToken cancellationToken) { int retryCount; do { if (Authenticator != null && response.StatusCode == HttpStatusCode.Unauthorized) { retryCount = _retryMessages.GetOrAdd(response, 0); if (retryCount >= 5) { // Multiple concurrent requests means that the Nc can sometimes get out of order // so try again, but within reason. break; } _retryMessages.TryUpdate(response, retryCount + 1, retryCount); var newRequest = new HttpRequestMessage(response.RequestMessage.Method, response.RequestMessage.RequestUri); foreach (var header in response.RequestMessage.Headers) { if (header.Key != "Authorization") { newRequest.Headers.Add(header.Key, header.Value); } } newRequest.Content = response.RequestMessage.Content; var challengeResponse = Authenticator.ResponseFromChallenge(response); if (challengeResponse != null) { newRequest.Headers.Add("Authorization", challengeResponse); return(ProcessResponse(SendAsync(newRequest, cancellationToken).Result, cancellationToken)); } } } while(false); var hasSetCookie = response.Headers.Contains("Set-Cookie"); if (hasSetCookie) { var cookie = default(Cookie); if (CookieParser.TryParse(response.Headers.GetValues("Set-Cookie").ElementAt(0), response.RequestMessage.RequestUri.Host, out cookie)) { lock (_locker) { try { _cookieStore.Add(cookie); } catch (CookieException e) { var headerValue = new SecureLogString(response.Headers.GetValues("Set-Cookie").ElementAt(0), LogMessageSensitivity.Insecure); Log.To.Sync.W("DefaultAuthHandler", $"Invalid cookie string received from remote: {headerValue}", e); } } } } _retryMessages.TryRemove(response, out retryCount); return(response); }
private void AddRequestHeaders(HttpRequestMessage request) { foreach (var requestHeaderKey in RequestHeaders.Keys) { if (requestHeaderKey.ToLowerInvariant() == "cookie") { Cookie cookie; var cookieStr = RequestHeaders[requestHeaderKey]; if (!CookieParser.TryParse(cookieStr, request.RequestUri.Host, out cookie)) { Log.To.Sync.W(Tag, "Invalid cookie string received, {0}", new SecureLogString(cookieStr, LogMessageSensitivity.Insecure)); } else { try { CookieStore.Add(cookie); } catch (CookieException e) { var headerValue = new SecureLogString(cookieStr, LogMessageSensitivity.Insecure); Log.To.Sync.W(Tag, $"Invalid cookie string received, {headerValue}", e); } } request.Headers.Add("Cookie", CookieStore.GetCookieHeader(request.RequestUri)); continue; } request.Headers.Add(requestHeaderKey, RequestHeaders.Get(requestHeaderKey)); } }
// This is used by the listener internal Replication ReplicationWithProperties(IDictionary <string, object> properties) { // Extract the parameters from the JSON request body: // http://wiki.apache.org/couchdb/Replication bool push, createTarget; var results = new Dictionary <string, object>() { { "database", null }, { "remote", null }, { "headers", null }, { "authorizer", null } }; Status result = ParseReplicationProperties(properties, out push, out createTarget, results); if (result.IsError) { throw Misc.CreateExceptionAndLog(Log.To.Listener, result.Code, TAG, "Failed to create replication"); } object continuousObj = properties.Get("continuous"); bool continuous = false; if (continuousObj is bool) { continuous = (bool)continuousObj; } var scheduler = new SingleTaskThreadpoolScheduler(); Replication rep = null; if (push) { rep = new Pusher((Database)results["database"], (Uri)results["remote"], continuous, new TaskFactory(scheduler)); } else { rep = new Puller((Database)results["database"], (Uri)results["remote"], continuous, new TaskFactory(scheduler)); } rep.Filter = properties.Get("filter") as string; rep.FilterParams = properties.Get("query_params").AsDictionary <string, object>(); rep.DocIds = properties.Get("doc_ids").AsList <string>(); rep.Headers = new Dictionary <string, string>(); foreach (var header in results.Get("headers").AsDictionary <string, string>()) { if (header.Key.ToLowerInvariant() == "cookie") { var cookie = default(Cookie); if (CookieParser.TryParse(header.Value, ((Uri)results["remote"]).GetLeftPart(UriPartial.Authority), out cookie)) { rep.SetCookie(cookie.Name, cookie.Value, cookie.Path, cookie.Expires, cookie.Secure, cookie.HttpOnly); } else { Log.To.Listener.W(TAG, "Invalid cookie string received ({0}), ignoring...", header.Value); } } else { rep.Headers.Add(header.Key, header.Value); } } rep.Headers = results.Get("headers").AsDictionary <string, string>(); rep.Authenticator = results.Get("authorizer") as IAuthenticator; if (push) { ((Pusher)rep).CreateTarget = createTarget; } var db = (Database)results["database"]; // If this is a duplicate, reuse an existing replicator: var activeReplicators = default(IList <Replication>); var existing = default(Replication); if (db.ActiveReplicators.AcquireTemp(out activeReplicators)) { existing = activeReplicators.FirstOrDefault(x => x.LocalDatabase == rep.LocalDatabase && x.RemoteUrl == rep.RemoteUrl && x.IsPull == rep.IsPull && x.RemoteCheckpointDocID().Equals(rep.RemoteCheckpointDocID())); } return(existing ?? rep); }