/// <summary>
        /// Convert the response coming from ASP.NET Core into APIGatewayProxyResponse which is
        /// serialized into the JSON object that API Gateway expects.
        /// </summary>
        /// <param name="responseFeatures"></param>
        /// <param name="statusCodeIfNotSet">Sometimes the ASP.NET server doesn't set the status code correctly when successful, so this parameter will be used when the value is 0.</param>
        /// <param name="lambdaContext"></param>
        /// <returns><see cref="APIGatewayProxyResponse"/></returns>
        protected override APIGatewayHttpApiV2ProxyResponse MarshallResponse(IHttpResponseFeature responseFeatures, ILambdaContext lambdaContext, int statusCodeIfNotSet = 200)
        {
            var response = new APIGatewayHttpApiV2ProxyResponse
            {
                StatusCode = responseFeatures.StatusCode != 0 ? responseFeatures.StatusCode : statusCodeIfNotSet
            };

            string contentType     = null;
            string contentEncoding = null;

            if (responseFeatures.Headers != null)
            {
                response.Headers = new Dictionary <string, string>();
                foreach (var kvp in responseFeatures.Headers)
                {
                    if (kvp.Key.Equals(HeaderNames.SetCookie, StringComparison.CurrentCultureIgnoreCase))
                    {
                        // Cookies must be passed through the proxy response property and not as a
                        // header to be able to pass back multiple cookies in a single request.
                        response.Cookies = kvp.Value.ToArray();
                        continue;
                    }

                    response.SetHeaderValues(kvp.Key, kvp.Value.ToArray(), false);

                    // Remember the Content-Type for possible later use
                    if (kvp.Key.Equals("Content-Type", StringComparison.CurrentCultureIgnoreCase) && response.Headers[kvp.Key]?.Length > 0)
                    {
                        contentType = response.Headers[kvp.Key];
                    }
                    else if (kvp.Key.Equals("Content-Encoding", StringComparison.CurrentCultureIgnoreCase) && response.Headers[kvp.Key]?.Length > 0)
                    {
                        contentEncoding = response.Headers[kvp.Key];
                    }
                }
            }

            if (contentType == null)
            {
                response.Headers["Content-Type"] = null;
            }

            if (responseFeatures.Body != null)
            {
                // Figure out how we should treat the response content, check encoding first to see if body is compressed, then check content type
                var rcEncoding = GetResponseContentEncodingForContentEncoding(contentEncoding);
                if (rcEncoding != ResponseContentEncoding.Base64)
                {
                    rcEncoding = GetResponseContentEncodingForContentType(contentType);
                }

                (response.Body, response.IsBase64Encoded) = Utilities.ConvertAspNetCoreBodyToLambdaBody(responseFeatures.Body, rcEncoding);
            }

            PostMarshallResponseFeature(responseFeatures, response, lambdaContext);

            _logger.LogDebug($"Response Base 64 Encoded: {response.IsBase64Encoded}");

            return(response);
        }
Ejemplo n.º 2
0
        public async Task Invoke(HttpContext context)
        {
            string endpoint = GetLoweredTrimedPath(context.Request.Path);
            var    status   = (EndpointStatus)EndpointStatus[endpoint];

            if (status == null)
            {
                status = (EndpointStatus)EndpointStatus["*"];
            }
            if (status != null &&
                CheckLimitExceeded(status))
            {
                if (!context.RequestAborted.IsCancellationRequested)
                {
                    IHttpResponseFeature responseFeature = context.Features.Get <IHttpResponseFeature>();
                    responseFeature.StatusCode   = StatusCodes.Status503ServiceUnavailable;
                    responseFeature.ReasonPhrase = "Concurrent request limit exceeded.";
                }
            }
            else
            {
                try
                {
                    await _next(context);
                }
                finally
                {
                    if (ShouldDecrementConcurrentRequestsCountAsync(status.Limit))
                    {
                        Interlocked.Decrement(ref status.ConcurrentRequestsCount);
                    }
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Convert the response coming from ASP.NET Core into APIGatewayProxyResponse which is
        /// serialized into the JSON object that API Gateway expects.
        /// </summary>
        /// <returns>The response.</returns>
        /// <param name="responseFeatures">Response features.</param>
        /// <param name="fcContext">Fc context.</param>
        /// <param name="statusCodeIfNotSet">Status code if not set.</param>
        protected HttpResponse MarshallResponse(IHttpResponseFeature responseFeatures, IFcContext fcContext, HttpResponse response, int statusCodeIfNotSet = 200)
        {
            response.StatusCode = responseFeatures.StatusCode != 0 ? responseFeatures.StatusCode : statusCodeIfNotSet;
            string contentType = null;

            if (responseFeatures.Headers != null)
            {
                foreach (var kvp in responseFeatures.Headers)
                {
                    response.Headers[kvp.Key] = kvp.Value;

                    // Remember the Content-Type for possible later use
                    if (kvp.Key.Equals("Content-Type", StringComparison.CurrentCultureIgnoreCase))
                    {
                        contentType = response.Headers[kvp.Key];
                    }
                }
            }

            if (contentType == null)
            {
                response.Headers["Content-Type"] = StringValues.Empty;
            }

            response.Body = responseFeatures.Body;

            PostMarshallResponseFeature(responseFeatures, response, fcContext);

            return(response);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Convert the response coming from ASP.NET Core into APIGatewayProxyResponse which is
        /// serialized into the JSON object that API Gateway expects.
        /// </summary>
        /// <param name="responseFeatures"></param>
        /// <returns></returns>
        private APIGatewayProxyResponse MarshallResponse(IHttpResponseFeature responseFeatures)
        {
            var response = new APIGatewayProxyResponse
            {
                StatusCode = responseFeatures.StatusCode
            };

            if (responseFeatures.Headers != null)
            {
                response.Headers = new Dictionary <string, string>();
                foreach (var kvp in responseFeatures.Headers)
                {
                    if (kvp.Value.Count == 1)
                    {
                        response.Headers[kvp.Key] = kvp.Value[0];
                    }
                    else
                    {
                        response.Headers[kvp.Key] = string.Join(",", kvp.Value);
                    }
                }
            }

            if (responseFeatures.Body != null)
            {
                responseFeatures.Body.Position = 0;
                using (StreamReader reader = new StreamReader(responseFeatures.Body, Encoding.UTF8))
                {
                    response.Body = reader.ReadToEnd();
                }
            }

            return(response);
        }
Ejemplo n.º 5
0
        // This IHttpResponseFeature extension method extracts custom metric datapoints from the headers of a IHttpResponseFeature object.
        internal static List <DataPoint> ExtractCustomMetricDataPoints(this IHttpResponseFeature responseFeature)
        {
            var metricDataPointHeaders = new List <KeyValuePair <string, StringValues> >();

            foreach (var kvp in responseFeature.Headers)
            {
                if (kvp.Key.StartsWith(CustomMetricPrefix, StringComparison.Ordinal))
                {
                    metricDataPointHeaders.Add(kvp);
                }
            }

            if (metricDataPointHeaders.Count == 0)
            {
                return(null);
            }

            var dataPoints = new List <DataPoint>(metricDataPointHeaders.Count);

            foreach (var metricDataPointHeader in metricDataPointHeaders)
            {
                dataPoints.Add(JsonConvert.DeserializeObject <DataPoint>(metricDataPointHeader.Value));
                responseFeature.Headers.Remove(metricDataPointHeader.Key);
            }

            return(dataPoints);
        }
Ejemplo n.º 6
0
        public async Task WriteAsync(Stream stream, object feature, CancellationToken token)
        {
            IHttpResponseFeature hrf = (IHttpResponseFeature)feature;

            if (hrf.Body != Stream.Null && !hrf.Headers.ContentLength.HasValue)
            {
                hrf.Headers.ContentLength = hrf.Body.Length;
            }

            var buffer = new BufferedStream(stream);

            using (var writer = new BinaryWriter(buffer, Encoding.UTF8, true))
            {
                writer.Write(hrf.StatusCode);
                writer.Write(hrf.ReasonPhrase ?? String.Empty);

                WriteHeaders(writer, hrf.Headers);
            }
            await stream.FlushAsync(token);

            if (hrf.Body != Stream.Null && hrf.Body.Length > 0)
            {
                hrf.Body.Seek(0, SeekOrigin.Begin);
                await hrf.Body.CopyToAsync(stream, 81920, token);

                await stream.FlushAsync(token);
            }
        }
Ejemplo n.º 7
0
 public AspNetHttpResponse(HttpContext context, Microsoft.AspNetCore.Http.HttpResponse response)
 {
     this.Context         = context;
     this.response        = response;
     this.responseFeature = response.HttpContext.Features.Get <IHttpResponseFeature>();
     this.Headers         = new AspNetHeaderDictionary(response.Headers);
 }
Ejemplo n.º 8
0
        public async Task Invoke(HttpContext context)
        {
            if (context.Request.Path != "/pdf/process")
            {
                await _next(context);

                return;
            }
            if (CheckLimitExceeded() && !(await TryWaitInQueueAsync(context.RequestAborted)))
            {
                if (!context.RequestAborted.IsCancellationRequested)
                {
                    IHttpResponseFeature responseFeature = context.Features.Get <IHttpResponseFeature>();

                    responseFeature.StatusCode   = StatusCodes.Status503ServiceUnavailable;
                    responseFeature.ReasonPhrase = "Concurrent request limit exceeded.";
                }
            }
            else
            {
                try
                {
                    await _next(context);
                }
                finally
                {
                    if (await ShouldDecrementConcurrentRequestsCountAsync())
                    {
                        Interlocked.Decrement(ref _concurrentRequestsCount);
                    }
                }
            }
        }
Ejemplo n.º 9
0
        private Task SendResponseAsync(
            IMqResponseFeature mqResponse,
            IHttpResponseFeature httpResponse,
            IHeaderConverter headerConverter
            )
        {
            var needPublish = false;
            var needAck     = mqResponse.AckDeliveryTag.HasValue;

            if (mqResponse.Exchange != null)
            {
                MergeResponseHeaders(mqResponse, httpResponse, headerConverter);
                needPublish = true;
            }

            return(Task.Run(() =>
            {
                if (needPublish)
                {
                    _mqConnection.Model.BasicPublish(mqResponse.Exchange, mqResponse.RoutingKey, mqResponse.Mandatory, mqResponse.Properties, GetBody(mqResponse));
                }
                if (needAck)
                {
                    _mqConnection.Model.BasicAck(mqResponse.AckDeliveryTag.Value, multiple: false);
                }
            }));
        }
Ejemplo n.º 10
0
 private void SetError(IHttpResponseFeature responseFeature, Int32 statusCode, Exception exception)
 {
     if (responseFeature == null || responseFeature.HasStarted)
     {
         return;
     }
     responseFeature.StatusCode = statusCode;
 }
Ejemplo n.º 11
0
 void IFeatureCache.CheckFeaturesRevision()
 {
     if (_cachedFeaturesRevision != _features.Revision)
     {
         _response = null;
         _cachedFeaturesRevision = _features.Revision;
     }
 }
Ejemplo n.º 12
0
        public StubHttpResponse(StubHttpContext context)
        {
            HttpContext = context;

            _feature = context.Features.Get <IHttpResponseFeature>();

            Cookies = new ResponseCookies(Headers, new DefaultObjectPool <StringBuilder>(new DefaultPooledObjectPolicy <StringBuilder>()));
        }
 void IFeatureCache.CheckFeaturesRevision()
 {
     if (_cachedFeaturesRevision != _features.Revision)
     {
         _response = null;
         _cachedFeaturesRevision = _features.Revision;
     }
 }
        /// <summary>
        /// Convert the response coming from ASP.NET Core into APIGatewayProxyResponse which is
        /// serialized into the JSON object that API Gateway expects.
        /// </summary>
        /// <param name="responseFeatures"></param>
        /// <param name="statusCodeIfNotSet">Sometimes the ASP.NET server doesn't set the status code correctly when successful, so this parameter will be used when the value is 0.</param>
        /// <param name="lambdaContext"></param>
        /// <returns><see cref="APIGatewayProxyResponse"/></returns>
        protected override APIGatewayProxyResponse MarshallResponse(IHttpResponseFeature responseFeatures, ILambdaContext lambdaContext, int statusCodeIfNotSet = 200)
        {
            var response = new APIGatewayProxyResponse
            {
                StatusCode = responseFeatures.StatusCode != 0 ? responseFeatures.StatusCode : statusCodeIfNotSet
            };

            string contentType     = null;
            string contentEncoding = null;

            if (responseFeatures.Headers != null)
            {
                response.MultiValueHeaders = new Dictionary <string, IList <string> >();

                response.Headers = new Dictionary <string, string>();
                foreach (var kvp in responseFeatures.Headers)
                {
                    response.MultiValueHeaders[kvp.Key] = kvp.Value.ToList();

                    // Remember the Content-Type for possible later use
                    if (kvp.Key.Equals("Content-Type", StringComparison.CurrentCultureIgnoreCase) && response.MultiValueHeaders[kvp.Key].Count > 0)
                    {
                        contentType = response.MultiValueHeaders[kvp.Key][0];
                    }
                    else if (kvp.Key.Equals("Content-Encoding", StringComparison.CurrentCultureIgnoreCase) && response.MultiValueHeaders[kvp.Key].Count > 0)
                    {
                        contentEncoding = response.MultiValueHeaders[kvp.Key][0];
                    }
                }
            }

            if (contentType == null)
            {
                response.MultiValueHeaders["Content-Type"] = new List <string>()
                {
                    null
                };
            }

            if (responseFeatures.Body != null)
            {
                // Figure out how we should treat the response content, check encoding first to see if body is compressed, then check content type
                var rcEncoding = GetResponseContentEncodingForContentEncoding(contentEncoding);
                if (rcEncoding != ResponseContentEncoding.Base64)
                {
                    rcEncoding = GetResponseContentEncodingForContentType(contentType);
                }

                (response.Body, response.IsBase64Encoded) = Utilities.ConvertAspNetCoreBodyToLambdaBody(responseFeatures.Body, rcEncoding);
            }

            PostMarshallResponseFeature(responseFeatures, response, lambdaContext);

            _logger.LogDebug($"Response Base 64 Encoded: {response.IsBase64Encoded}");

            return(response);
        }
Ejemplo n.º 15
0
        private static void MergeResponseHeaders(IMqResponseFeature mqResponse, IHttpResponseFeature httpResponse, IHeaderConverter headerConverter)
        {
            var headers = mqResponse.Properties.Headers;

            foreach (var item in httpResponse.Headers)
            {
                headers[item.Key] = headerConverter.Write(item.Value);
            }
        }
Ejemplo n.º 16
0
 internal WebContext(IFeatureCollection features)
 {
     this.features   = features;
     connection      = new DefaultConnectionInfo(features);
     fRequest        = features.Get <IHttpRequestFeature>();
     fRequestCookies = new RequestCookiesFeature(features);
     fResponse       = features.Get <IHttpResponseFeature>();
     fWebSocket      = features.Get <IHttpWebSocketFeature>();
 }
        /// <inheritdoc/>
        protected override ApplicationLoadBalancerResponse MarshallResponse(IHttpResponseFeature responseFeatures, ILambdaContext lambdaContext, int statusCodeIfNotSet = 200)
        {
            var response = new ApplicationLoadBalancerResponse
            {
                StatusCode = responseFeatures.StatusCode != 0 ? responseFeatures.StatusCode : statusCodeIfNotSet
            };

            response.StatusDescription = $"{response.StatusCode} {((System.Net.HttpStatusCode)response.StatusCode).ToString()}";


            string contentType = null;

            if (responseFeatures.Headers != null)
            {
                if (this._multiHeaderValuesEnabled)
                {
                    response.MultiValueHeaders = new Dictionary <string, IList <string> >();
                }
                else
                {
                    response.Headers = new Dictionary <string, string>();
                }

                foreach (var kvp in responseFeatures.Headers)
                {
                    if (this._multiHeaderValuesEnabled)
                    {
                        response.MultiValueHeaders[kvp.Key] = kvp.Value.ToList();
                    }
                    else
                    {
                        response.Headers[kvp.Key] = kvp.Value[0];
                    }

                    // Remember the Content-Type for possible later use
                    if (kvp.Key.Equals("Content-Type", StringComparison.CurrentCultureIgnoreCase))
                    {
                        contentType = kvp.Value[0];
                    }
                }
            }

            if (responseFeatures.Body != null)
            {
                // Figure out how we should treat the response content
                var rcEncoding = GetResponseContentEncodingForContentType(contentType);

                (response.Body, response.IsBase64Encoded) = Utilities.ConvertAspNetCoreBodyToLambdaBody(responseFeatures.Body, rcEncoding);
            }

            PostMarshallResponseFeature(responseFeatures, response, lambdaContext);

            _logger.LogDebug($"Response Base 64 Encoded: {response.IsBase64Encoded}");

            return(response);
        }
Ejemplo n.º 18
0
        public HalHttpResponse(HttpContext context)
        {
            this.HttpContext = context
                               ?? throw new ArgumentNullException(nameof(context));

            this.responseFeature = context.Features.Get <IHttpResponseFeature>()
                                   ?? throw new ArgumentException(
                                             "context should contain a IHttpResponseFeature",
                                             nameof(context));
        }
Ejemplo n.º 19
0
        // This IHttpResponseFeature extension method gets custom metric datapoints from the headers of a IHttpResponseFeature object.
        internal static List <DataPoint> GetCustomMetricDataPoints(this IHttpResponseFeature responseFeature)
        {
            var dataPoints = from metricDataPointHeader in
                             (from header in responseFeature.Headers
                              where header.Key.StartsWith(CustomMetricPrefix, StringComparison.Ordinal)
                              select header)
                             select JsonConvert.DeserializeObject <DataPoint>(metricDataPointHeader.Value);

            return(dataPoints.ToList());
        }
Ejemplo n.º 20
0
    private HttpContext GetHttpContext(IHttpResponseFeature responseFeature = null)
    {
        if (responseFeature == null)
        {
            responseFeature = new TestResponseFeature();
        }
        var httpContext = new DefaultHttpContext();

        httpContext.Features.Set <IHttpResponseFeature>(responseFeature);
        return(httpContext);
    }
        /// <inheritdoc />
        /// <summary>
        /// This overriding method is called after the APIGatewayProxyFunction has marshaled IHttpResponseFeature that came
        /// back from making the request into ASP.NET Core into API Gateway's response object APIGatewayProxyResponse. It gets the
        /// user-defined custom metric datapoints from the response headers, posts them to SignalFx and removes the headers.
        /// </summary>
        protected override void PostMarshallResponseFeature(IHttpResponseFeature aspNetCoreResponseFeature, APIGatewayProxyResponse apiGatewayResponse, ILambdaContext lambdaContext)
        {
            var dataPoints = aspNetCoreResponseFeature.GetCustomMetricDataPoints();

            foreach (var dataPoint in dataPoints)
            {
                dataPoint.AddDefaultDimensions(lambdaContext);
            }
            PostDataPoints(dataPoints);
            aspNetCoreResponseFeature.RemoveCustomMetricDataPointHeaders();
        }
Ejemplo n.º 22
0
        // This IHttpResponseFeature extension method removes custom metric datapoints headers from a IHttpResponseFeature object.
        internal static void RemoveCustomMetricDataPointHeaders(this IHttpResponseFeature responseFeature)
        {
            var metricDataPointHeaders = from header in responseFeature.Headers
                                         where header.Key.StartsWith(CustomMetricPrefix, StringComparison.Ordinal)
                                         select header;

            foreach (var metricDataPointHeader in metricDataPointHeaders.ToList())
            {
                responseFeature.Headers.Remove(metricDataPointHeader.Key);
            }
        }
Ejemplo n.º 23
0
        private async Task AssertExecution(IHttpRequestFeature requestFeature, IHttpResponseFeature responseFeature,
                                           BatchMiddlewareEvents batchMiddlewareEvents,
                                           params ResponseFeature[] responseFeatures)
        {
            var featureCollection = new FeatureCollection();

            featureCollection.Set(requestFeature);
            featureCollection.Set(responseFeature);
            var defaultContext = new DefaultHttpContext(featureCollection);
            var middleware     = CreateMiddleware(CreateRequestDelegate(responseFeatures), batchMiddlewareEvents);
            await middleware.Invoke(defaultContext).ConfigureAwait(false);
        }
 public async Task Invoke(HttpContext context)
 {
     try
     {
         await requestDelegate.Invoke(context);
     }
     catch (HttpException httpException)
     {
         context.Response.StatusCode = (int)httpException.StatusCode;
         IHttpResponseFeature feature = context.Features.Get <IHttpResponseFeature>();
         feature.ReasonPhrase = httpException.Message;
     }
 }
Ejemplo n.º 25
0
        protected override void PostMarshallResponseFeature(
            IHttpResponseFeature aspNetCoreResponseFeature,
            APIGatewayProxyResponse lambdaResponse,
            ILambdaContext lambdaContext)
        {
            base.PostMarshallResponseFeature(aspNetCoreResponseFeature, lambdaResponse, lambdaContext);

            AppLogger.LogJson(new
            {
                Event      = "Response",
                RequestId  = lambdaContext.AwsRequestId,
                StatusCode = lambdaResponse.StatusCode,
            });
        }
Ejemplo n.º 26
0
        public StubHttpResponse(StubHttpContext context)
        {
            HttpContext = context;

            _httpResponseFeature = context.Features.Get <IHttpResponseFeature>();

#if NETCOREAPP3_0
            Cookies   = new StubResponseCookieCollection();
            _features = context.Features;
            _features.Set <IHttpResponseBodyFeature>(new StreamResponseBodyFeature(new MemoryStream()));
#else
            Cookies =
                new ResponseCookies(Headers, new DefaultObjectPool <StringBuilder>(new DefaultPooledObjectPolicy <StringBuilder>()));
#endif
        }
Ejemplo n.º 27
0
        private static async Task CopyHttpResponseFeature(IHttpResponseFeature fromHttpResponseFeature, IHttpResponseFeature toHttpResponseFeature, CancellationToken token)
        {
            toHttpResponseFeature.StatusCode   = fromHttpResponseFeature.StatusCode;
            toHttpResponseFeature.ReasonPhrase = fromHttpResponseFeature.ReasonPhrase;
            toHttpResponseFeature.Headers.Clear();
            foreach (var pair in fromHttpResponseFeature.Headers)
            {
                toHttpResponseFeature.Headers[pair.Key] = pair.Value;
            }

            if (toHttpResponseFeature.Headers.ContentLength.GetValueOrDefault(1) > 0)
            {
                await fromHttpResponseFeature.Body.CopyToAsync(toHttpResponseFeature.Body, 81920, token);
            }
        }
Ejemplo n.º 28
0
        public async Task Invoke(HttpContext context)
        {
            try
            {
                await this.next.Invoke(context);
            }

            catch (HttpException httpException)
            {
                context.Response.StatusCode = httpException.StatusCode;

                IHttpResponseFeature httpResponseFeature = context.Features.Get <IHttpResponseFeature>();

                httpResponseFeature.ReasonPhrase = httpException.Message;
            }
        }
Ejemplo n.º 29
0
        public async Task HandleAsync(HttpContext httpContext, Func <Task> _)
        {
            if (httpContext is null)
            {
                throw new ArgumentNullException(nameof(httpContext));
            }

            LogRequestMessage(httpContext, Resources.Debug_HandlingRequest);

            CancellationToken cancellationToken = httpContext.RequestAborted;
            HttpResponse      response          = httpContext.Response;

            using HttpRequestMessage httpRequestMessage = new WrappedHttpRequest(httpContext.Request);
            cancellationToken.ThrowIfCancellationRequested();

            HttpResponseMessage  httpResponseMessage;
            IHttpResponseFeature responseFeature = httpContext.Features.Get <IHttpResponseFeature>();

            try
            {
                httpResponseMessage = await SendAsync(httpRequestMessage, cancellationToken).ConfigureAwait(false);
            }
#pragma warning disable CA1031 // Do not catch general exception types
            catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
            {
                LogRequestMessage(httpContext, Resources.Error_VerifyMockSetup);

#pragma warning disable CA2000 // Dispose objects before losing scope
                httpResponseMessage = new HttpResponseMessage(HttpStatusCode.InternalServerError)
                {
                    ReasonPhrase = Resources.Error_VerifyMockSetup,
                    Content      = new StringContent(Resources.Error_VerifyMockSetup + Environment.NewLine + ex, Encoding.UTF8, "text/plain")
                };
#pragma warning restore CA2000 // Dispose objects before losing scope
            }
            finally
            {
                LogRequestMessage(httpContext, Resources.Debug_RequestHandled);
            }

            // Dispose message when response is done.
            response.RegisterForDispose(httpResponseMessage);
            cancellationToken.ThrowIfCancellationRequested();

            await httpResponseMessage.MapToFeatureAsync(responseFeature, cancellationToken).ConfigureAwait(false);
        }
        public override Task ExecuteResultAsync([NotNull] ActionContext context)
        {
            HttpResponse response = context.HttpContext.Response;

            try
            {
                response.StatusCode = (int)Response.StatusCode;

                IHttpResponseFeature responseFeature = context.HttpContext.Features.Get <IHttpResponseFeature>();
                if (responseFeature != null)
                {
                    responseFeature.ReasonPhrase = Response.ReasonPhrase;
                }

                HttpResponseHeaders headers = Response.Headers;

                // Ignore the Transfer-Encoding header if it is just "chunked".
                // We let the host decide about whether the response should be chunked or not.
                if (headers.TransferEncodingChunked == true && headers.TransferEncoding.Count == 1)
                {
                    headers.TransferEncoding.Clear();
                }

                foreach ((string key, IEnumerable <string> value) in headers)
                {
                    response.Headers.Append(key, value.ToArray());
                }

                HttpContentHeaders contentHeaders = Response.Content.Headers;

                // Copy the response content headers only after ensuring they are complete.
                // We ask for Content-Length first because HttpContent lazily computes this
                // and only afterwards writes the value into the content headers.
                long?_ = contentHeaders.ContentLength;

                foreach ((string key, IEnumerable <string> value) in contentHeaders)
                {
                    response.Headers.Append(key, value.ToArray());
                }

                return(Response.Content.CopyToAsync(response.Body));
            }
            finally
            {
                ObjectHelper.Dispose(ref _response);
            }
        }
        private string BuildOutputFileName(string fileName, IHttpResponseFeature httpResponseFeature)
        {
            var outFileName = Path.Combine(options.Value.OutboxPath, fileName);

            var info = new FileInfo(outFileName);
            var ext  = info.Extension;

            if (httpResponseFeature.Headers["Content-Type"].Any(c => c.Contains("json")))
            {
                ext = ".json";
            }
            else if (httpResponseFeature.Headers["Content-Type"].Any(c => c.Contains("png")))
            {
                ext = ".png";
            }

            return(Path.Combine(info.Directory.FullName, DateTime.Now.Ticks.ToString() + "_" + info.Name.Replace(info.Extension, ext)));
        }