将Microsoft.AspNetCore.Http.HttpRequest转换为HttpRequestMessage

yos*_*bel 21 c# request asp.net-core

我需要将Microsoft.AspNetCore.Http.HttpRequest从AspNetCore上下文转换为HttpRequestMessage以传递给HttpClient.有没有一种简单的方法来实现这一目标?或者任何实现这一点的提示都会非常有用.

更新 我想将请求转换为消息,但我想更改目标网址,我只想将请求重定向到另一个服务器.

小智 14

尝试Web API兼容性Shim

HttpRequestMessageFeature hreqmf = new HttpRequestMessageFeature(context);
HttpRequestMessage httpRequestMessage = hreqmf.HttpRequestMessage;
Run Code Online (Sandbox Code Playgroud)

或者你可以从Microsoft.AspNetCore.Proxy中获得灵感

httpContext的这些扩展可能会派上用场.

  • 对于那些只想用最少的代码立即工作的人来说,就是这样。可惜你没有得到公认的答案。 (5认同)

yos*_*bel 8

我最终这样做了:

public static class RequestTranscriptHelpers
{
    public static HttpRequestMessage ToHttpRequestMessage(this HttpRequest req)
        => new HttpRequestMessage()
            .SetMethod(req)
            .SetAbsoluteUri(req)
            .SetHeaders(req)
            .SetContent(req)
            .SetContentType(req);

    private static HttpRequestMessage SetAbsoluteUri(this HttpRequestMessage msg, HttpRequest req)
        => msg.Set(m => m.RequestUri = new UriBuilder
        {
            Scheme = req.Scheme,
            Host = req.Host.Host,
            Port = req.Host.Port.Value,
            Path = req.PathBase.Add(req.Path),
            Query = req.QueryString.ToString()
        }.Uri);

    private static HttpRequestMessage SetMethod(this HttpRequestMessage msg, HttpRequest req)
        => msg.Set(m => m.Method = new HttpMethod(req.Method));

    private static HttpRequestMessage SetHeaders(this HttpRequestMessage msg, HttpRequest req)
        => req.Headers.Aggregate(msg, (acc, h) => acc.Set(m => m.Headers.TryAddWithoutValidation(h.Key, h.Value.AsEnumerable())));

    private static HttpRequestMessage SetContent(this HttpRequestMessage msg, HttpRequest req)
        => msg.Set(m => m.Content = new StreamContent(req.Body));

    private static HttpRequestMessage SetContentType(this HttpRequestMessage msg, HttpRequest req)
        => msg.Set(m => m.Content.Headers.Add("Content-Type", req.ContentType), applyIf: req.Headers.ContainsKey("Content-Type"));

    private static HttpRequestMessage Set(this HttpRequestMessage msg, Action<HttpRequestMessage> config, bool applyIf = true)
    {
        if (applyIf)
        {
            config.Invoke(msg);
        }

        return msg;
    }
}



  public static class ResponseTranscriptHelpers
    {
        public static async Task FromHttpResponseMessage(this HttpResponse resp, HttpResponseMessage msg)
        {
            resp.SetStatusCode(msg)
                .SetHeaders(msg)
                .SetContentType(msg);

            await resp.SetBodyAsync(msg);
        }

        private static HttpResponse SetStatusCode(this HttpResponse resp, HttpResponseMessage msg)
            => resp.Set(r => r.StatusCode = (int)msg.StatusCode);

        private static HttpResponse SetHeaders(this HttpResponse resp, HttpResponseMessage msg)
            => msg.Headers.Aggregate(resp, (acc, h) => acc.Set(r => r.Headers[h.Key] = new StringValues(h.Value.ToArray())));

        private static async Task<HttpResponse> SetBodyAsync(this HttpResponse resp, HttpResponseMessage msg)
        {
            using (var stream = await msg.Content.ReadAsStreamAsync())
            using (var reader = new StreamReader(stream))
            {
                var content = await reader.ReadToEndAsync();

                return resp.Set(async r => await r.WriteAsync(content));
            }
        }

        private static HttpResponse SetContentType(this HttpResponse resp, HttpResponseMessage msg)
            => resp.Set(r => r.ContentType = msg.Content.Headers.GetValues("Content-Type").Single(), applyIf: msg.Content.Headers.Contains("Content-Type"));

        private static HttpResponse Set(this HttpResponse msg, Action<HttpResponse> config, bool applyIf = true)
        {
            if (applyIf)
            {
                config.Invoke(msg);
            }

            return msg;
        }
    }
Run Code Online (Sandbox Code Playgroud)

我没有尝试@Strenkor En'Triel的回复,因为我先找到了这个解决方案,但我会尝试一下.

  • 作者所做的就是分解代码,以便可以以多种方式使用它。在我看来,这是一段漂亮的代码,而且读起来也很好。 (5认同)
  • 我觉得此代码段的编码器正试图尽可能地混淆代码!我从未见过以如此复杂的方式编写的简单代码。请检查Microsoft的其他人如何简单地编写它:https://github.com/aspnet/Proxy/blob/master/src/Microsoft.AspNetCore.Proxy/ProxyAdvancedExtensions.cs (3认同)