/// <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="context">The transform context.</param> /// <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 ArgumentNullException(nameof(context)); } if (string.IsNullOrEmpty(headerName)) { throw new ArgumentException($"'{nameof(headerName)}' cannot be null or empty.", nameof(headerName)); } if (context.HttpContext.Response.Headers.TryGetValue(headerName, out var existingValues)) { context.HttpContext.Response.Headers.Remove(headerName); } else if (context.ProxyResponse is { } proxyResponse&& !context.HeadersCopied) { if (!RequestUtilities.TryGetValues(proxyResponse.Headers, headerName, out existingValues)) { RequestUtilities.TryGetValues(proxyResponse.Content.Headers, headerName, out existingValues); } } return(existingValues); }
/// <summary> /// Removes and returns the current trailer value by first checking the HttpResponse /// and falling back to the value from HttpResponseMessage only if /// <see cref="ResponseTrailersTransformContext.HeadersCopied"/> is not set. /// This ordering allows multiple transforms to mutate the same header. /// </summary> /// <param name="context">The transform context.</param> /// <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(ResponseTrailersTransformContext context, string headerName) { if (context is null) { throw new ArgumentNullException(nameof(context)); } if (string.IsNullOrEmpty(headerName)) { throw new ArgumentException($"'{nameof(headerName)}' cannot be null or empty.", nameof(headerName)); } Debug.Assert(context.ProxyResponse is not null); var responseTrailersFeature = context.HttpContext.Features.Get <IHttpResponseTrailersFeature>(); var responseTrailers = responseTrailersFeature?.Trailers; // Support should have already been checked by the caller. Debug.Assert(responseTrailers is not null); Debug.Assert(!responseTrailers.IsReadOnly); if (responseTrailers.TryGetValue(headerName, out var existingValues)) { responseTrailers.Remove(headerName); } else if (!context.HeadersCopied) { RequestUtilities.TryGetValues(context.ProxyResponse.TrailingHeaders, headerName, out existingValues); } return(existingValues); }
public void TryGetValues(params string[] headerValues) { var request = new HttpRequestMessage(); foreach (var value in headerValues) { request.Headers.TryAddWithoutValidation("foo", value); } request.Headers.TryAddWithoutValidation("bar", headerValues); Assert.True(RequestUtilities.TryGetValues(request.Headers, "foo", out var actualValues)); Assert.Equal(headerValues, actualValues); Assert.True(RequestUtilities.TryGetValues(request.Headers, "bar", out actualValues)); Assert.Equal(headerValues, actualValues); }
/// <summary> /// Removes and returns the current header value by first checking the HttpRequestMessage, /// then the HttpContent, and falling back to the HttpContext only if /// <see cref="RequestTransformContext.HeadersCopied"/> is not set. /// This ordering allows multiple transforms to mutate the same header. /// </summary> /// <param name="context">The transform context.</param> /// <param name="headerName">The name of the header to take.</param> /// <returns>The requested header value, or StringValues.Empty if none.</returns> public static StringValues TakeHeader(RequestTransformContext context, string headerName) { if (string.IsNullOrEmpty(headerName)) { throw new ArgumentException($"'{nameof(headerName)}' cannot be null or empty.", nameof(headerName)); } var proxyRequest = context.ProxyRequest; if (RequestUtilities.TryGetValues(proxyRequest.Headers, headerName, out var existingValues)) { proxyRequest.Headers.Remove(headerName); } else if (proxyRequest.Content is { } content&& RequestUtilities.TryGetValues(content.Headers, headerName, out existingValues)) { content.Headers.Remove(headerName); }
private static void RestoreUpgradeHeaders(HttpContext context, HttpResponseMessage response) { // We don't use NonValidated for the Connection header as we do want value validation. // HttpHeaders.TryGetValues will handle the parsing and split the values for us. if (RequestUtilities.TryGetValues(response.Headers, HeaderNames.Upgrade, out var upgradeValues) && response.Headers.TryGetValues(HeaderNames.Connection, out var connectionValues)) { foreach (var value in connectionValues) { if (value.Equals("upgrade", StringComparison.OrdinalIgnoreCase)) { context.Response.Headers.TryAdd(HeaderNames.Connection, value); context.Response.Headers.TryAdd(HeaderNames.Upgrade, upgradeValues); break; } } } }