static Exception MaybeWrap(HttpTransportAsyncResult self, Exception e) { var we = e as WebException; if (we != null) { var status = we.Status; if (we.Status == WebExceptionStatus.Timeout || self.timedOut) { self.timedOut = true; status = WebExceptionStatus.Timeout; } else if (we.Status == WebExceptionStatus.RequestCanceled || self.cancelled) { self.cancelled = true; status = WebExceptionStatus.RequestCanceled; } e = new WebException(null, we, status, null); } if (self.timedOut) { return(new TimeoutException(self.timedOutReason.ToString() + " timed out", e)); } if (self.cancelled) { return(new OperationCanceledException(e.Message, e)); } return(e); }
static void WriteToRequestStream(HttpTransportAsyncResult self, Stream stream, HttpContent content) { if (self.timedOut) { throw new TimeoutException(); } if (self.cancelled) { throw new OperationCanceledException(); } self.timedOutReason = TimeoutReason.WriteToRequestStream; try { Trace(self, "starting to writeto"); content.WriteTo(stream); Trace(self, "ending writeto"); } catch (Exception e) { Trace(self, "got exception during writeto: " + e); throw; } stream.Close(); Trace(self, "closed request stream"); }
static HttpResponseMessage PopulateResponse(HttpTransportAsyncResult self) { HttpResponseMessage response; Trace(self, "PopulateResponse"); var webResponse = self.webResponse; long?len = null; if (webResponse.ContentLength != -1) { len = webResponse.ContentLength; } response = new HttpResponseMessage() { Request = self.request, Content = HttpContent.Create(new HttpWebResponseInputStream(webResponse), webResponse.ContentType, len), Uri = webResponse.ResponseUri, StatusCode = webResponse.StatusCode, Method = webResponse.Method, }; if (webResponse.IsFromCache) { response.Properties.Add(CacheResponseProperty.LoadFrom(self.webRequest.CachePolicy, webResponse)); } var webResponseHeaders = webResponse.Headers; var responseHeaders = response.Headers; CopyHeadersFromHttpWebResponse(webResponseHeaders, responseHeaders); if (response.Method == "HEAD") { response.Content.LoadIntoBuffer(); } var webRequestHeaders = self.webRequest.Headers; var requestHeaders = self.request.Headers; foreach (var newHeader in webRequestHeaders.AllKeys) { if (!requestHeaders.ContainsKey(newHeader)) { requestHeaders.Add(newHeader, webRequestHeaders[newHeader]); } } if (self.settings.Cookies != null) { self.settings.Cookies.Add(webResponse.Cookies); response.Properties.Add(new CookieCollection() { webResponse.Cookies }); } return(response); }
protected internal override void EndProcessRequestAndTryGetResponse(IAsyncResult result, out HttpResponseMessage response, out object state) { var resp = HttpTransportAsyncResult.End(result); Debug.Assert(resp != null); response = resp; state = null; }
static void MaybeAbort(HttpTransportAsyncResult self, bool timedOut) { Trace(self, (timedOut ? "timed out " : "completed ") + self.request.ToString()); if (timedOut) { self.timedOut = true; self.timedOutAt = DateTime.UtcNow; self.Cancel(); } }
static void CreateAndPrepareWebRequest(HttpTransportAsyncResult self) { Trace(self, "CreateAndPrepareRequest"); var request = self.request; var settings = self.settings; var http = (HttpWebRequest)WebRequest.Create(request.Uri); http.Method = request.Method; CopySettingsToHttpWebRequest(settings, http); HttpWebRequestTransportSettings messageSettings = request.GetPropertyOrDefault <HttpWebRequestTransportSettings>(); if (messageSettings != null) { CopySettingsToHttpWebRequest(messageSettings, http); } var calc = HttpMessageCore.CalculateEffectiveContentType(request); if (calc != request.Headers.ContentType) { request.Headers.ContentType = calc; } if (!HttpContent.IsNullOrEmpty(request.Content) && request.Content.HasLength()) { if (request.Headers.ContentLength == null) { request.Headers.ContentLength = request.Content.GetLength(); } } CopyHeadersToHttpWebRequest(request.Headers, http); if (http.Method == "GET" && http.ContentLength >= 0) { throw new NotSupportedException("can't set Content-Length to " + http.ContentLength + " on " + http.Method); } if (http.Method == "GET" && !HttpContent.IsNullOrEmpty(request.Content)) { throw new NotSupportedException("can't set a non-IsEmpty content on a GET: " + self.request.Content); } self.webRequest = http; }
static void EndGetRequestStreamAndWrite(IAsyncResult result) { if (result.CompletedSynchronously) { return; } HttpTransportAsyncResult self = (HttpTransportAsyncResult)result.AsyncState; Trace(self, "EndGetRequestStreamAndWrite"); try { self.stayedSync = false; var stream = self.webRequest.EndGetRequestStream(result); Debug.Assert(!self.stayedSync); var content = self.request.Content; WriteToRequestStream(self, stream, content); self.timedOutReason = TimeoutReason.GetResponse; var result2 = self.webRequest.BeginGetResponse(EndGetResponseCallback, self); Trace(self, "started begingetresponse"); self.stayedSync = false; if (result2.CompletedSynchronously) { Trace(self, "begingetresponse completed sync"); PopulateWebResponse(self, result2, PopulateWebResponseEndSyncFunc); } else { self.RegisterAbortTimeout(result2, TimeoutReason.GetResponse); } } catch (Exception e) { if (IsFatal(e)) { throw; } self.Complete(e); } }
public TimeoutState(WaitHandle handle, Action <HttpTransportAsyncResult, bool> callback, HttpTransportAsyncResult value) { this.handle = handle; this.callback = callback; this.value = value; }
public static void Register(WaitHandle handle, Action <HttpTransportAsyncResult, bool> callback, HttpTransportAsyncResult value, TimeSpan timeout) { value.TimeoutStarted = DateTime.UtcNow.TimeOfDay; var x = new TimeoutState(handle, callback, value); var h = ThreadPool.RegisterWaitForSingleObject(handle, TimeoutState.StaticWaitOrTimerCallback, x, timeout, true); x.Registered = h; }
static void Trace(HttpTransportAsyncResult self, string s) { #if DEBUG && TRACE Debug.WriteLine(DateTime.UtcNow.TimeOfDay - self.started + " " + string.Format("transport thread 0x{0} : {1}", System.Threading.Thread.CurrentThread.ManagedThreadId.ToString("x2"), s)); #endif }
static void PopulateWebResponse(HttpTransportAsyncResult self, IAsyncResult result, Func <WebRequest, IAsyncResult, WebResponse> getResponse) { Trace(self, "PopulateWebResponse " + getResponse); Debug.Assert(getResponse == PopulateWebResponseSyncFunc || getResponse == PopulateWebResponseEndAsyncFunc || getResponse == PopulateWebResponseEndSyncFunc); HttpResponseMessage responseMessage = null; try { self.webResponse = (HttpWebResponse)getResponse(self.webRequest, result); } catch (System.Net.WebException ex) { self.webResponse = ex.Response as HttpWebResponse; // if an SSL request fails, the inner exception will be populated if (self.webResponse == null || ex.InnerException != null) { if (ex.Response != null) { try { ex.Response.Close(); } catch (Exception duringClose) { Debug.WriteLine(duringClose); if (IsFatal(duringClose)) { throw; } ex.Data["CloseException"] = duringClose; } } self.Complete(ex); return; } // we got a webexception because of a status code, so we treat this as normal Debug.Assert(self.webResponse != null); } catch (Exception e) { if (IsFatal(e)) { throw; } self.Complete(e); return; } try { responseMessage = PopulateResponse(self); self.Complete(self.stayedSync, responseMessage); } catch (Exception e) { if (IsFatal(e)) { throw; } self.Complete(e); } }
protected internal override void ProcessRequestAndTryGetResponse(HttpRequestMessage request, out HttpResponseMessage response, out object state) { var result = new HttpTransportAsyncResult(true, request, this.Settings, null, null); EndProcessRequestAndTryGetResponse(result, out response, out state); }