static HttpConfig Set(HttpConfig initial, bool?useDefaultCredentials, bool?useCookies, string userAgent, TimeSpan?timeout) { var config = initial ?? Default; if (useDefaultCredentials != null) { config = config.WithUseDefaultCredentials(useDefaultCredentials.Value); } if (useCookies != null) { config = config.WithCookies(useCookies.Value ? new CookieContainer() : null); } if (userAgent != null) { config = config.WithUserAgent(userAgent); } if (timeout != null) { config = config.WithTimeout(timeout.Value); } return(config); }
public Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpConfig config) => _send(_client.SendAsync, request, config);
public IHttpClient WithConfig(HttpConfig config) => new DelegatingHttpClient(_client.WithConfig(config), _send);
public Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpConfig config) => _client.WithConfig(Config).SendAsync(request, config);
public IHttpClient WithConfig(HttpConfig config) { Config = config; return(this); }
static async Task <HttpResponseMessage> Send(HttpRequestMessage request, HttpConfig config) { var hwreq = WebRequest.CreateHttp(request.RequestUri); hwreq.Method = request.Method.Method; hwreq.Timeout = (int)config.Timeout.TotalMilliseconds; hwreq.AllowAutoRedirect = false; if (config.Credentials != null) { hwreq.Credentials = config.Credentials; } else { hwreq.UseDefaultCredentials = config.UseDefaultCredentials; } if (config.IgnoreInvalidServerCertificate) { hwreq.ServerCertificateValidationCallback = delegate { return(true); } } ; if (config.Cookies?.Any() == true) { CookieContainer cookies; hwreq.CookieContainer = cookies = new CookieContainer(); foreach (var cookie in config.Cookies) { cookies.Add(cookie); } } var userAgent = request.Headers.UserAgent.ToString(); hwreq.UserAgent = userAgent.Length > 0 ? userAgent : config.UserAgent; if (request.Headers.Referrer is Uri referrerUrl) { hwreq.Referer = referrerUrl.AbsoluteUri; } else if (config.Headers.TryGetValue("Referer", out var referrer)) { hwreq.Referer = referrer.FirstOrDefault(); } var accept = request.Headers.Accept.ToString(); if (accept.Length > 0) { hwreq.Accept = accept; } else if (config.Headers.TryGetValue("Accept", out var configAccept)) { hwreq.Accept = configAccept; } var content = request.Content; foreach (var e in from e in request.Headers.Concat(content?.Headers ?? Enumerable.Empty <KeyValuePair <string, IEnumerable <string> > >()) .Concat(from e in config.Headers select e.Key.AsKeyTo(e.Value.AsEnumerable())) .ToLookup(e => e.Key, e => e.Value) .Select(g => g.Key.AsKeyTo(g.First())) where !e.Key.Equals("Content-Type", StringComparison.OrdinalIgnoreCase) && !e.Key.Equals("User-Agent", StringComparison.OrdinalIgnoreCase) && !e.Key.Equals("Referer", StringComparison.OrdinalIgnoreCase) && !e.Key.Equals("Accept", StringComparison.OrdinalIgnoreCase) from v in e.Value select e.Key.AsKeyTo(v)) { hwreq.Headers.Add(e.Key, e.Value); } try { if (content != null) { // ReSharper disable once PossibleNullReferenceException hwreq.ContentType = content.Headers.ContentType.ToString(); using (var s = hwreq.GetRequestStream()) await content.CopyToAsync(s).DontContinueOnCapturedContext(); } return(CreateResponse(hwreq, (HttpWebResponse)await hwreq.GetResponseAsync().DontContinueOnCapturedContext())); } catch (WebException e) when(e.Status == WebExceptionStatus.ProtocolError) { return(CreateResponse(hwreq, (HttpWebResponse)e.Response)); } }
public Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpConfig config) => Send(request, config ?? Config);
public IHttpClient WithConfig(HttpConfig config) => new DefaultHttpClient(config);
public DefaultHttpClient(HttpConfig config) { Config = config; }
static async Task <T> HttpFetchAsync <T>(IHttpClient http, HttpConfig config, HttpMethod method, Uri url, HttpContent content, HttpOptions options, Func <HttpConfig, HttpResponseMessage, T> responseSelector, Func <HttpConfig, HttpMethod, Uri, HttpContent, T> redirectionSelector) { var request = new HttpRequestMessage { Method = method, RequestUri = url, Content = content }; HttpResponseMessage response = null; try { response = await http.SendAsync(request, config) .DontContinueOnCapturedContext(); if (response.Headers.TryGetValues("Set-Cookie", out var setCookies)) { var cc = new CookieContainer(); foreach (var cookie in setCookies) { try { cc.SetCookies(url, cookie); } catch (CookieException) { /* ignore bad cookies */ } } var mergedCookies = from cookies in new[] { http.Config.Cookies ?? Enumerable.Empty <Cookie>(), cc.GetCookies(url).Cast <Cookie>(), } from c in cookies // // According to RFC 6265[1], "cookies for a given host // are shared across all the ports on that host" so // don't take Cookie.Port into account when grouping. // It is also assumed that Cookie.Domain // // [1] https://tools.ietf.org/html/rfc6265#section-1 // group c by new { c.Name, Domain = c.Domain.ToLowerInvariant(), c.Path } into g select g.OrderByDescending(e => e.TimeStamp).First(); config = config.WithCookies(mergedCookies.ToArray()); } // Source: // https://referencesource.microsoft.com/#System/net/System/Net/HttpWebRequest.cs,5669 // // Check for Redirection // // Table View: // Method 301 302 303 307 // * * * GET * // POST GET GET GET POST // // Put another way: // 301 & 302 - All methods are redirected to the same method but POST. POST is redirected to a GET. // 303 - All methods are redirected to GET // 307 - All methods are redirected to the same method. // var sc = response.StatusCode; if (sc == HttpStatusCode.Ambiguous || // 300 sc == HttpStatusCode.Moved || // 301 sc == HttpStatusCode.Redirect || // 302 sc == HttpStatusCode.RedirectMethod || // 303 sc == HttpStatusCode.RedirectKeepVerb) // 307 { var redirectionUrl = response.Headers.Location?.AsRelativeTo(response.RequestMessage.RequestUri); if (redirectionUrl == null) { // 300 // If the server has a preferred choice of representation, // it SHOULD include the specific URI for that // representation in the Location field; user agents MAY // use the Location field value for automatic redirection. if (sc != HttpStatusCode.Ambiguous) { throw new ProtocolViolationException("Server did not supply a URL for a redirection response."); } } else { if (redirectionUrl.Scheme == "ws" || redirectionUrl.Scheme == "wss") { throw new NotSupportedException($"Redirection to a WebSocket URL ({redirectionUrl}) is not supported."); } if (redirectionUrl.Scheme != Uri.UriSchemeHttp && redirectionUrl.Scheme != Uri.UriSchemeHttps) { throw new ProtocolViolationException( $"Server sent a redirection response where the redirection URL ({redirectionUrl}) scheme was neither HTTP nor HTTPS."); } return(sc == HttpStatusCode.RedirectMethod || method == HttpMethod.Post && (sc == HttpStatusCode.Moved || sc == HttpStatusCode.Redirect) ? redirectionSelector(config, HttpMethod.Get, redirectionUrl, null) : redirectionSelector(config, method, redirectionUrl, content)); } } if (!options.ReturnErroneousFetch) { response.EnsureSuccessStatusCode(); } var result = responseSelector(config, response); response = null; // disown return(result); } finally { response?.Dispose(); } }
static HttpConfig() { var req = WebRequest.CreateHttp("http://localhost/"); Default = new HttpConfig(HttpHeaderCollection.Empty, TimeSpan.FromMilliseconds(req.Timeout), req.UseDefaultCredentials, req.Credentials, req.UserAgent, null, false); }
HttpConfig(HttpConfig other) : this(other.Timeout, other.UseDefaultCredentials, other.Credentials, other.UserAgent, other.Cookies) { }
static HttpConfig() { var req = WebRequest.CreateHttp("http://localhost/"); Default = new HttpConfig(TimeSpan.FromMilliseconds(req.Timeout), req.UseDefaultCredentials, req.Credentials, req.UserAgent, req.CookieContainer); }
static async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpConfig config, HttpOptions options) { var hwreq = WebRequest.CreateHttp(request.RequestUri); hwreq.Method = request.Method.Method; hwreq.Timeout = (int)config.Timeout.TotalMilliseconds; hwreq.CookieContainer = config.Cookies; hwreq.Credentials = config.Credentials; hwreq.UseDefaultCredentials = config.UseDefaultCredentials; var userAgent = request.Headers.UserAgent.ToString(); hwreq.UserAgent = userAgent.Length > 0 ? userAgent : config.UserAgent; var referrer = request.Headers.Referrer; if (referrer != null) { hwreq.Referer = referrer.ToString(); } var accept = request.Headers.Accept.ToString(); if (accept.Length > 0) { hwreq.Accept = accept; } var content = request.Content; foreach (var e in from e in request.Headers.Concat(content?.Headers ?? Enumerable.Empty <KeyValuePair <string, IEnumerable <string> > >()) where !e.Key.Equals("Content-Type", StringComparison.OrdinalIgnoreCase) && !e.Key.Equals("User-Agent", StringComparison.OrdinalIgnoreCase) && !e.Key.Equals("Referer", StringComparison.OrdinalIgnoreCase) && !e.Key.Equals("Accept", StringComparison.OrdinalIgnoreCase) from v in e.Value select e.Key.AsKeyTo(v)) { hwreq.Headers.Add(e.Key, e.Value); } HttpWebResponse hwrsp = null; try { if (content != null) { // ReSharper disable once PossibleNullReferenceException hwreq.ContentType = content.Headers.ContentType.ToString(); using (var s = hwreq.GetRequestStream()) await content.CopyToAsync(s); } return(await CreateResponse(hwreq, hwrsp = (HttpWebResponse)hwreq.GetResponse())); } catch (WebException e) when(e.Status == WebExceptionStatus.ProtocolError) { if (!options.ReturnErrorneousFetch) { throw; } return(await CreateResponse(hwreq, hwrsp = (HttpWebResponse)e.Response)); } finally { hwrsp?.Dispose(); } }
public virtual HttpResponseMessage Send(HttpRequestMessage request, HttpConfig config, HttpOptions options) => SendAsync(request, config, options).Result;