Ocelot
Ocelot copied to clipboard
Problems to cancel a request (CancellationToken)
Expected Behavior
The action of the api does not correctly receive the cancellation token when aborting a request through Ocelot.
Actual Behavior
By calling the api directly and while it is running, I cancel the request. The CancellationToken parameter takes the correct value and the appropriate exception is thrown. On the other hand, if I make the same request through Ocelot, the exception is not thrown.
Steps to Reproduce the Problem
Api Code
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
public class PaymentsController : ControllerBase {
private readonly ILogger logger;
public PaymentsController(ILogger<Logging> logger) {
this.logger = logger;
}
[HttpGet("{id}")]
[ProducesResponseType(400)]
[ProducesResponseType(typeof(string), 202)]
[ApiExplorerSettings(IgnoreApi = true)]
public async Task<ActionResult<string>> GetAsync(string id, CancellationToken ct) {
try {
Console.WriteLine("Se va a para la ejecución");
await Task.Delay(5000, ct);
ct.ThrowIfCancellationRequested();
Console.WriteLine($"La ejecución continua -{ct.IsCancellationRequested}-");
} catch (Exception ex) when (ex is TaskCanceledException || ex is OperationCanceledException) {
Console.WriteLine("Operación cancelada");
return BadRequest();
}
return Ok("todo OK");
}
}
Direct request to the api: http://.../api/v1/Payments/2
Hosting environment: Staging
Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://*****/api/v1/Payments/2
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Route matched with {action = "GetAsync", controller = "Payments"}. Executing action LK.Psd2.Api.Controllers.V1.PaymentsController.GetAsync (LK.Psd2.Api)
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action method LK.Psd2.Api.Controllers.V1.PaymentsController.GetAsync (LK.Psd2.Api) with arguments (2, System.Threading.CancellationToken) - Validation state: Valid
Se va a para la ejecuci¢n
Operaci¢n cancelada
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action method LK.Psd2.Api.Controllers.V1.PaymentsController.GetAsync (LK.Psd2.Api), returned result Microsoft.AspNetCore.Mvc.BadRequestResult in 37.1519ms.
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
Executing HttpStatusCodeResult, setting HTTP status code 400
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action LK.Psd2.Api.Controllers.V1.PaymentsController.GetAsync (LK.Psd2.Api) in 416.8234ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 570.0624ms 0
Request to the api through Ocelot: https://.../api/v1/Payments/2
Ocelot logs:
dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
Hosting starting
Hosting environment: Staging
Application started. Press Ctrl+C to shut down.
dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
Hosting started
dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
Loaded hosting startup assembly LK.Psd2.ApiGw
dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[0]
Loaded hosting startup assembly Microsoft.AspNetCore.Server.IISIntegration
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET https://******/api/v1/Payments/2
dbug: Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware[0]
Wildcard detected, all requests with hosts will be allowed.
trce: Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware[0]
All hosts are allowed.
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: no request id, previousRequestId: no previous request id, message: MiddlewareStarting: Microsoft.AspNetCore.HttpsPolicy.HstsMiddleware; /api/v1/Payments/2
trce: Microsoft.AspNetCore.HttpsPolicy.HstsMiddleware[3]
Adding HSTS header to response.
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: no request id, previousRequestId: no previous request id, message: MiddlewareStarting: Microsoft.AspNetCore.Builder.UseExtensions+<>c__DisplayClass0_1; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: no request id, previousRequestId: no previous request id, message: MiddlewareStarting: Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: no request id, previousRequestId: no previous request id, message: MiddlewareStarting: TransitionToOcelotMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: no request id, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: ExceptionHandlerMiddleware; /api/v1/Payments/2
dbug: Ocelot.Errors.Middleware.ExceptionHandlerMiddleware[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: ocelot pipeline started
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: ResponderMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: DownstreamRouteFinderMiddleware; /api/v1/Payments/2
dbug: Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Upstream url path is /api/v1/Payments/2
dbug: Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: downstream templates are /api/{version}/{everything}
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: SecurityMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: HttpHeadersTransformationMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: DownstreamRequestInitialiserMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: ClientRateLimitMiddleware; /api/v1/Payments/2
info: Ocelot.RateLimit.Middleware.ClientRateLimitMiddleware[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: EndpointRateLimiting is not enabled for /api/{version}/{everything}
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: ReRouteRequestIdMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: AuthenticationMiddleware; /api/v1/Payments/2
info: Ocelot.Authentication.Middleware.AuthenticationMiddleware[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: No authentication needed for /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: ClaimsToClaimsMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: AuthorisationMiddleware; /api/v1/Payments/2
info: Ocelot.Authorisation.Middleware.AuthorisationMiddleware[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: /api/{version}/{everything} route does not require user to be authorised
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: ClaimsToHeadersMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: ClaimsToQueryStringMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: LoadBalancingMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: DownstreamUrlCreatorMiddleware; /api/v1/Payments/2
dbug: Ocelot.DownstreamUrlCreator.Middleware.DownstreamUrlCreatorMiddleware[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Downstream url is http://******/api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: OutputCacheMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareStarted: HttpRequesterMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: HttpRequesterMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: OutputCacheMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: DownstreamUrlCreatorMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: LoadBalancingMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: ClaimsToQueryStringMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: ClaimsToHeadersMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: AuthorisationMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: ClaimsToClaimsMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: AuthenticationMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: ReRouteRequestIdMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: ClientRateLimitMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: DownstreamRequestInitialiserMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: HttpHeadersTransformationMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: SecurityMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: DownstreamRouteFinderMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: ResponderMiddleware; /api/v1/Payments/2
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: Ocelot.MiddlewareFinished: ExceptionHandlerMiddleware; /api/v1/Payments/2
dbug: Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer[1]
Connection ID "17654110540902969818" disconnecting.
dbug: Ocelot.Requester.Middleware.HttpRequesterMiddleware[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: setting http response message
dbug: Ocelot.Responder.Middleware.ResponderMiddleware[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: no pipeline errors, setting and returning completed response
dbug: Ocelot.Errors.Middleware.ExceptionHandlerMiddleware[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: ocelot pipeline finished
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: MiddlewareFinished: TransitionToOcelotMiddleware; 200
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: MiddlewareFinished: Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware; 200
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: MiddlewareFinished: Microsoft.AspNetCore.Builder.UseExtensions+<>c__DisplayClass0_1; 200
trce: Ocelot.Logging.OcelotDiagnosticListener[0]
requestId: 800031db-0000-f500-b63f-84710c7967bb, previousRequestId: no previous request id, message: MiddlewareFinished: Microsoft.AspNetCore.HttpsPolicy.HstsMiddleware; 200
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 7468.4477ms 200 text/plain; charset=utf-8
api logs:
Hosting environment: Staging
Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://******/api/v1/Payments/2 0
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Route matched with {action = "GetAsync", controller = "Payments"}. Executing action LK.Psd2.Api.Controllers.V1.PaymentsController.GetAsync (LK.Psd2.Api)
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action method LK.Psd2.Api.Controllers.V1.PaymentsController.GetAsync (LK.Psd2.Api) with arguments (2, System.Threading.CancellationToken) - Validation state: Valid
Se va a para la ejecuci¢n
La ejecuci¢n continua -False-
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action method LK.Psd2.Api.Controllers.V1.PaymentsController.GetAsync (LK.Psd2.Api), returned result Microsoft.AspNetCore.Mvc.OkObjectResult in 5019.3262ms.
info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1]
Executing ObjectResult, writing value of type 'System.String'.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action LK.Psd2.Api.Controllers.V1.PaymentsController.GetAsync (LK.Psd2.Api) in 5402.3125ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 5559.3111ms 200 text/plain; charset=utf-8
Ocelot config:
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/{version}/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "psd2.desa.net",
"Port": 80
}
],
"UpstreamPathTemplate": "/api/{version}/{everything}",
"UpstreamHttpMethod": []
}
],
"GlobalConfiguration": {
"RequestIdKey": "OcRequestId"
}
}
Ocelot Startup.cs
public class Startup {
private readonly IConfiguration cfg;
public Startup(IConfiguration configuration) => cfg = configuration;
public void ConfigureServices(IServiceCollection services) {
services.AddCors(options => {
options.AddPolicy(
"CorsPolicy",
builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
services.AddOcelot();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
} else {
app.UseHsts();
}
app.UseCors("CorsPolicy");
app.UseOcelot().Wait();
}
}
Specifications
- Version: 13.0.0
- Platform: .netcore 2.2.2 (Windows Server 2012R2 IIS 8.5)
- Subsystem:
maybe HttpContext.RequestAborted
can be used for Ocelot inner handle to support for request abort
I have tried to use that property in the API and the result is the same :-( Any other idea?
Sorry @jurgi, I'd not elaborated clearly ,that's not been implemented by Ocelot
for now, just a mind on Ocelot.
Any update on this issue? I will likely need to abandon Ocelot without this feature.
Hello, I've investigated this issue and I see that the pull request above added this feature, but... There was a breaking change in the Ocelot version 16.0.0 regarding HttpContext and this feature was not updated to work with these changes. I'll try to fix it next week as a PR, but I don't know when the next release of Ocelot is planned.
Hi, is there any further update on this issue?
Seemed not 😢
Hi, are there any plans to fix this? This is really a very unpleasant error
Well, this one caught me by surprise. Any chance that this will be fixed in a near future? Checked PR 1367 from @jlukawska and to my understanding this would be an easy fix to merge. Thanks.
Please merge PR #1367! I just confirmed that it still is a fully functioning fix for this issue. What are we waiting for? 🙂
Request cancellation is a basic concept; we should be able to rely on Ocelot to handle this correctly.
We were very surprised to find out that it's (no longer) working correctly, we're using Ocelot for quite some time now and we think it was functioning in the past (maybe before version 16.0.0?).
I'm afraid the Ocelot project is no longer maintained :( Nothing has been merged for a long time.
@TomPallister please chime in! It seems like the cancellation issue is a show-stopper for quite some people, we are also using a forked version of Ocelot. There is an easy fix (just merge PR #1367)
Specifications
- Version: 13.0.0
@jurgi Hi Iurgi! You are the issue reporter! You've reported the bug for a very old version! Please note that Ocelot project doesn't support old versions. You need to upgrade the .NET solution constantly after Ocelot releases! So, use the latest version please! Current release: 19.0.2 for .NET 7. NuGet: NuGet Gallery | Ocelot 19.0.2
So, could you confirm the bug is still in v19.0.2 please? What versions of (NuGet package, .NET) do you use currently for Gateway project with Ocelot?
I can confirm that this bug is still present in v19.0.2
I can confirm that this bug is still present in v19.0.2
Hi @dvandenhoek ! Please provide the logs and a solution to review!
@yangzhongke @wast @TomPallister @thiagoloureiro @sharpn @RaynaldM @raman-m Do we accept this issue?
@jurgi Congrats! 🎉