-
I'm using YARP 1.1 for several applications for implementing blue/green deploy The underlying service stopped working properly, but YARP still responded 200 It looks like the HttpForwarder always tries setting a response code, even in I couldn't find out where ResponseCode isn't set, but I guess it's in some error // First the SendAsync has to throw
destinationResponse = await httpClient.SendAsync(destinationRequest, activityCancellationSource.Token);
// to get us into HandleRequestFailureAsync
// The exception cannot be an OperationCanceledException
// and requestContent?.ConsumptionTask.IsCompleted == true
// Then the StreamCopyResult cannot be a success
var (requestBodyCopyResult, requestBodyException) = requestContent.ConsumptionTask.Result;
if (requestBodyCopyResult != StreamCopyResult.Success)
// Then within HandleRequestBodyFailure, the context.Response.HasStarted has to be
// true. In that case, I cannot see context.Response.StatusCode being set. But in
// that case it looks like it tries to abort the context which shouldn't set 200 ok? But it really looks like ResponseCode isn't set by YARP in some timeout case, In the image, you can see YARP is W3SVC124, and the underlying application is Any idea how to go forward on this? Any tips on what might be wrong? I didn't Our code is very straight forward, and pretty much just looks like the following: builder.Services.AddHttpForwarder();
// ... snip ...
app.UseEndpoints(endpoints => {
var forwarder = app.Services.GetRequiredService<IHttpForwarder>();
var httpClient = new HttpMessageInvoker(new SocketsHttpHandler {
UseProxy = false,
AllowAutoRedirect = false,
AutomaticDecompression = DecompressionMethods.None,
UseCookies = false,
ActivityHeadersPropagator = new ReverseProxyPropagator(DistributedContextPropagator.Current)
});
var requestConfig = new ForwarderRequestConfig {
ActivityTimeout = TimeSpan.FromMinutes(5)
};
endpoints.Map("/{**catch-all}", async httpContext => {
await forwarder.SendAsync(httpContext, "https://the-application:48666", httpClient, requestConfig);
});
}); |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 4 replies
-
I'm able to trigger something similar with the following testcode app.MapGet("/write-some-then-block", async (HttpContext context) => {
var delay = TimeSpan.FromMinutes(10.0);
await context.Response.Body.WriteAsync(Encoding.UTF8.GetBytes($"We're blocking for {delay}"));
await Task.Delay(delay);
await context.Response.Body.WriteAsync(Encoding.UTF8.GetBytes($"Blocked for {delay}"));
}); It will get a partial response, but 200 OK. It times out after 5m as I specified in YARP: The default timeout is 100 seconds, but I don't understand how we could see this /// <summary>
/// How long a request is allowed to remain idle between any operation completing, after which it will be canceled.
/// The default is 100 seconds. The timeout will reset when response headers are received or after successfully reading or
/// writing any request, response, or streaming data like gRPC or WebSockets. TCP keep-alives and HTTP/2 protocol pings will
/// not reset the timeout, but WebSocket pings will.
/// </summary>
public TimeSpan? ActivityTimeout { get; init; } But if I change |
Beta Was this translation helpful? Give feedback.
The status code can't be changed after the first write to the response body, the status and headers have already been sent to the client. That's what's happening in your sample, and it sounds like what's happening in your issue?