コード例 #1
0
ファイル: HttpConfig.cs プロジェクト: gusty/WebLinq
        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);
        }
コード例 #2
0
 public Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpConfig config) =>
 _send(_client.SendAsync, request, config);
コード例 #3
0
 public IHttpClient WithConfig(HttpConfig config) =>
 new DelegatingHttpClient(_client.WithConfig(config), _send);
コード例 #4
0
 public Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpConfig config) =>
 _client.WithConfig(Config).SendAsync(request, config);
コード例 #5
0
 public IHttpClient WithConfig(HttpConfig config)
 {
     Config = config;
     return(this);
 }
コード例 #6
0
        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));
            }
        }
コード例 #7
0
 public Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpConfig config) =>
 Send(request, config ?? Config);
コード例 #8
0
 public IHttpClient WithConfig(HttpConfig config) =>
 new DefaultHttpClient(config);
コード例 #9
0
 public DefaultHttpClient(HttpConfig config)
 {
     Config = config;
 }
コード例 #10
0
        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();
            }
        }
コード例 #11
0
        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);
        }
コード例 #12
0
ファイル: HttpConfig.cs プロジェクト: gusty/WebLinq
 HttpConfig(HttpConfig other) :
     this(other.Timeout, other.UseDefaultCredentials, other.Credentials, other.UserAgent, other.Cookies)
 {
 }
コード例 #13
0
ファイル: HttpConfig.cs プロジェクト: gusty/WebLinq
        static HttpConfig()
        {
            var req = WebRequest.CreateHttp("http://localhost/");

            Default = new HttpConfig(TimeSpan.FromMilliseconds(req.Timeout), req.UseDefaultCredentials, req.Credentials, req.UserAgent, req.CookieContainer);
        }
コード例 #14
0
        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();
            }
        }
コード例 #15
0
 public virtual HttpResponseMessage Send(HttpRequestMessage request, HttpConfig config, HttpOptions options) =>
 SendAsync(request, config, options).Result;