Ocelot: 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:
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 17 (9 by maintainers)
Commits related to this issue
- #893 fix request cancellation, add acceptance test — committed to jlukawska/Ocelot by jlukawska 4 years ago
- #893 fix request cancellation, add acceptance test — committed to jlukawska/Ocelot by jlukawska 4 years ago
- #893 fix request cancellation, add acceptance test — committed to jlukawska/Ocelot by jlukawska 4 years ago
- #893 fix request cancellation, add acceptance test — committed to jlukawska/Ocelot by jlukawska 4 years ago
- #893 Problems to cancel a request (CancellationToken) (#1367) * #893 fix request cancellation, add acceptance test * correct exception message * correct exception message * #893 fix request ... — committed to ThreeMammals/Ocelot by jlukawska 9 months ago
@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)
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?).
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.
I can confirm that this bug is still present in v19.0.2
I’m afraid the Ocelot project is no longer maintained 😦 Nothing has been merged for a long time.
Sorry @jurgi, I’d not elaborated clearly ,that’s not been implemented by
Ocelot
for now, just a mind on Ocelot.