public Task<HttpResponseMessage> SendAsync(HttpRequestMessage message, HttpCompletionOption option, CancellationToken token) { #if NET_3_5 if(_connectionCount >= _connectionLimit) { return Task.Delay(500).ContinueWith(t => SendAsync(message, option, token)).Unwrap(); } Interlocked.Increment(ref _connectionCount); #else return _sendSemaphore.WaitAsync().ContinueWith(t => { #endif var challengeResponseAuth = Authenticator as IChallengeResponseAuthenticator; if (challengeResponseAuth != null) { if (_authHandler != null) { _authHandler.Authenticator = challengeResponseAuth; } challengeResponseAuth.PrepareWithRequest(message); } var authHeader = AuthUtils.GetAuthenticationHeaderValue(Authenticator, message.RequestUri); if (authHeader != null) { _httpClient.DefaultRequestHeaders.Authorization = authHeader; } return _httpClient.SendAsync(message, option, token); #if !NET_3_5 }).Unwrap().ContinueWith(t => { _sendSemaphore.Release(); return t.Result; }); #endif }
public void TestGetAuthenticationHeaderValue() { var username1 = "username1"; var password1 = "password1"; var credParam1 = Convert.ToBase64String( Encoding.UTF8.GetBytes(string.Format("{0}:{1}", username1, password1))); var auth = AuthenticatorFactory.CreateBasicAuthenticator(username1, password1); var authHeader = AuthUtils.GetAuthenticationHeaderValue(auth, null); Assert.IsNotNull(authHeader); Assert.AreEqual(credParam1, authHeader.Parameter); var username2 = "username2"; var password2 = "password2"; var credParam2 = Convert.ToBase64String( Encoding.UTF8.GetBytes(string.Format("{0}:{1}", username2, password2))); var userinfo = username2 + ":" + password2; var uri = new Uri("http://" + userinfo + "@couchbase.com"); var request = new HttpRequestMessage(HttpMethod.Get, uri); authHeader = AuthUtils.GetAuthenticationHeaderValue(auth, request.RequestUri); Assert.IsNotNull(authHeader); Assert.AreEqual(credParam2, authHeader.Parameter); uri = new Uri("http://www.couchbase.com"); request = new HttpRequestMessage(HttpMethod.Get, uri); authHeader = AuthUtils.GetAuthenticationHeaderValue(null, request.RequestUri); Assert.IsNull(authHeader); auth = AuthenticatorFactory.CreateFacebookAuthenticator("1234"); authHeader = AuthUtils.GetAuthenticationHeaderValue(auth, null); Assert.IsNull(authHeader); }
public virtual void Run() { Log.V(Tag, "{0}: RemoteRequest run() called, url: {1}".Fmt(this, url)); HttpClient httpClient = null; try { httpClient = clientFactory.GetHttpClient(); //var manager = httpClient.GetConnectionManager(); var authHeader = AuthUtils.GetAuthenticationHeaderValue(Authenticator, requestMessage.RequestUri); if (authHeader != null) { httpClient.DefaultRequestHeaders.Authorization = authHeader; } requestMessage.Headers.Add("Accept", "multipart/related, application/json"); AddRequestHeaders(requestMessage); SetBody(requestMessage); ExecuteRequest(httpClient, requestMessage); Log.V(Tag, "{0}: RemoteRequest run() finished, url: {1}".Fmt(this, url)); } finally { if (httpClient != null) { httpClient.Dispose(); } } }
public override void Run() { HttpClient httpClient = null; try { httpClient = clientFactory.GetHttpClient(); requestMessage.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("multipart/related")); var authHeader = AuthUtils.GetAuthenticationHeaderValue(Authenticator, requestMessage.RequestUri); if (authHeader != null) { httpClient.DefaultRequestHeaders.Authorization = authHeader; } //TODO: implement gzip support for server response see issue #172 //request.addHeader("X-Accept-Part-Encoding", "gzip"); AddRequestHeaders(requestMessage); SetBody(requestMessage); ExecuteRequest(httpClient, requestMessage); } finally { if (httpClient != null) { httpClient.Dispose(); } } }
public override bool Start() { if (IsRunning) { return(false); } IsRunning = true; Log.To.ChangeTracker.I(Tag, "Starting {0}...", this); _cts = new CancellationTokenSource(); var authHeader = AuthUtils.GetAuthenticationHeaderValue(Authenticator, ChangesFeedUrl); // A WebSocket has to be opened with a GET request, not a POST (as defined in the RFC.) // Instead of putting the options in the POST body as with HTTP, we will send them in an // initial WebSocket message _usePost = false; _caughtUp = false; _client = new WebSocket(ChangesFeedUrl.AbsoluteUri); _client.WaitTime = TimeSpan.FromSeconds(2); _client.OnOpen += OnConnect; _client.OnMessage += OnReceive; _client.OnError += OnError; _client.OnClose += OnClose; if (authHeader != null) { _client.CustomHeaders = new Dictionary <string, string> { ["Authorization"] = authHeader.ToString() }; } _client.ConnectAsync(); return(true); }
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage message, HttpCompletionOption option, CancellationToken token) { #if NET_3_5 if(_connectionCount >= _connectionLimit) { return Task.Delay(500).ContinueWith(t => SendAsync(message, option, token)).Unwrap(); } Interlocked.Increment(ref _connectionCount); #else return _sendSemaphore?.WaitAsync()?.ContinueWith(t => { #endif var challengeResponseAuth = Authenticator as IChallengeResponseAuthenticator; if (challengeResponseAuth != null) { _authHandler.Borrow(x => x.Authenticator = challengeResponseAuth); challengeResponseAuth.PrepareWithRequest(message); } var httpClient = default(HttpClient); if(!_httpClient.AcquireTemp(out httpClient)) { return null; } var authHeader = AuthUtils.GetAuthenticationHeaderValue(Authenticator, message.RequestUri); if (authHeader != null) { httpClient.DefaultRequestHeaders.Authorization = authHeader; } return httpClient.SendAsync(message, option, token); #if !NET_3_5 })?.Unwrap()?.ContinueWith(t => { _sendSemaphore?.Release(); if(t.IsFaulted) { var e = t.Exception; if(Misc.UnwrapAggregate(e) is ObjectDisposedException) { return null; } throw e; } return t.Result; }); #endif }
public virtual void Run() { Log.V(Tag, "{0}: RemoteRequest run() called, url: {1}".Fmt(this, url)); HttpClient httpClient = null; var requestMessage = CreateConcreteRequest(); httpClient = clientFactory.GetHttpClient(false); var challengeResponseAuth = Authenticator as IChallengeResponseAuthenticator; if (challengeResponseAuth != null) { var authHandler = clientFactory.Handler as DefaultAuthHandler; if (authHandler != null) { authHandler.Authenticator = challengeResponseAuth; } challengeResponseAuth.PrepareWithRequest(requestMessage); } var authHeader = AuthUtils.GetAuthenticationHeaderValue(Authenticator, requestMessage.RequestUri); if (authHeader != null) { httpClient.DefaultRequestHeaders.Authorization = authHeader; } requestMessage.Headers.Add("Accept", "multipart/related, application/json"); AddRequestHeaders(requestMessage); SetBody(requestMessage); ExecuteRequest(httpClient, requestMessage).ContinueWith(t => { Log.V(Tag, "{0}: RemoteRequest run() finished, url: {1}".Fmt(this, url)); if (httpClient != null) { httpClient.Dispose(); } requestMessage.Dispose(); }); }
public Task <HttpResponseMessage> SendAsync(HttpRequestMessage message, HttpCompletionOption option, CancellationToken token) { var challengeResponseAuth = Authenticator as IChallengeResponseAuthenticator; if (challengeResponseAuth != null) { if (_authHandler != null) { _authHandler.Authenticator = challengeResponseAuth; } challengeResponseAuth.PrepareWithRequest(message); } var authHeader = AuthUtils.GetAuthenticationHeaderValue(Authenticator, message.RequestUri); if (authHeader != null) { _httpClient.DefaultRequestHeaders.Authorization = authHeader; } return(_httpClient.SendAsync(message, option, token)); }
// TODO: Needs to refactored into smaller calls. Each continuation could be its own method, for example. public void Run() { IsRunning = true; var clientCopy = client; if (clientCopy == null) { // This is a race condition that can be reproduced by calling cbpuller.start() and cbpuller.stop() // directly afterwards. What happens is that by the time the Changetracker thread fires up, // the cbpuller has already set this.client to null. See issue #109 Log.W(Tag, "ChangeTracker run() loop aborting because client == null"); return; } if (tokenSource.IsCancellationRequested) { tokenSource.Dispose(); tokenSource = new CancellationTokenSource(); } backoff = new ChangeTrackerBackoff(); while (IsRunning && !tokenSource.Token.IsCancellationRequested) { if (Request != null) { Request.Dispose(); Request = null; } var url = GetChangesFeedURL(); if (UsePost) { Request = new HttpRequestMessage(HttpMethod.Post, url); var body = GetChangesFeedPostBody(); Request.Content = new StringContent(body); Request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); } else { Request = new HttpRequestMessage(HttpMethod.Get, url); } AddRequestHeaders(Request); var maskedRemoteWithoutCredentials = url.ToString(); maskedRemoteWithoutCredentials = maskedRemoteWithoutCredentials.ReplaceAll("://.*:.*@", "://---:---@"); Log.V(Tag, "Making request to " + maskedRemoteWithoutCredentials); if (tokenSource.Token.IsCancellationRequested) { break; } Task <HttpResponseMessage> changesRequestTask = null; Task <HttpResponseMessage> successHandler; Task <Boolean> errorHandler; HttpClient httpClient = null; try { httpClient = clientCopy.GetHttpClient(); var authHeader = AuthUtils.GetAuthenticationHeaderValue(Authenticator, Request.RequestUri); if (authHeader != null) { httpClient.DefaultRequestHeaders.Authorization = authHeader; } changesFeedRequestTokenSource = CancellationTokenSource.CreateLinkedTokenSource(tokenSource.Token); var evt = new ManualResetEvent(false); // We do this akward set of calls in order // to help minimize the frequency of the error: // // "Cannot re-call start of asynchronous method // while a previous call is still in progress." // // There's got to be a better way to deal with this. var info = httpClient.SendAsync( Request, changesFeedRequestTokenSource.Token ); info.ContinueWith((t) => evt.Set() ); if (evt.WaitOne(ManagerOptions.Default.RequestTimeout) == false) { Log.W(Tag, "SendAsync timeout"); continue; } changesRequestTask = info; successHandler = changesRequestTask.ContinueWith <HttpResponseMessage>( ChangeFeedResponseHandler, changesFeedRequestTokenSource.Token, TaskContinuationOptions.LongRunning | TaskContinuationOptions.OnlyOnRanToCompletion, WorkExecutor.Scheduler ); errorHandler = changesRequestTask.ContinueWith(t => { if (t.IsCanceled) { return(false); // Not a real error. } var err = t.Exception.Flatten(); Log.D(Tag, "ChangeFeedResponseHandler faulted.", err.InnerException ?? err); Error = err.InnerException ?? err; backoff.SleepAppropriateAmountOfTime(); return(true); // a real error. }, changesFeedRequestTokenSource.Token, TaskContinuationOptions.OnlyOnFaulted, WorkExecutor.Scheduler); try { Task.WaitAll(new Task[] { successHandler, errorHandler }, (Int32)ManagerOptions.Default.RequestTimeout.TotalMilliseconds, changesFeedRequestTokenSource.Token); Log.D(Tag, "Finished processing changes feed."); } catch (Exception ex) { var e = ex.InnerException ?? ex; // Swallow TaskCancelledExceptions, which will always happen // if either errorHandler or successHandler don't need to fire. if (!(e is OperationCanceledException)) { throw ex; } } finally { if (changesRequestTask != null) { if (changesRequestTask.IsCompleted) { changesRequestTask.Dispose(); } changesRequestTask = null; } if (successHandler != null) { if (successHandler.IsCompleted) { successHandler.Dispose(); } successHandler = null; } if (errorHandler != null) { if (errorHandler.IsCompleted) { errorHandler.Dispose(); } errorHandler = null; } if (Request != null) { Request.Dispose(); Request = null; } if (changesFeedRequestTokenSource != null) { changesFeedRequestTokenSource.Dispose(); changesFeedRequestTokenSource = null; } } } catch (Exception e) { if (!IsRunning && e.InnerException is IOException) { // swallow } else { // in this case, just silently absorb the exception because it // frequently happens when we're shutting down and have to // close the socket underneath our read. Log.E(Tag, "Exception in change tracker", e); } backoff.SleepAppropriateAmountOfTime(); } finally { if (httpClient != null) { httpClient.Dispose(); } if (mode == ChangeTrackerMode.OneShot) { Stop(); } } } }
public void Run() { IsRunning = true; var clientCopy = client; if (clientCopy == null) { // This is a race condition that can be reproduced by calling cbpuller.start() and cbpuller.stop() // directly afterwards. What happens is that by the time the Changetracker thread fires up, // the cbpuller has already set this.client to null. See issue #109 Log.W(TAG, "ChangeTracker run() loop aborting because client == null"); return; } if (tokenSource.IsCancellationRequested) { tokenSource.Dispose(); tokenSource = new CancellationTokenSource(); } backoff = new ChangeTrackerBackoff(); _startTime = DateTime.Now; if (Request != null) { Request.Dispose(); Request = null; } var url = GetChangesFeedURL(); Request = new HttpRequestMessage(HttpMethod.Post, url); var body = GetChangesFeedPostBody(); Request.Content = new StringContent(body); Request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); AddRequestHeaders(Request); var maskedRemoteWithoutCredentials = url.ToString(); maskedRemoteWithoutCredentials = maskedRemoteWithoutCredentials.ReplaceAll("://.*:.*@", "://---:---@"); Log.V(TAG, "Making request to " + maskedRemoteWithoutCredentials); if (tokenSource.Token.IsCancellationRequested) { return; } HttpClient httpClient = null; try { httpClient = clientCopy.GetHttpClient(mode == ChangeTrackerMode.LongPoll); var challengeResponseAuth = Authenticator as IChallengeResponseAuthenticator; if (challengeResponseAuth != null) { challengeResponseAuth.PrepareWithRequest(Request); } var authHeader = AuthUtils.GetAuthenticationHeaderValue(Authenticator, Request.RequestUri); if (authHeader != null) { httpClient.DefaultRequestHeaders.Authorization = authHeader; } changesFeedRequestTokenSource = CancellationTokenSource.CreateLinkedTokenSource(tokenSource.Token); var option = mode == ChangeTrackerMode.LongPoll ? HttpCompletionOption.ResponseHeadersRead : HttpCompletionOption.ResponseContentRead; var info = httpClient.SendAsync( Request, option, changesFeedRequestTokenSource.Token ); info.ContinueWith(t1 => { ChangeFeedResponseHandler(t1).ContinueWith(t2 => { if (httpClient != null) { httpClient.Dispose(); } }); }, changesFeedRequestTokenSource.Token, TaskContinuationOptions.LongRunning, TaskScheduler.Default); } catch (Exception e) { if (!IsRunning && e.InnerException is IOException) { // swallow } else { // in this case, just silently absorb the exception because it // frequently happens when we're shutting down and have to // close the socket underneath our read. Log.E(TAG, "Exception in change tracker", e); } backoff.SleepAppropriateAmountOfTime(); } }
// TODO: Needs to refactored into smaller calls. Each continuation could be its own method, for example. public void Run() { IsRunning = true; if (client == null) { // This is a race condition that can be reproduced by calling cbpuller.start() and cbpuller.stop() // directly afterwards. What happens is that by the time the Changetracker thread fires up, // the cbpuller has already set this.client to null. See issue #109 Log.W(Tag, "ChangeTracker run() loop aborting because client == null"); return; } if (tokenSource.IsCancellationRequested) { tokenSource.Dispose(); tokenSource = new CancellationTokenSource(); } backoff = new ChangeTrackerBackoff(); while (IsRunning && !tokenSource.Token.IsCancellationRequested) { // if (changesRequestTask != null && !changesRequestTask.IsCanceled && !changesRequestTask.IsFaulted) // { // Thread.Sleep(500); // continue; // } var httpClient = client.GetHttpClient(); if (Request != null) { Request.Dispose(); Request = null; } var url = GetChangesFeedURL(); if (UsePost) { Request = new HttpRequestMessage(HttpMethod.Post, url); var body = GetChangesFeedPostBody(); Request.Content = new StringContent(body); Request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); } else { Request = new HttpRequestMessage(HttpMethod.Get, url); } AddRequestHeaders(Request); var authHeader = AuthUtils.GetAuthenticationHeaderValue(Authenticator, Request.RequestUri); if (authHeader != null) { httpClient.DefaultRequestHeaders.Authorization = authHeader; } var maskedRemoteWithoutCredentials = url.ToString(); maskedRemoteWithoutCredentials = maskedRemoteWithoutCredentials.ReplaceAll("://.*:.*@", "://---:---@"); Log.V(Tag, "Making request to " + maskedRemoteWithoutCredentials); if (tokenSource.Token.IsCancellationRequested) { break; } Task <HttpResponseMessage> changesRequestTask = null; Task <HttpResponseMessage> successHandler; Task <Boolean> errorHandler; try { changesFeedRequestTokenSource = CancellationTokenSource.CreateLinkedTokenSource(tokenSource.Token); var evt = new ManualResetEvent(false); //successHandler.ConfigureAwait(false).GetAwaiter().OnCompleted(()=>evt.Set()); // ChangeFeedResponseHandler(response); var info = httpClient.SendAsync( Request, HttpCompletionOption.ResponseContentRead, changesFeedRequestTokenSource.Token ); var infoAwaiter = info.ConfigureAwait(false).GetAwaiter(); infoAwaiter.OnCompleted(() => evt.Set() ); evt.WaitOne(ManagerOptions.Default.RequestTimeout); changesRequestTask = info; //Task.FromResult(info.Result); successHandler = changesRequestTask.ContinueWith <HttpResponseMessage>( ChangeFeedResponseHandler, changesFeedRequestTokenSource.Token, TaskContinuationOptions.LongRunning | TaskContinuationOptions.OnlyOnRanToCompletion, WorkExecutor.Scheduler ); errorHandler = changesRequestTask.ContinueWith(t => { if (t.IsCanceled) { return(false); // Not a real error. } var err = t.Exception.Flatten(); Log.D(Tag, "ChangeFeedResponseHandler faulted.", err.InnerException ?? err); Error = err.InnerException ?? err; return(true); // a real error. }, changesFeedRequestTokenSource.Token, TaskContinuationOptions.OnlyOnFaulted, WorkExecutor.Scheduler); try { var completedTask = Task.WhenAll(successHandler, errorHandler); completedTask.Wait((Int32)ManagerOptions.Default.RequestTimeout.TotalMilliseconds, changesFeedRequestTokenSource.Token); Log.D(Tag, "Finished processing changes feed."); } catch (Exception ex) { // Swallow TaskCancelledExceptions, which will always happen // if either errorHandler or successHandler don't need to fire. if (!(ex.InnerException is TaskCanceledException)) { throw ex; } } finally { changesRequestTask.Dispose(); changesRequestTask = null; successHandler.Dispose(); successHandler = null; errorHandler.Dispose(); errorHandler = null; Request.Dispose(); Request = null; changesFeedRequestTokenSource.Dispose(); if (httpClient != null) { httpClient.Dispose(); } } } catch (Exception e) { if (!IsRunning && e.InnerException is IOException) { // swallow } else { // in this case, just silently absorb the exception because it // frequently happens when we're shutting down and have to // close the socket underneath our read. Log.E(Tag, "Exception in change tracker", e); } backoff.SleepAppropriateAmountOfTime(); } finally { if (mode == ChangeTrackerMode.OneShot) { Stop(); } } // var singleRequestTokenSource = CancellationTokenSource.CreateLinkedTokenSource(tokenSource.Token); // var cTask = httpClient.SendAsync(Request, HttpCompletionOption.ResponseHeadersRead, singleRequestTokenSource.Token); // var bTask = cTask // .ContinueWith<HttpResponseMessage>(t => // { // if (!IsRunning) // { // return null; // // swallow // } // if (t.IsFaulted && t.Exception.InnerException is IOException) // { // // in this case, just silently absorb the exception because it // // frequently happens when we're shutting down and have to // // close the socket underneath our read. // Log.E(Tag, "Exception in change tracker", t.Exception); // return null; // } // if (!singleRequestTokenSource.IsCancellationRequested && t.Exception != null) // { // var e = t.Exception.InnerException as WebException; // var status = (HttpStatusCode)e.Status; // if ((Int32)status >= 300 && !Misc.IsTransientError(status)) // { // var response = t.Result; // var msg = response.Content != null // ? String.Format("Change tracker got error with status code: {0}", status) // : String.Format("Change tracker got error with status code: {0} and null response content", status); // Log.E(Tag, msg); // Error = new CouchbaseLiteException(msg, new Status(status.GetStatusCode())); // Stop(); // } // backoff.SleepAppropriateAmountOfTime(); // } // return t.Result; // }, singleRequestTokenSource.Token, TaskContinuationOptions.OnlyOnFaulted, WorkExecutor.Scheduler) // .ContinueWith<HttpResponseMessage>(ChangeFeedResponseHandler, singleRequestTokenSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, WorkExecutor.Scheduler) // .ContinueWith<HttpResponseMessage>(t => // { // Log.D(Tag, "ChangeFeedResponseHandler finished."); // singleRequestTokenSource.Token.ThrowIfCancellationRequested(); // if (t != null) t.Result.Dispose(); // return null; // }, singleRequestTokenSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, WorkExecutor.Scheduler); // changesRequestTask = bTask; // .ContinueWith((t) => // { // Log.D(Tag, "ChangeFeedResponseHandler faulted."); // }, singleRequestTokenSource.Token, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent, TaskScheduler.Default); } }