Response not being sent for non-2xx status codes
adnan-kamili opened this issue · comments
Describe the bug
We are getting a 500 response when the target returns non-2xx code. If the target returns a 200 response, all works well we get the response body in the client. In case the target returns 400, the proxy logs 400 but the client gets a 500 error.
To Reproduce
Since we don't know before hand if the request is to be proxied, we enable request buffering in a middleware. In the controller we get to know if request is to be proxied so an exception is thrown which the CustomExceptionFilter handles in the following manner:
public override async Task OnExceptionAsync(ExceptionContext context)
{
...
if (context.Exception is TenantMigratedException tenantMigratedException)
{
context.HttpContext.Request.Body.Position = 0;
await _reverseProxyService.ForwardRequestAsync(context.HttpContext, tenantMigratedException.Region);
return;
}
...
}
Here is the reverse proxy service:
public class ReverseProxyService
{
private readonly IHttpForwarder _forwarder;
private readonly HttpMessageInvoker _httpClient;
private readonly ForwarderRequestConfig _requestOptions;
public ReverseProxyService(IHttpForwarder forwarder)
{
_forwarder = forwarder;
_httpClient = new HttpMessageInvoker(new SocketsHttpHandler
{
UseProxy = false,
AllowAutoRedirect = false,
AutomaticDecompression = System.Net.DecompressionMethods.None,
UseCookies = false,
EnableMultipleHttp2Connections = true,
ActivityHeadersPropagator = new ReverseProxyPropagator(DistributedContextPropagator.Current),
ConnectTimeout = TimeSpan.FromSeconds(15),
SslOptions = new SslClientAuthenticationOptions
{
RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true
}
});
_requestOptions = new ForwarderRequestConfig { ActivityTimeout = TimeSpan.FromSeconds(100) };
}
public async Task ForwardRequestAsync(HttpContext context, string region)
{
string destinationPrefix = null;
if (region == RegionName.EU)
{
destinationPrefix = $"https://{AppConstants.EuWebApiHost}/";
}
if (string.IsNullOrEmpty(destinationPrefix))
{
return;
}
var error = await _forwarder.SendAsync(context, destinationPrefix, _httpClient, _requestOptions, HttpTransformer.Default);
if (error != ForwarderError.None)
{
var errorFeature = context.Features.Get<IForwarderErrorFeature>();
var exception = errorFeature?.Exception;
context.Response.StatusCode = 500;
await context.Response.WriteAsync(JsonSerializer.Serialize(new
{
message = exception?.Message ?? "An error occurred while forwarding the request."
}));
}
}
}
Got Exceptions? Include both the message and the stack trace
We don't see any specific exception, here are some YARP logs:
[17:28:19 INF] [0HN3MD2GKNKEA:00000001] - Proxying to https://api.eu.xxxxx.com/v3/accounts/login HTTP/2 RequestVersionOrLower
[17:28:20 INF] [0HN3MD2GKNKEA:00000001] - Received HTTP/2.0 response 400.
Further technical details
- Yarp.ReverseProxy" Version="2.1.0"
- .NET 7.0.x
- macOS
Are you indicating to MVC that you're handling these exceptions (context.ExceptionHandled = true;
in OnExceptionAsync
)?
If you are and you're still seeing issues, could you share a minimal runnable example we could test with?
Thanks this fixed the issue