/// <summary>
        /// Removes and returns the current header value by first checking the HttpResponse
        /// and falling back to the value from HttpResponseMessage or HttpContent only if
        /// <see cref="ResponseTransformContext.HeadersCopied"/> is not set.
        /// This ordering allows multiple transforms to mutate the same header.
        /// </summary>
        /// <param name="headerName">The name of the header to take.</param>
        /// <returns>The response header value, or StringValues.Empty if none.</returns>
        public static StringValues TakeHeader(ResponseTransformContext context, string headerName)
        {
            if (context is null)
            {
                throw new System.ArgumentNullException(nameof(context));
            }

            if (string.IsNullOrEmpty(headerName))
            {
                throw new System.ArgumentException($"'{nameof(headerName)}' cannot be null or empty.", nameof(headerName));
            }

            var existingValues = StringValues.Empty;

            if (context.HttpContext.Response.Headers.TryGetValue(headerName, out var responseValues))
            {
                context.HttpContext.Response.Headers.Remove(headerName);
                existingValues = responseValues;
            }
            else if (context.ProxyResponse != null && !context.HeadersCopied &&
                     (context.ProxyResponse.Headers.TryGetValues(headerName, out var values) ||
                      context.ProxyResponse.Content.Headers.TryGetValues(headerName, out values)))
            {
                existingValues = (string[])values;
            }

            return(existingValues);
        }
        /// <inheritdoc/>
        public override ValueTask ApplyAsync(ResponseTransformContext context)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (context.ProxyResponse == null)
            {
                return(default);
        // Assumes the response status code has been set on the HttpContext already.
        /// <inheritdoc/>
        public override ValueTask ApplyAsync(ResponseTransformContext context)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (Always || Success(context))
            {
                context.HttpContext.Response.Headers.Remove(HeaderName);
            }

            return(default);
        /// <inheritdoc/>
        public override ValueTask ApplyAsync(ResponseTransformContext context)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            Debug.Assert(!context.HeadersCopied);

            // See https://github.com/microsoft/reverse-proxy/blob/51d797986b1fea03500a1ad173d13a1176fb5552/src/ReverseProxy/Forwarder/HttpTransformer.cs#L67-L77
            var responseHeaders = context.HttpContext.Response.Headers;

            CopyResponseHeaders(context.ProxyResponse.Headers, responseHeaders);
            if (context.ProxyResponse.Content != null)
            {
                CopyResponseHeaders(context.ProxyResponse.Content.Headers, responseHeaders);
            }

            context.HeadersCopied = true;

            return(default);
        // Assumes the response status code has been set on the HttpContext already.
        /// <inheritdoc/>
        public override ValueTask ApplyAsync(ResponseTransformContext context)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (Always || Success(context))
            {
                var existingHeader = TakeHeader(context, HeaderName);
                if (Append)
                {
                    var value = StringValues.Concat(existingHeader, Value);
                    SetHeader(context, HeaderName, value);
                }
                else
                {
                    SetHeader(context, HeaderName, Value);
                }
            }

            return(default);
示例#6
0
 /// <inheritdoc/>
 public override ValueTask ApplyAsync(ResponseTransformContext context)
 {
     return(_func(context));
 }
 internal static bool Success(ResponseTransformContext context)
 {
     // TODO: How complex should this get? Compare with http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header
     return(context.HttpContext.Response.StatusCode < 400);
 }
 /// <summary>
 /// Sets the given header on the HttpResponse.
 /// </summary>
 public static void SetHeader(ResponseTransformContext context, string headerName, StringValues values)
 {
     context.HttpContext.Response.Headers[headerName] = values;
 }
 /// <summary>
 /// Transforms the given response. The status and headers will have (optionally) already been
 /// copied to the <see cref="HttpResponse"/> and any changes should be made there.
 /// </summary>
 public abstract ValueTask ApplyAsync(ResponseTransformContext context);