private static RequestDelegate CreateRouteHandler( string path, CarterModule module, IEnumerable <IStatusCodeHandler> statusCodeHandlers, ILogger logger) { return(async ctx => { if (!module.Routes.TryGetValue((ctx.Request.Method, path), out var routeHandler)) { // if the path was registered but a handler matching the // current method was not found, return MethodNotFound ctx.Response.StatusCode = StatusCodes.Status405MethodNotAllowed; return; } // begin handling the request if (HttpMethods.IsHead(ctx.Request.Method)) { //Cannot read the default stream once WriteAsync has been called on it ctx.Response.Body = new MemoryStream(); } // run the module handlers bool shouldContinue = true; if (module.Before != null) { shouldContinue = await module.Before(ctx); } if (shouldContinue) { // run the route handler logger.LogDebug("Executing module route handler for {Method} /{Path}", ctx.Request.Method, path); await routeHandler(ctx); // run after handler if (module.After != null) { await module.After(ctx); } } // run status code handler var scHandler = statusCodeHandlers.FirstOrDefault(x => x.CanHandle(ctx.Response.StatusCode)); if (scHandler != null) { await scHandler.Handle(ctx); } if (HttpMethods.IsHead(ctx.Request.Method)) { var length = ctx.Response.Body.Length; ctx.Response.Body.SetLength(0); ctx.Response.ContentLength = length; } }); }
/// <inheritdoc /> public void OnResourceExecuting(ResourceExecutingContext context) { if (context == null) { throw new System.ArgumentNullException(nameof(context)); } var routeData = context.RouteData; var request = context.HttpContext.Request; if (routeData.TryGetWebHookReceiverName(out var receiverName) && (HttpMethods.IsGet(request.Method) || HttpMethods.IsHead(request.Method))) { var getHeadRequestMetadata = _getHeadRequestMetadata .FirstOrDefault(metadata => metadata.IsApplicable(receiverName)); if (getHeadRequestMetadata != null) { // First verify that we have the secret key configuration value. This may be redundant if the // receiver also implements IWebHookVerifyCodeMetadata in its metadata. However this verification // is necessary for some receivers because signature verification (for example) is not possible // without a body. var secretKey = GetSecretKey( receiverName, routeData, getHeadRequestMetadata.SecretKeyMinLength, getHeadRequestMetadata.SecretKeyMaxLength); if (secretKey == null) { context.Result = new NotFoundResult(); return; } if (HttpMethods.IsHead(request.Method)) { if (getHeadRequestMetadata.AllowHeadRequests) { // Success #1 context.Result = new OkResult(); } // Never respond to a HEAD request with a challenge response. return; } if (getHeadRequestMetadata.ChallengeQueryParameterName == null) { // Success #2: Simple GET case. Have done all necessary verification. context.Result = new OkResult(); return; } // Success #3 unless required query parameter is missing. context.Result = GetChallengeResponse(getHeadRequestMetadata, receiverName, request, routeData); } } }
private static bool ShouldValidate(HttpContext context) { // as seen on https://github.com/aspnet/AspNetCore/blob/release/3.0/src/Mvc/Mvc.ViewFeatures/src/Filters/AutoValidateAntiforgeryTokenAuthorizationFilter.cs var method = context.Request.Method; return(!(HttpMethods.IsGet(method) || HttpMethods.IsHead(method) || HttpMethods.IsTrace(method) || HttpMethods.IsOptions(method))); }
public override bool AttemptResponseCaching(ResponseCachingContext context) { var request = context.HttpContext.Request; if (!HttpMethods.IsGet(request.Method) && !HttpMethods.IsHead(request.Method)) { context.Logger.LogRequestMethodNotCacheable(request.Method); return(false); } return(true); }
public async Task InvokeAsync(HttpContext context, RequestDelegate next) { if (HttpMethods.IsGet(context.Request.Method) || HttpMethods.IsHead(context.Request.Method)) { context.Response.StatusCode = StatusCodes.Status200OK; await context.Response.WriteAsync("I'm alive"); } else { context.Response.StatusCode = StatusCodes.Status404NotFound; } }
private static HttpRequestMessage CreateProxiedHttpRequest(this HttpContext context, string uriString, bool shouldAddForwardedHeaders) { var uri = new Uri(uriString); var request = context.Request; var requestMessage = new HttpRequestMessage(); var requestMethod = request.Method; var usesStreamContent = true; // When using other content types, they specify the Content-Type header, and may also change the Content-Length. // Write to request content, when necessary. if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { if (request.HasFormContentType) { usesStreamContent = false; requestMessage.Content = request.Form.ToHttpContent(request.ContentType); } else { requestMessage.Content = new StreamContent(request.Body); } } // Copy the request headers. foreach (var header in request.Headers) { if (!usesStreamContent && (header.Key.Equals("Content-Type", StringComparison.OrdinalIgnoreCase) || header.Key.Equals("Content-Length", StringComparison.OrdinalIgnoreCase))) { continue; } if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray())) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } // Add forwarded headers. if (shouldAddForwardedHeaders) { AddForwardedHeadersToHttpRequest(context, requestMessage); } // Set destination and method. requestMessage.Headers.Host = uri.Authority; requestMessage.RequestUri = uri; requestMessage.Method = new HttpMethod(requestMethod); return(requestMessage); }
static bool SetupMethodAndContent(HttpRequest request, HttpRequestMessage proxiedMessage) { var hasContent = false; var requestMethod = request.Method; // Try to use the static HttpMethods rather than creating a new one. if (HttpMethods.IsGet(requestMethod)) { proxiedMessage.Method = HttpMethod.Get; } else if (HttpMethods.IsHead(requestMethod)) { proxiedMessage.Method = HttpMethod.Head; } else if (HttpMethods.IsDelete(requestMethod)) { proxiedMessage.Method = HttpMethod.Delete; } else if (HttpMethods.IsTrace(requestMethod)) { proxiedMessage.Method = HttpMethod.Trace; } else { hasContent = true; if (HttpMethods.IsPost(requestMethod)) { proxiedMessage.Method = HttpMethod.Post; } else if (HttpMethods.IsOptions(requestMethod)) { proxiedMessage.Method = HttpMethod.Options; } else if (HttpMethods.IsPut(requestMethod)) { proxiedMessage.Method = HttpMethod.Put; } else if (HttpMethods.IsPatch(requestMethod)) { proxiedMessage.Method = HttpMethod.Patch; } else { proxiedMessage.Method = new HttpMethod(request.Method); } proxiedMessage.Content = new StreamContent(request.Body); } return(hasContent); }
private static void SetProxyRequestBody(HttpRequestMessage requestMessage, HttpContext context) { var requestMethod = context.Request.Method; //previously had DELETE as a part of this but we were actually passing up body content as part of our delete wallet calls :-| if (HttpMethods.IsGet(requestMethod) || HttpMethods.IsHead(requestMethod) || HttpMethods.IsTrace(requestMethod)) { return; } requestMessage.Content = new StreamContent(context.Request.Body); }
public async void HealthCheck_Get_Status200(string method) { var response = await _client.SendAsync(new HttpRequestMessage(new HttpMethod(method), "api/_system/healthcheck")); if (!HttpMethods.IsHead(method) && !HttpMethods.IsDelete(method) && !HttpMethods.IsTrace(method)) { Assert.Equal("system_ok", await response.Content.ReadAsStringAsync()); } Assert.Equal(HttpStatusCode.OK, response.StatusCode); }
private static void SetProxyRequestBody(HttpRequestMessage requestMessage, HttpContext context) { var requestMethod = context.Request.Method; if (HttpMethods.IsGet(requestMethod) || HttpMethods.IsHead(requestMethod) || HttpMethods.IsDelete(requestMethod) || HttpMethods.IsTrace(requestMethod)) { return; } requestMessage.Content = new StreamContent(context.Request.Body); }
/// <summary> /// Creates an HttpRequestMessage from the given context and assign the /// returned HttpRequestMessage to the given destination. /// </summary> /// <param name="context">HttpContext to get HttpRequest from.</param> /// <param name="destination">Destination of the HttpRequestMessage.</param> /// <returns></returns> public static HttpRequestMessage CreateProxyHttpRequest(HttpContext context, Uri destination) { /* * Code copied an modified a little from AspNetCore Proxy middleware. * https://github.com/aspnet/Proxy/blob/dev/src/Microsoft.AspNetCore.Proxy/ProxyAdvancedExtensions.cs */ if (context == null) { throw new ArgumentNullException(nameof(context)); } if (destination == null) { throw new ArgumentNullException(nameof(destination)); } // Get the request from the HttpContext. var request = context.Request; // Create an HttpRequestMessage. var requestMessage = new HttpRequestMessage(); // Get request method from the HttpContext. var requestMethod = request.Method; // Copy content of the request body, if neccesary. if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(request.Body); requestMessage.Content = streamContent; } // Copy the request headers. foreach (var header in request.Headers) { if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray())) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } // Copy host, request an so on from HttpContext request. requestMessage.Headers.Host = destination.Authority; requestMessage.RequestUri = destination; requestMessage.Method = new HttpMethod(request.Method); return(requestMessage); }
public async Task Invoke(HttpContext context, IRedisManager redisManager) { try { var requestMessage = new HttpRequestMessage(); var requestMethod = context.Request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(context.Request.Body); requestMessage.Content = streamContent; } // All request headers and cookies must be transferend to remote server. Some headers will be skipped foreach (var header in context.Request.Headers) { if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } string uriString = GetUri(context, redisManager); //recreate remote url requestMessage.RequestUri = new Uri(uriString); requestMessage.Method = new HttpMethod(context.Request.Method); var responseMessage = await redisManager.GetConnection().SendAsync(requestMessage); context.Response.StatusCode = (int)responseMessage.StatusCode; foreach (var header in responseMessage.Headers) { context.Response.Headers[header.Key] = header.Value.ToArray(); } foreach (var header in responseMessage.Content.Headers) { context.Response.Headers[header.Key] = header.Value.ToArray(); } //tell to the browser that response is not chunked //context.Response.Headers.Remove("transfer-encoding"); await responseMessage.Content.CopyToAsync(context.Response.Body); } catch (Exception e) { Debug.WriteLine(e.Message); } }
/// <summary> /// Return a corresponding VerbsHttpMethod with the verb used in the request. /// </summary> /// <param name="context">ActionExecutingContext</param> /// <returns>Return VerbsHttpMethod corresponding to the request.</returns> public static VerbsHttpMethod GetVerbs(this ActionExecutingContext context) { var method = context.HttpContext.Request.Method; if (HttpMethods.IsGet(method)) { return(VerbsHttpMethod.Get); } if (HttpMethods.IsPost(method)) { return(VerbsHttpMethod.Post); } if (HttpMethods.IsDelete(method)) { return(VerbsHttpMethod.Delete); } if (HttpMethods.IsPut(method)) { return(VerbsHttpMethod.Put); } if (HttpMethods.IsHead(method)) { return(VerbsHttpMethod.Head); } if (HttpMethods.IsOptions(method)) { return(VerbsHttpMethod.Options); } if (HttpMethods.IsPatch(method)) { return(VerbsHttpMethod.Patch); } if (HttpMethods.IsTrace(method)) { return(VerbsHttpMethod.Trace); } if (HttpMethods.IsConnect(method)) { return(VerbsHttpMethod.Connect); } throw new HttpMethodNotFoundException($"Could not find the HttpMethod '{method}'"); }
private StreamContent GetStreamContent(HttpContext context) { var requestMethod = context.Request.Method; if (HttpMethods.IsGet(requestMethod) || HttpMethods.IsHead(requestMethod) || HttpMethods.IsDelete(requestMethod) || HttpMethods.IsTrace(requestMethod)) { return(null); } return(new StreamContent(context.Request.Body)); }
public async Task <HttpResponseMessage> Send(HttpContext httpContext, string url) { var requestMessage = new HttpRequestMessage(); var requestMethod = httpContext.Request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(httpContext.Request.Body); requestMessage.Content = streamContent; } _httpClient.DefaultRequestHeaders.Clear(); CopyRequestHeaders( httpContext.Request.Headers, requestMessage.Headers, requestMessage.Content?.Headers, new HashSet <string>(StringComparer.OrdinalIgnoreCase) { "host" } // Use HOST header for backend: it might use it for routing ); requestMessage.RequestUri = new Uri(url); requestMessage.Method = new HttpMethod(requestMethod); try { Console.WriteLine("CALLING: " + url); return(await _httpClient.SendAsync( requestMessage, HttpCompletionOption.ResponseHeadersRead, httpContext.RequestAborted)); } catch (HttpRequestException ex) { if (ex.InnerException?.GetType().Name == "CurlException") { var newEx = new HttpRequestException("Error requesting backend URL: " + url, ex); newEx.Data.Add("url", url); throw newEx; } throw; } }
/// <summary> /// Converts the given HTTP method (usually obtained from <see cref="HttpRequest.Method"/>) /// into the corresponding <see cref="HttpMethod"/> static instance. /// </summary> public static HttpMethod GetHttpMethod(string method) { if (HttpMethods.IsGet(method)) { return(HttpMethod.Get); } if (HttpMethods.IsPost(method)) { return(HttpMethod.Post); } if (HttpMethods.IsPut(method)) { return(HttpMethod.Put); } if (HttpMethods.IsDelete(method)) { return(HttpMethod.Delete); } if (HttpMethods.IsOptions(method)) { return(HttpMethod.Options); } if (HttpMethods.IsHead(method)) { return(HttpMethod.Head); } if (HttpMethods.IsPatch(method)) { return(HttpMethod.Patch); } if (HttpMethods.IsTrace(method)) { return(HttpMethod.Trace); } // NOTE: Proxying "CONNECT" is not supported (by design!) //if (HttpMethods.IsConnect(method)) //{ // return new HttpMethod("CONNECT"); //} throw new InvalidOperationException($"Unsupported request method '{method}'."); }
private static void SetRequestBody(HttpRequestMessage message, HttpContext ctx) { var method = ctx.Request.Method; if (HttpMethods.IsGet(method) || HttpMethods.IsDelete(method) || HttpMethods.IsHead(method) || HttpMethods.IsOptions(method)) { return; } var content = new StreamContent(ctx.Request.Body); message.Content = content; }
private async Task HandleHttpRequest(HttpContext context) { var requestMessage = new HttpRequestMessage(); var requestMethod = context.Request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { requestMessage.Content = new StreamContent(context.Request.Body); } foreach (var header in context.Request.Headers) { if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } requestMessage.Headers.Host = this.options.Host + ":" + this.options.Port; var uriString = $"{this.options.Scheme}://{this.options.Host}:{this.options.Port}{context.Request.PathBase}{context.Request.Path}{context.Request.QueryString}"; requestMessage.RequestUri = new Uri(uriString); requestMessage.Method = new HttpMethod(context.Request.Method); var responseMessage = await this.httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted); using (responseMessage) { context.Response.StatusCode = (int)responseMessage.StatusCode; var responseHeaders = responseMessage.Headers.Concat(responseMessage.Content.Headers); foreach (var header in responseHeaders) { context.Response.Headers[header.Key] = header.Value.ToArray(); } // SendAsync removes chunking from the response. This removes the header so it doesn't expect a chunked response. context.Response.Headers.Remove(HeaderNames.TransferEncoding); if (context.Response.StatusCode != StatusCodes.Status304NotModified) { await responseMessage.Content.CopyToAsync(context.Response.Body); } } }
public async Task Invoke(HttpContext context) { if (!HttpMethods.IsHead(context.Request.Method)) { await _next.Invoke(context); return; } context.Request.Method = HttpMethods.Get; context.Response.Body = Stream.Null; await _next.Invoke(context); context.Request.Method = HttpMethods.Head; }
private static bool ValidateMethod(HttpContext context) { var method = context.Request.Method; var isValid = false; if (HttpMethods.IsGet(method)) { isValid = true; } else if (HttpMethods.IsHead(method)) { isValid = true; } return(isValid); }
private static (RangeItemHeaderValue?range, long rangeLength, bool serveBody) SetRangeHeaders( HttpContext httpContext, RequestHeaders httpRequestHeaders, long fileLength, ILogger logger) { var response = httpContext.Response; var httpResponseHeaders = response.GetTypedHeaders(); var serveBody = !HttpMethods.IsHead(httpContext.Request.Method); // Range may be null for empty range header, invalid ranges, parsing errors, multiple ranges // and when the file length is zero. var(isRangeRequest, range) = RangeHelper.ParseRange( httpContext, httpRequestHeaders, fileLength, logger); if (!isRangeRequest) { return(range : null, rangeLength : 0, serveBody); } // Requested range is not satisfiable if (range == null) { // 14.16 Content-Range - A server sending a response with status code 416 (Requested range not satisfiable) // SHOULD include a Content-Range field with a byte-range-resp-spec of "*". The instance-length specifies // the current length of the selected resource. e.g. */length response.StatusCode = StatusCodes.Status416RangeNotSatisfiable; httpResponseHeaders.ContentRange = new ContentRangeHeaderValue(fileLength); response.ContentLength = 0; return(range : null, rangeLength : 0, serveBody : false); } response.StatusCode = StatusCodes.Status206PartialContent; httpResponseHeaders.ContentRange = new ContentRangeHeaderValue( range.From !.Value, range.To !.Value, fileLength); // Overwrite the Content-Length header for valid range requests with the range length. var rangeLength = SetContentLength(response, range); return(range, rangeLength, serveBody); }
/// <summary> /// This middleware transforms incoming Http HEAD request /// internally to Http GET and ensures that a null stream is /// being sent back. /// </summary> public async Task Invoke(HttpContext context) { var isHead = HttpMethods.IsHead(context.Request.Method); if (isHead) { context.Request.Method = HttpMethods.Get; context.Response.Body = Stream.Null; } await _next(context); if (isHead) { context.Request.Method = HttpMethods.Head; } }
private static bool ValidateMethod(HttpContext context) { string method = context.Request.Method; bool flag = false; if (HttpMethods.IsGet(method)) { flag = true; } else if (HttpMethods.IsHead(method)) { flag = true; } return(flag); }
public static async Task HandleHttpRequestX(HttpContext context, string uriString) { var _httpClient = new HttpClient(new HttpClientHandler()); var requestMessage = new HttpRequestMessage(); var requestMethod = context.Request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(context.Request.Body); requestMessage.Content = streamContent; } // Copy the request headers foreach (var header in context.Request.Headers) { if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } requestMessage.RequestUri = new Uri(uriString); requestMessage.Headers.Host = $"{requestMessage.RequestUri.Host}:{requestMessage.RequestUri.Port}"; requestMessage.Method = new HttpMethod(context.Request.Method); using (var responseMessage = await _httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted)) { context.Response.StatusCode = (int)responseMessage.StatusCode; foreach (var header in responseMessage.Headers) { context.Response.Headers[header.Key] = header.Value.ToArray(); } foreach (var header in responseMessage.Content.Headers) { context.Response.Headers[header.Key] = header.Value.ToArray(); } // SendAsync removes chunking from the response. This removes the header so it doesn't expect a chunked response. context.Response.Headers.Remove("transfer-encoding"); await responseMessage.Content.CopyToAsync(context.Response.Body); } }
public static string ReadRequestBodyAsString(this HttpRequest request) { string requestBodyAsText = ""; if (!HttpMethods.IsGet(request.Method) && !HttpMethods.IsHead(request.Method) && !HttpMethods.IsDelete(request.Method) && !HttpMethods.IsTrace(request.Method) && request.ContentLength > 0) { using (var reader = new StreamReader(request.Body)) { requestBodyAsText = reader.ReadToEnd(); } } return(requestBodyAsText); }
private void CopyOriginalReqContent(HttpRequest req, HttpRequestMessage requestMessage) { if (!HttpMethods.IsGet(req.Method) && !HttpMethods.IsHead(req.Method) && !HttpMethods.IsDelete(req.Method)) { // here is is a method with a BODY var streamContent = new StreamContent(req.Body); requestMessage.Content = streamContent; } // copy headers foreach (var header in req.Headers) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } }
private bool SetupContent(object content, string contentMediaType, bool contentAsJson, bool contentUseCamelCase, HttpRequest request, HttpRequestMessage requestMessage, string requestMethod) { if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { if (request.HasFormContentType) { var dataToSend = content != null ? content as IFormCollection : request.Form; requestMessage.Content = ToHttpContent(dataToSend, request.ContentType); return(false); } else { requestMessage.Content = content != null?CreateHttpContent(content, contentMediaType, contentAsJson, contentUseCamelCase) : new StreamContent(request.Body); } } return(true); }
private static void SetProxyRequestBody(HttpRequestMessage requestMessage, HttpContext context) { var requestMethod = context.Request.Method; if (HttpMethods.IsGet(requestMethod) || HttpMethods.IsHead(requestMethod) || HttpMethods.IsDelete(requestMethod) || HttpMethods.IsTrace(requestMethod)) { return; } // We need to copy the stream to not get exceptions var memStr = new System.IO.MemoryStream(); context.Request.Body.CopyTo(memStr); memStr.Position = 0; requestMessage.Content = new StreamContent(memStr); }
private void CopyFromOriginalRequestContentAndHeaders(HttpContext context, HttpRequestMessage requestMessage) { var requestMethod = context.Request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(context.Request.Body); requestMessage.Content = streamContent; } foreach (var header in context.Request.Headers) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } }
private static HttpRequestMessage CreateProxyHttpRequest(this HttpRequest request) { var requestMessage = new HttpRequestMessage(); var requestMethod = request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(request.Body); requestMessage.Content = streamContent; } // Copy the request headers *except* x-forwarded-* headers. foreach (var header in request.Headers) { if (header.Key.StartsWith("X-Forwarded-", StringComparison.OrdinalIgnoreCase)) { continue; } if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray())) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } // HACK: Attempting to send a malformed User-Agent will throw from with HttpClient // Remove when .net core 3 is released. Consider supporting netcoreapp2.x with #ifdef // https://github.com/damianh/ProxyKit/issues/53 // https://github.com/dotnet/corefx/issues/34933 try { requestMessage.Headers.TryGetValues("User-Agent", out var _); } catch (IndexOutOfRangeException) { requestMessage.Headers.Remove("User-Agent"); } requestMessage.Method = new HttpMethod(request.Method); return(requestMessage); }