示例#1
0
            /// <summary>
            /// This is the method that is called to configure the <see cref="NetStd20HttpRequest.RequestClient"/>
            /// and <see cref="NetStd20HttpRequest.RequestHandler"/> returned by <see cref="CreateWebRequest(string, Uri)"/>.
            /// </summary>
            /// <param name="request">Value returned by <see cref="CreateWebRequest(string, Uri)"/>.</param>
            protected override NetStd20HttpRequest ConfigureWebRequest(NetStd20HttpRequest request)
            {
                // Must ensure this method is thread-safe because the parent method will update
                // NetStd20HttpRequest.RequestHandler properties, which is really just calling NamedHttpClientHandlerWrapper.
                // We don't want multiple threads to be updating NamedHttpClientHandlerWrapper properties at the same
                // time because the wrapped HttpClientHandler properties are probably not thread-safe, and we don't want
                // another thread to add to the wrapper while we are updating wrapper's current set of handlers.
                NamedHttpClientHandlerWrapper wrapper = request.RequestHandler;

                // The lock will prevent new handlers from being added in the HttpEngineFactory.AddNamedClientHandler() method above.
                lock (wrapper)
                {
                    // By this point, it is an error if we do not have access to the HttpClientHandler associated with the named client.
                    // Because we clear the wrapper at the end of this code block, wrapper may be empty if we had previously
                    // configured the named HttpClientHandler already. The IsAlwaysEmpty property gets around this issue.
                    if (wrapper.IsAlwaysEmpty)
                    {
                        throw new InvalidOperationException(string.Format(
                                                                "HttpClientHandler for the named client '{0}' has not been registered with MiniRestSharp. Did you forget to call RestSharpServiceCollectionExtensions.AddRestSharpClient(IServiceCollection, string)?",
                                                                wrapper.Name));
                    }

                    // I've confirmed that the only place the wrapped HttpClientHandlers are configured is in this method.
                    NetStd20HttpRequest returnValue = base.ConfigureWebRequest(request);

                    // Now that the wrapped HttpClientHandlers are configured, we remove them from the wrapper
                    // since we can't configure them again anyway. It's of course possible that these handlers
                    // get recycled by IHttpClientFactory and become configurable again. When this happens I think the
                    // RestSharpServiceCollectionExtensions system will end up calling HttpEngineFactory.AddNamedClientHandler()
                    // again, which will result in it being added to wrapper again for another round of configuration later.
                    wrapper.Clear();

                    return(returnValue);
                }
            }
示例#2
0
        private async Task <HttpResponse> PostPutInternal(string method)
        {
            NetStd20HttpRequest request = this.CreateWebRequest(method, this.Url);

            this.ConfigureWebRequest(request);

            this.PreparePostBody(request.RequestMessage);

            this.WriteRequestBody(request);
            return(await this.GetResponse(request));
        }
示例#3
0
        private async Task <HttpResponse> GetStyleMethodInternal(string method)
        {
            NetStd20HttpRequest request = this.CreateWebRequest(method, this.Url);

            this.ConfigureWebRequest(request);

            if (this.HasBody && (method == "DELETE" || method == "OPTIONS"))
            {
                request.RequestMessage.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(this.RequestContentType);
                this.WriteRequestBody(request);
            }

            return(await this.GetResponse(request));
        }
示例#4
0
        protected virtual NetStd20HttpRequest ConfigureWebRequest(NetStd20HttpRequest request)
        {
            ////////// 1. Configure HttpRequestMessage.
            this.AppendHeaders(request.RequestMessage);

            // Override certain headers that are controlled by RestSharp.
            request.RequestMessage.Headers.TE.Clear();
            request.RequestMessage.Headers.TE.Add(new TransferCodingWithQualityHeaderValue("deflate"));
            request.RequestMessage.Headers.TE.Add(new TransferCodingWithQualityHeaderValue("gzip"));
            request.RequestMessage.Headers.TE.Add(new TransferCodingWithQualityHeaderValue("identity"));

            if (this.UserAgent.HasValue())
            {
                request.RequestMessage.Headers.UserAgent.Add(ProductInfoHeaderValue.Parse(this.UserAgent));
            }

            ////////// 2. Configure HttpClientHandler
            this.AppendCookies(request.RequestHandler, request.RequestMessage.RequestUri);

            // This matches with request.Headers.TE header.
            request.RequestHandler.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip | DecompressionMethods.None;

            // Handler credentials.
            request.RequestHandler.UseDefaultCredentials = this.UseDefaultCredentials;
            if (this.Credentials != null)
            {
                request.RequestHandler.Credentials = this.Credentials;
            }

            // redirects
            request.RequestHandler.AllowAutoRedirect = this.FollowRedirects;
            if (this.FollowRedirects && this.MaxRedirects.HasValue)
            {
                request.RequestHandler.MaxAutomaticRedirections = this.MaxRedirects.Value;
            }

            ////////// 3. Configure HttpClient
            if (this.Timeout != 0)
            {
                request.RequestClient.Timeout = TimeSpan.FromMilliseconds(this.Timeout);
            }

            return(request);
        }
示例#5
0
        private async Task <HttpResponse> GetResponse(NetStd20HttpRequest request)
        {
            HttpResponse response = new HttpResponse {
                ResponseStatus = ResponseStatus.None
            };

            try
            {
                NetStd20HttpResponse webResponse = await GetRawResponse(request);

                this.ExtractResponseData(response, webResponse);
            }
            catch (Exception ex)
            {
                this.ExtractErrorResponse(response, ex);
            }

            return(response);
        }
示例#6
0
        private void WriteRequestBody(NetStd20HttpRequest webRequest)
        {
            if (this.HasBody || this.HasFiles || this.AlwaysMultipartFormData)
            {
                webRequest.RequestMessage.Content.Headers.ContentLength = this.CalculateContentLength();
            }

            using (Stream requestStream = webRequest.GetRequestStreamAsync())
            {
                if (this.HasFiles || this.AlwaysMultipartFormData)
                {
                    this.WriteMultipartFormData(requestStream);
                }
                else if (this.RequestBodyBytes != null)
                {
                    requestStream.Write(this.RequestBodyBytes, 0, this.RequestBodyBytes.Length);
                }
                else if (this.RequestBody != null)
                {
                    this.WriteStringTo(requestStream, this.RequestBody);
                }
            }
        }
示例#7
0
        private static async Task <NetStd20HttpResponse> GetRawResponse(NetStd20HttpRequest request)
        {
            try
            {
                // Some methods do not allow entity-body in request, so we must remove the HttpContent.
                // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods for which method allows/disallows entity-body.
                // We need to do this because in the constructor of NetStd20HttpRequest, we always set a HttpContent to make
                // programming easier. In netstandard2.0, the framework does not allow HttpContent for methods such as GET.
                HttpMethod requestMethod = request.RequestMessage.Method;
                if (requestMethod == HttpMethod.Delete ||
                    requestMethod == HttpMethod.Get ||
                    requestMethod == HttpMethod.Head ||
                    requestMethod == HttpMethod.Options)
                {
                    // Will also remove any HttpContent-specific headers that may have been set erroneously.
                    request.RequestMessage.Content = null;
                }

                return(await request.GetResponseAsync());
            }
            catch (WebException ex)
            {
                // Check to see if this is an HTTP error or a transport error.
                // In cases where an HTTP error occurs ( status code >= 400 )
                // return the underlying HTTP response, otherwise assume a
                // transport exception (ex: connection timeout) and
                // rethrow the exception

                var exResponse = ex.Response as NetStd20HttpResponse;
                if (exResponse != null)
                {
                    return(exResponse);
                }

                throw;
            }
        }