Convert Microsoft.AspNetCore.Http.HttpRequest to HttpRequestMessage
I need to convert Microsoft.AspNetCore.Http.HttpRequest from an AspNetCore context to an HttpRequestMessage to pass to an HttpClient. Is there a simple way of achieve this? Or any hint to implement this would be very helpful.
Update I want to convert the request into a message but I want to change the target url, I want just to redirect the request into another server.
Try Web API Compatibility Shim
HttpRequestMessageFeature hreqmf = new HttpRequestMessageFeature(httpRequest.HttpContext);
HttpRequestMessage httpRequestMessage = hreqmf.HttpRequestMessage;
Or you could get inspired by Microsoft.AspNetCore.Proxy
These extensions to httpContext may come in handy.
I ended up doing this:
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;
}
}
I haven't tried @Strenkor En'Triel response since I found this solution first, but I will try it.
Both IHttpRequestMessageFeature
and Microsoft.AspNetCore.Proxy
are discontinued. IHttpRequestMessageFeature
has been removed since ASP.NET Core 3.0.
Microsoft now has a new reverse proxy nuget package Microsoft.ReverseProxy based on ASP.NET Core infrastructure. As per their docs, IHttpProxy
for direct proxying scenario can:
serve as the core proxy adapter between incoming AspNetCore and outgoing System.Net.Http requests. It handles the mechanics of creating a
HttpRequestMessage
from aHttpContext
, sending it, and relaying the response.
Here is an example.