Alongside other endpoints, I have in my Web API (.NET 6.0 or .NET 8.0), I would like to create proxy for some portion of requests I know I just want to pass to 3rd party API, while not really caring about what is being sent/received (so that I don’t need to redo all contracts on my side).
Reason why I want to achieve this in a MVC controller is re-usability – authorization and error handling. I want to control who can do this proxy request trough authorization (existing functionality), and if something goes wrong, there’s custom error handling (also existing).
Additionally, my _myTypedClient
has attached HTTP message handler which adds another authorization header to the request (so caller of my API doesn’t need any understanding of 3rd party API auth, and requests to 3rd party API is done on behalf of my application).
I came up with code like this (this is most likely not complete):
// TODO: Add more methods ...
[HttpPost("proxy/svc/{**path}")]
[HttpPut("proxy/svc/{**path}")]
[HttpPatch("proxy/svc/{**path}")]
[HttpDelete("proxy/svc/{**path}")]
public async Task Proxy(string path)
{
var request = new HttpRequestMessage(HttpMethod.Parse(Request.Method), path);
// create outbound request content if present
// TODO: dispose properly
if (Request.ContentLength > 0)
{
var memory = new MemoryStream();
await Request.Body.CopyToAsync(memory, Request.HttpContext.RequestAborted);
memory.Position = 0;
var content = new StreamContent(memory);
content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse(Request.ContentType!);
content.Headers.ContentLength = memory.Length;
}
// MyTypedClient(HttpClient)
var response = await _myTypedClient.SendAsync(request, Request.HttpContext.RequestAborted);
// write response
Response.StatusCode = (int)response.StatusCode;
Response.Headers.TryAdd(HeaderNames.ContentLength, response.Content.Headers.ContentLength.ToString());
Response.Headers.TryAdd(
HeaderNames.ContentType,
response.Content.Headers.ContentType?.ToString() ?? MediaTypeNames.Application.Json);
var responseStream = await response.Content.ReadAsStreamAsync(Request.HttpContext.RequestAborted);
await responseStream.CopyToAsync(Response.Body, Request.HttpContext.RequestAborted);
}
- Would it be possible to match any HTTP method?
- How could I handle stream better? (I haven’t found way how to pass
Body
directly toStreamContent
of my HTTP client) - Should I even do this?! Am I not seeing some massive drawback here?
1