예제 #1
0
        /// <summary>
        /// Clones a HttpContent instance
        /// </summary>
        /// <param name="content">The HttpContent to clone</param>
        /// <returns>A copy of the HttpContent</returns>
        public static HttpContent Clone(this HttpContent content)
        {
            if (content == null)
            {
                return(null);
            }

            HttpContent clone;

            switch (content)
            {
            case StringContent sc:
                clone = new StringContent(sc.ReadAsStringAsync().Result);
                break;

            default:
                throw new Exception($"{content.GetType()} Content type not implemented for HttpContent.Clone extension method.");
            }

            clone.Headers.Clear();
            foreach (KeyValuePair <string, IEnumerable <string> > header in content.Headers)
            {
                clone.Headers.Add(header.Key, header.Value);
            }

            return(clone);
        }
예제 #2
0
        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            long   excuteTime = 0;
            string inparam    = "";
            string outparam   = "";
            string func       = actionExecutedContext.Request.RequestUri.AbsolutePath;

            if (actionExecutedContext.Request.Properties.ContainsKey(key))
            {
                Stopwatch stopwatch = actionExecutedContext.Request.Properties[key] as Stopwatch;
                if (stopwatch != null)
                {
                    stopwatch.Stop();
                    excuteTime = stopwatch.ElapsedMilliseconds;
                }
            }
            object obj;

            if (actionExecutedContext.ActionContext.ActionArguments.TryGetValue(inparamName, out obj))
            {
                inparam = JsonConvert.SerializeObject(obj);
                BasicModelRequest request         = JsonConvert.DeserializeObject <BasicModelRequest>(inparam);
                HttpContent       responseContent = actionExecutedContext.Response.Content;
                object            responseObj     =
                    responseContent.GetType().GetProperty("Value")?.GetValue(responseContent);
                outparam = JsonConvert.SerializeObject(responseObj);
                LogHelper.Current.WriteInfoLog(new LogEnt(func, request.user_id, inparam, outparam, excuteTime));
            }
        }
        protected async Task <(bool result, dynamic contentValue)> HandleMessageContentAsync(HttpContent httpContent)
        {
            (bool result, dynamic contentValue) = await HttpContentReader.ReadAsync(httpContent);

            if (!result)
            {
                Logger.ContentNotSupported(httpContent.GetType().FullName);
                return(false, default);
예제 #4
0
        /// <summary>
        /// Serializes the specified content.
        /// </summary>
        /// <param name="bytes">The bytes.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="content">The content.</param>
        /// <returns></returns>
        public static int Serialize(ref byte[] bytes, int offset, HttpContent content)
        {
            if (content is null)
            {
                return(MessagePackBinary.WriteNil(ref bytes, offset));
            }

            int startOffset = offset;

            offset += MessagePackBinary.WriteFixedArrayHeaderUnsafe(ref bytes, offset, 3);

            // If we know the type, store a byte to indicate which one it is
            if (!_knownTypes.TryGetValue(content.GetType(), out byte type))
            {
                type = 0;
            }
            offset += MessagePackBinary.WriteByte(ref bytes, offset, type);

            // Headers
            if (content.Headers == null)
            {
                MessagePackBinary.WriteNil(ref bytes, offset);
                offset++;
            }
            else
            {
                KeyValuePair <string, IEnumerable <string> >[] headers = content.Headers.ToArray();
                offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, headers.Length);
                foreach (KeyValuePair <string, IEnumerable <string> > kvp in headers)
                {
                    // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 Header names are not case-sensitive
                    // so we normalize to lower case
                    offset += MessagePackBinary.WriteString(ref bytes, offset, kvp.Key.ToLowerInvariant());

                    string[] values = kvp.Value.ToArray();
                    offset += MessagePackBinary.WriteFixedArrayHeaderUnsafe(ref bytes, offset, values.Length);
                    foreach (string v in values)
                    {
                        offset += MessagePackBinary.WriteString(ref bytes, offset, v);
                    }
                }
            }

            // All content is written out as a byte array
            offset += MessagePackBinary.WriteBytes(ref bytes, offset,
                                                   content.ReadAsByteArrayAsync().Result);

            return(offset - startOffset);
        }
예제 #5
0
        /// <summary>
        /// Tests whether the content of the HTTP response message is of certain type.
        /// </summary>
        /// <typeparam name="TContentType">Type of expected HTTP content.</typeparam>
        /// <param name="content">Actual HTTP content.</param>
        /// <param name="failedValidationAction">Action to call in case of failed validation.</param>
        public static void WithContentOfType <TContentType>(
            HttpContent content,
            Action <string, string, string> failedValidationAction)
            where TContentType : HttpContent
        {
            var expectedType = typeof(TContentType);
            var actualType   = content.GetType();

            if (Reflection.AreNotAssignable(actualType, expectedType))
            {
                failedValidationAction(
                    "content",
                    string.Format("to be {0}", expectedType.ToFriendlyTypeName()),
                    string.Format("was in fact {0}", actualType.ToFriendlyTypeName()));
            }
        }
        public static async Task <PreventDisposeContentWrapper> CreateWrapperAsync(HttpContent wrappedContent)
        {
            if (wrappedContent == null)
            {
                return(new PreventDisposeContentWrapper(new byte[0], null));
            }
            var bytes = await wrappedContent.ReadAsByteArrayAsync();

            var wrapper = new PreventDisposeContentWrapper(bytes, wrappedContent.GetType());

            foreach (var header in wrappedContent.Headers)
            {
                wrapper.Headers.Add(header.Key, header.Value);
            }
            return(wrapper);
        }
 public static object HttpContentToByteArray(HttpContent httpContent)
 {
     if (httpContent is HttpContent content)
     {
         return(content.ReadAsByteArrayAsync().Result);
     }
     else
     {
         throw new ArgumentException($"Argument type is not equal, {nameof(httpContent)} :{httpContent?.GetType().FullName}");
     }
 }
예제 #8
0
        internal static Task CreateErrorResponseAsync(HttpContextBase httpContextBase, HttpContent responseContent, HttpRequestMessage request, Exception exception)
        {
            Contract.Assert(httpContextBase != null);
            Contract.Assert(responseContent != null);
            Contract.Assert(exception != null);
            Contract.Assert(request != null);

            HttpResponseBase      httpResponseBase  = httpContextBase.Response;
            HttpResponseMessage   errorResponse     = null;
            HttpResponseException responseException = exception as HttpResponseException;

            // Ensure all headers and content are cleared to eliminate any partial results.
            ClearContentAndHeaders(httpResponseBase);

            // If the exception we are handling is HttpResponseException,
            // that becomes the error response.
            if (responseException != null)
            {
                errorResponse = responseException.Response;
            }
            else
            {
                // The exception is not HttpResponseException.
                // Create a 500 response with content containing an explanatory message and
                // stack trace, subject to content negotiation and policy for error details.
                try
                {
                    MediaTypeHeaderValue mediaType = responseContent.Headers.ContentType;
                    string messageDetails          = (mediaType != null)
                                                ? Error.Format(
                        SRResources.Serialize_Response_Failed_MediaType,
                        responseContent.GetType().Name,
                        mediaType)
                                                : Error.Format(
                        SRResources.Serialize_Response_Failed,
                        responseContent.GetType().Name);

                    errorResponse = request.CreateErrorResponse(
                        HttpStatusCode.InternalServerError,
                        new InvalidOperationException(messageDetails, exception));

                    // CreateErrorResponse will choose 406 if it cannot find a formatter,
                    // but we want our default error response to be 500 always
                    errorResponse.StatusCode = HttpStatusCode.InternalServerError;
                }
                catch
                {
                    // Failed creating an HttpResponseMessage for the error response.
                    // This can happen for missing config, missing conneg service, etc.
                    // Create an empty error response and return a non-faulted task.
                    CreateEmptyErrorResponse(httpResponseBase);
                    return(TaskHelpers.Completed());
                }
            }

            Contract.Assert(errorResponse != null);
            CopyResponseStatusAndHeaders(httpContextBase, errorResponse);

            // The error response may return a null content if content negotiation
            // fails to find a formatter, or this may be an HttpResponseException without
            // content.  In either case, cleanup and return a completed task.

            if (errorResponse.Content == null)
            {
                errorResponse.Dispose();
                return(TaskHelpers.Completed());
            }

            // Copy the headers from the newly generated HttpResponseMessage.
            // We must ask the content for its content length because Content-Length
            // is lazily computed and added to the headers.
            var unused = errorResponse.Content.Headers.ContentLength;

            CopyHeaders(errorResponse.Content.Headers, httpContextBase);

            return(CreateErrorResponseAsyncCore(errorResponse, httpResponseBase));
        }
예제 #9
0
        // Send HttpContent, used by all above methods, accept any of the HttpContent sub-classes
        // FormUrlEncodedContent: A container for name/value tuples encoded using application/x-www-form-urlencoded MIME type.
        // MultipartContent: Provides a collection of HttpContent objects that get serialized using the multipart/* content type specification.
        // MultipartFormDataContent: Provides a container for content encoded using multipart/form-data MIME type. (Use this format if you are uploading a file to a server)
        // StreamContent: Provides HTTP content based on a stream.
        // StringContent: Provides HTTP content based on a string.
        // ObjectContent: Contains a value as well as an associated MediaTypeFormatter that will be used to serialize the value when writing this content.
        // ObjectContent comes from the System.Net.Http.Formatting assembly provided by package Microsoft.AspNet.WebApi.Client
        // HttpContent: A base class representing an HTTP entity body and content headers.
        public virtual async Task <ApiResponse> SendAsync(HttpMethod method, string resourcePath, HttpContent content = null)
        {
            // Create the context here so we have access to it in the catch block
            Polly.Context context = new Polly.Context();
            //Create the Request
            HttpRequestMessage request = new HttpRequestMessage(method, resourcePath);

            if (content != null)
            {
                request.Content = content;
            }
            else
            {
                // content is normally provided for post and put methods
                if (method == HttpMethod.Post || method == HttpMethod.Put)
                {
                    _logger.LogDebug($"{DateTime.Now.ToString()} : SendAsync: The HttpContent is null for POST or PUT request!");
                }
            }
            // Set the PolicyExecutionContext so that it is available after execution of the request
            // https://github.com/App-vNext/Polly/issues/505
            request.SetPolicyExecutionContext(context);
            request.SetResourcePath(resourcePath);
            // Make the request
            RequestCount++;
            PendingRequestCount++;
            LastRequestTimeStamp = DateTime.UtcNow;
            var requestTimer = new Stopwatch();

            try {
                if (content == null)
                {
                    _logger.LogDebug($"{DateTime.Now.ToString()} : SendAsync: Sending request with Method: {method?.ToString()} HttpContent is null, RequestUri: {request.RequestUri}");
                }
                else
                {
                    _logger.LogDebug($"{DateTime.Now.ToString()} : SendAsync: Sending request with Method: {method?.ToString()} HttpContent Type: \"{content?.GetType()?.Name?.ToString()}\" RequestUri: {request.RequestUri}");
                }
                requestTimer.Start();
                using (var response = await _client.SendAsync(request, CancellationTokenSource.Token)) {
                    requestTimer.Stop();
                    TransferRetryInfo(response.RequestMessage, context);
                    return(await _apiResponseBuilder.GetApiResponse(response, resourcePath, requestTimer));
                }
            } catch (Exception exception) {
                // Handles communication errors such as "Connection Refused" etc.
                // Network failures (System.Net.Http.HttpRequestException)
                // Timeouts (System.IO.IOException)
                requestTimer.Stop();
                TransferRetryInfo(exception, context);
                return(_apiResponseBuilder.GetApiResponseForException(exception, request, resourcePath, requestTimer));
            } finally {
                PendingRequestCount--;
            }
        }
예제 #10
0
 /// <summary>
 /// Returns true if the content is filled.
 /// </summary>
 /// <param name="content">The content to check..</param>
 /// <returns><c>true</c> if there is content; <c>false</c> otherwise.</returns>
 internal static bool HasContent(this HttpContent content)
 => content != null && content.GetType().Name != "EmptyContent";
        private static void HandleWebHostBufferedContentException(ExceptionHandlerContext context)
        {
            Contract.Assert(context != null);

            ExceptionContext exceptionContext = context.ExceptionContext;

            Contract.Assert(exceptionContext != null);

            Exception exception = exceptionContext.Exception;

            Contract.Assert(exception != null);

            HttpRequestMessage request = exceptionContext.Request;

            if (request == null)
            {
                throw new ArgumentException(Error.Format(SRResources.TypePropertyMustNotBeNull,
                                                         typeof(ExceptionContext).Name, "Request"), "context");
            }

            HttpResponseMessage response = exceptionContext.Response;

            if (response == null)
            {
                throw new ArgumentException(Error.Format(SRResources.TypePropertyMustNotBeNull,
                                                         typeof(ExceptionContext).Name, "Response"), "context");
            }

            HttpContent responseContent = response.Content;

            if (responseContent == null)
            {
                throw new ArgumentException(Error.Format(SRResources.TypePropertyMustNotBeNull,
                                                         typeof(HttpResponseMessage).Name, "Content"), "context");
            }

            HttpResponseMessage errorResponse;

            // Create a 500 response with content containing an explanatory message and
            // stack trace, subject to content negotiation and policy for error details.
            try
            {
                MediaTypeHeaderValue mediaType = responseContent.Headers.ContentType;
                string messageDetails          = (mediaType != null)
                                            ? Error.Format(
                    SRResources.Serialize_Response_Failed_MediaType,
                    responseContent.GetType().Name,
                    mediaType)
                                            : Error.Format(
                    SRResources.Serialize_Response_Failed,
                    responseContent.GetType().Name);

                errorResponse = request.CreateErrorResponse(
                    HttpStatusCode.InternalServerError,
                    new InvalidOperationException(messageDetails, exception));

                // CreateErrorResponse will choose 406 if it cannot find a formatter,
                // but we want our default error response to be 500 always
                errorResponse.StatusCode = HttpStatusCode.InternalServerError;
            }
            catch
            {
                // Failed creating an HttpResponseMessage for the error response.
                // This can happen for missing config, missing conneg service, etc.
                // Create an empty error response and return a non-faulted task.
                errorResponse = request.CreateResponse(HttpStatusCode.InternalServerError);
            }

            context.Result = new ResponseMessageResult(errorResponse);
        }