Back to Ocelot

Error Handling

docs/features/errorcodes.rst

25.0.08.5 KB
Original Source

Error Handling

.. contents:: Table of Contents :depth: 2 :local: .. _Handle errors in ASP.NET Core: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/error-handling .. _standard error handling: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/error-handling

MS Learn: Handle errors in ASP.NET Core_

Ocelot has custom error handling for Exception objects. Thus, we override the standard error handling_ provided by ASP.NET Core, which is based on manipulating Exception objects.

.. _eh-middleware:

Middleware

.. _499 Client Closed Request: https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.statuscodes.status499clientclosedrequest .. _500 Internal Server Error: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/500

Class: ExceptionHandlerMiddleware <https://github.com/ThreeMammals/Ocelot/blob/main/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs>_

The ExceptionHandlerMiddleware produces the following status codes, in fallback order, after setting the :ref:lg-request-id:

  1. Native response status: Returned when no exception is present, or when a mapped error status is available (excluding 499 and 500).
  2. 499 Client Closed Request_: A custom Ocelot status returned when an OperationCanceledException occurs due to an aborted request. A warning is logged.
  3. 500 Internal Server Error_: The standard status returned when a generic Exception occurs and Ocelot does not process or map the error. An error record is logged.

Ocelot returns HTTP status codes based on internal logic in specific cases of :ref:eh-client-error-responses and :ref:eh-server-error-responses.

.. _eh-client-error-responses:

Client Error Responses

.. _RFC 7230: https://www.rfc-editor.org/rfc/rfc7230 .. _400 Bad Request: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/400 .. _401 Unauthorized: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/401 .. _403 Forbidden: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/403 .. _404 Not Found: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/404 .. _RequestCanceledError: https://github.com/search?q=repo%3AThreeMammals%2FOcelot+RequestCanceledError&type=code .. _OcelotErrorCode.RequestCanceled: https://github.com/search?q=repo%3AThreeMammals%2FOcelot%20OcelotErrorCode.RequestCanceled&type=code

  • 400 Bad Request: If something is wrong with the incoming request, Ocelot generates an HttpRequestException, for example: [#f1]

    • An upstream request header contains non-ASCII characters. RFC 7230_ specifies that when a server encounters invalid or unparsable request data, it should respond with a 400 Bad Request_ status code.
  • 401 Unauthorized_: If the authentication middleware runs and the user is not authenticated.

  • 403 Forbidden_ is returned by:

    • :doc:../features/authorization middleware, when the user is unauthorized, a claim or scope is invalid, or a required claim is missing or not found.
    • :ref:Security <routing-security-options> middleware, when it runs based on :ref:Security Options <routing-security-options> and the upstream client IP is not allowed or is blocked by IPSecurityPolicy (or another ISecurityPolicy).
  • 404 Not Found_: If a downstream route cannot be found, or if Ocelot is unable to map an internal error code to an HTTP status code.

  • 499 Client Closed Request_: If the request is canceled by the client.

    | Ocelot Error: RequestCanceledError <https://github.com/search?q=repo%3AThreeMammals%2FOcelot+RequestCanceledError&type=code>_ | Ocelot Code: OcelotErrorCode.RequestCanceled <https://github.com/search?q=repo%3AThreeMammals%2FOcelot%20OcelotErrorCode.RequestCanceled&type=code>_

    According to Ocelot Core's design, HTTP status code 499 is returned in the following OperationCanceledException scenarios:

    1. By ExceptionHandlerMiddleware, if an OperationCanceledException is thrown and the context's cancellation token is in the "cancellation requested" state. Ocelot logs a warning with the exception body. If the response has not started, the status code will be set to 499.
    2. By ResponderMiddleware, if the default IErrorsToHttpStatusCodeMapper service maps the detected OcelotErrorCode.RequestCanceled_ to status 499. This error code is produced by the IExceptionToErrorMapper service when an OperationCanceledException is thrown by other middlewares.

.. _eh-server-error-responses:

Server Error Responses

.. _502 Bad Gateway: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/502 .. _503 Service Unavailable: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/503

  • 500 Internal Server Error_: If unable to complete the HTTP request to the downstream service, and the exception is not OperationCanceledException or HttpRequestException.

  • 502 Bad Gateway_: If unable to connect to the downstream service.

  • 503 Service Unavailable_: Returned when the downstream request times out.

    | Ocelot Error: RequestTimedOutError <https://github.com/search?q=repo%3AThreeMammals%2FOcelot+RequestTimedOutError&type=code>_ | Ocelot Code: OcelotErrorCode.RequestTimedOutError <https://github.com/search?q=repo%3AThreeMammals%2FOcelot%20OcelotErrorCode.RequestTimedOutError&type=code>_

    According to Ocelot Core's design, status code 503 is produced in the following TimeoutException scenarios:

    1. By TimeoutDelegatingHandler from the IMessageInvokerPool service, when an OperationCanceledException is thrown and the context's cancellation token is not in the “cancellation requested” state. Ocelot does not log an error with the exception body, but the IExceptionToErrorMapper service generates the internal OcelotErrorCode.RequestTimedOutError_.
    2. By ResponderMiddleware, if the default IErrorsToHttpStatusCodeMapper service maps the detected OcelotErrorCode.RequestTimedOutError_ to status 503. This error code is produced by the IExceptionToErrorMapper service when a TimeoutException is thrown by other middlewares—especially by TimeoutDelegatingHandler.

.. _eh-error-mapper:

Error Mapper

Class: HttpExceptionToErrorMapper <https://github.com/ThreeMammals/Ocelot/blob/main/src/Ocelot/Requester/HttpExceptionToErrorMapper.cs>_

Historically, Ocelot errors are implemented by the Exception-to-Error mapper <https://github.com/search?q=repo%3AThreeMammals%2FOcelot%20HttpExceptionToErrorMapper&type=code>_. The Map method converts an Exception object to a native Ocelot.Errors.Error object.

We override HTTP status codes because of Exception-to-Error mapping. This can be confusing for the developer since the actual status code of the downstream service may be different and get lost. Please research and review all response headers of the upstream service. If you do not find status codes and/or required headers, then the :doc:../features/headerstransformation feature should help.

We expect you to share your use case with us in the Discussions <https://github.com/ThreeMammals/Ocelot/discussions>_ space of the repository. |octocat|

.. |octocat| image:: https://github.githubassets.com/images/icons/emoji/octocat.png :alt: octocat :height: 25 :class: img-valign-middle

""""

.. [#f1] RFC 7230_ ("Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing"), Section 3.2 ("Header Fields"), and especially Section 3.2.4 ("Field Parsing"), describe cases that may arise with request data (where a 400 Bad Request_ status is preferred) and response data (where a 502 Bad Gateway_ status is preferred). Ocelot does not perform any special validation of header data for upstream requests or downstream responses; it proxies headers as-is, with the exception of the ":doc:../features/headerstransformation" feature. This enhancement was requested in bug 2374, fixed in pull request 2379, and the patch was rolled out as part of the 25.0_ release.

.. _"Header Fields": https://www.rfc-editor.org/rfc/rfc7230#section-3.2 .. _"Field Parsing": https://www.rfc-editor.org/rfc/rfc7230#section-3.2.4 .. _2374: https://github.com/ThreeMammals/Ocelot/issues/2374 .. _2379: https://github.com/ThreeMammals/Ocelot/pull/2379 .. _25.0: https://github.com/ThreeMammals/Ocelot/releases/tag/25.0.0