-
Notifications
You must be signed in to change notification settings - Fork 441
Improvements for Problem guideline #826
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
a8ffd42
633e507
ae4e4bf
500ef7e
e00310c
71b903e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -461,16 +461,16 @@ proper guidance for handling batch/bulk requests and responses, we herewith | |||||||||||||
| define the following approach: | ||||||||||||||
|
|
||||||||||||||
| * A batch or bulk request *always* responds with HTTP status code {207} | ||||||||||||||
| unless a non-item-specific failure occurs. | ||||||||||||||
| unless a non-item-specific failure occurs. | ||||||||||||||
|
|
||||||||||||||
| * A batch or bulk request *may* return {4xx}/{5xx} status codes, if the | ||||||||||||||
| failure is non-item-specific and cannot be restricted to individual items of | ||||||||||||||
| the batch or bulk request, e.g. in case of overload situations or general | ||||||||||||||
| service failures. | ||||||||||||||
| failure is non-item-specific and cannot be restricted to individual items of | ||||||||||||||
| the batch or bulk request, e.g. in case of overload situations or general | ||||||||||||||
| service failures. | ||||||||||||||
|
|
||||||||||||||
| * A batch or bulk response with status code {207} *always* returns as payload | ||||||||||||||
| a multi-status response containing item specific status and/or monitoring | ||||||||||||||
| information for each part of the batch or bulk request. | ||||||||||||||
| a multi-status response containing item specific status and/or monitoring | ||||||||||||||
| information for each part of the batch or bulk request. | ||||||||||||||
|
|
||||||||||||||
| **Note:** These rules apply _even in the case_ that processing of all | ||||||||||||||
| individual parts _fail_ or each part is executed _asynchronously_! | ||||||||||||||
|
|
@@ -529,23 +529,23 @@ providing further details to the client. There are two approaches a service | |||||||||||||
| can take for header information: | ||||||||||||||
|
|
||||||||||||||
| * Return a {Retry-After} header indicating how long the client ought to wait | ||||||||||||||
| before making a follow-up request. The Retry-After header can contain a HTTP | ||||||||||||||
| date value to retry after or the number of seconds to delay. Either is | ||||||||||||||
| acceptable but APIs should prefer to use a delay in seconds. | ||||||||||||||
| before making a follow-up request. The Retry-After header can contain a HTTP | ||||||||||||||
| date value to retry after or the number of seconds to delay. Either is | ||||||||||||||
| acceptable but APIs should prefer to use a delay in seconds. | ||||||||||||||
| * Return a trio of `X-RateLimit` headers. These headers (described below) allow | ||||||||||||||
| a server to express a service level in the form of a number of allowing | ||||||||||||||
| requests within a given window of time and when the window is reset. | ||||||||||||||
| a server to express a service level in the form of a number of allowing | ||||||||||||||
| requests within a given window of time and when the window is reset. | ||||||||||||||
|
|
||||||||||||||
| The `X-RateLimit` headers are: | ||||||||||||||
|
|
||||||||||||||
| * `X-RateLimit-Limit`: The maximum number of requests that the client is | ||||||||||||||
| allowed to make in this window. | ||||||||||||||
| allowed to make in this window. | ||||||||||||||
| * `X-RateLimit-Remaining`: The number of requests allowed in the current | ||||||||||||||
| window. | ||||||||||||||
| window. | ||||||||||||||
| * `X-RateLimit-Reset`: The relative time in seconds when the rate limit window | ||||||||||||||
| will be reset. **Beware** that this is different to Github and Twitter's | ||||||||||||||
| usage of a header with the same name which is using UTC epoch seconds | ||||||||||||||
| instead. | ||||||||||||||
| will be reset. **Beware** that this is different to Github and Twitter's | ||||||||||||||
| usage of a header with the same name which is using UTC epoch seconds | ||||||||||||||
| instead. | ||||||||||||||
|
|
||||||||||||||
| The reason to allow both approaches is that APIs can have different | ||||||||||||||
| needs. Retry-After is often sufficient for general load handling and | ||||||||||||||
|
|
@@ -564,52 +564,32 @@ number of requests made within a given window for each named entity. | |||||||||||||
| == {MUST} support problem JSON | ||||||||||||||
|
|
||||||||||||||
| {RFC-9457}[RFC 9457] defines a Problem JSON object using the media type | ||||||||||||||
| `application/problem+json` to provide an extensible human and machine readable | ||||||||||||||
| failure information beyond the HTTP response status code to transports the | ||||||||||||||
| failure kind (`type` / `title`) and the failure cause and location (`instant` / | ||||||||||||||
| `detail`). To make best use of this additional failure information, every | ||||||||||||||
| endpoints must be capable of returning a Problem JSON on client usage errors | ||||||||||||||
| ({4xx} status codes) as well as server side processing errors ({5xx} status | ||||||||||||||
| codes). | ||||||||||||||
|
Comment on lines
-567
to
-573
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's keep this paragraph. |
||||||||||||||
|
|
||||||||||||||
| *Note:* Clients must be robust and *not rely* on a Problem JSON object | ||||||||||||||
| being returned, since (a) failure responses may be created by infrastructure | ||||||||||||||
| components not aware of this guideline or (b) service may be unable to comply | ||||||||||||||
| with this guideline in certain error situations. | ||||||||||||||
| `application/problem+json` to provide a standardized format for expressing | ||||||||||||||
| errors in API responses. It serves several purposes: | ||||||||||||||
|
|
||||||||||||||
| *Hint:* The media type `application/problem+json` is often not implemented as | ||||||||||||||
| a subset of `application/json` by libraries and services! Thus clients need to | ||||||||||||||
| include `application/problem+json` in the {Accept}-Header to trigger delivery | ||||||||||||||
| of the extended failure information. | ||||||||||||||
| * Developers: to debug, diagnose and resolve issues during API integration or | ||||||||||||||
| operation | ||||||||||||||
| * Client applications: to inform users about errors (in user interface) and to | ||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The problem object is provided for developers, not for application and UI users. |
||||||||||||||
| support automated processing and error handling when appropriate. | ||||||||||||||
|
|
||||||||||||||
| The OpenAPI schema definition of the Problem JSON object can be found | ||||||||||||||
| ==== Problem object specification | ||||||||||||||
| The Problem object is specified in the OpenAPI | ||||||||||||||
| schema definition | ||||||||||||||
| https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.1.yaml[on | ||||||||||||||
| GitHub]. You can reference it by using: | ||||||||||||||
| GitHub]. | ||||||||||||||
|
|
||||||||||||||
| [source,yaml] | ||||||||||||||
| ---- | ||||||||||||||
| responses: | ||||||||||||||
| 503: | ||||||||||||||
| description: Service Unavailable | ||||||||||||||
| content: | ||||||||||||||
| "application/problem+json": | ||||||||||||||
| schema: | ||||||||||||||
| $ref: 'https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.1.yaml#/Problem' | ||||||||||||||
| ---- | ||||||||||||||
|
|
||||||||||||||
| You may define custom problem types as extensions of the Problem JSON object | ||||||||||||||
| if your API needs to return specific, additional, and more detailed error | ||||||||||||||
| information. | ||||||||||||||
| **Note:** If a member's value type does not match the specified type, | ||||||||||||||
| the member MUST be ignored -- i.e., processing will continue as if | ||||||||||||||
| the member had not been present. | ||||||||||||||
|
Comment on lines
+581
to
+583
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better delete it here -- this aspect is already addressed below. |
||||||||||||||
|
|
||||||||||||||
| *Note:* Problem `type` and `instance` identifiers in our APIs are not meant | ||||||||||||||
| to be resolved. {RFC-9457}[RFC 9457] encourages that problem types are URI | ||||||||||||||
| {RFC-9457}[RFC 9457] encourages that problem types are URI | ||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The old wording is IMO clearer. |
||||||||||||||
| references that point to human-readable documentation, *but* we deliberately | ||||||||||||||
| decided against that, as all important parts of the API must be documented | ||||||||||||||
| using <<101, OpenAPI>> anyway. In addition, URLs tend to be fragile and not | ||||||||||||||
| very stable over longer periods because of organizational and documentation | ||||||||||||||
| changes and descriptions might easily get out of sync. | ||||||||||||||
|
|
||||||||||||||
| In order to stay compatible with {RFC-9457}[RFC 9457] we proposed to use | ||||||||||||||
| In order to stay compatible with {RFC-9457}[RFC 9457] we recommend to use | ||||||||||||||
| https://tools.ietf.org/html/rfc3986#section-4.1[relative URI references] | ||||||||||||||
| usually defined by `absolute-path [ '?' query ] [ '#' fragment ]` as simplified | ||||||||||||||
| identifiers in `type` and `instance` fields: | ||||||||||||||
|
|
@@ -622,9 +602,131 @@ identifiers in `type` and `instance` fields: | |||||||||||||
| *Hint:* The use of https://tools.ietf.org/html/rfc3986#section-4.3[absolute | ||||||||||||||
| URIs] is not forbidden but strongly discouraged. If you use absolute URIs, | ||||||||||||||
| please reference | ||||||||||||||
| https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.0.yaml#/Problem[problem-1.0.0.yaml#/Problem] | ||||||||||||||
| https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.1.yaml#/Problem[problem-1.0.1.yaml#/Problem] | ||||||||||||||
| instead. | ||||||||||||||
|
|
||||||||||||||
| ==== Usage of Problem Object | ||||||||||||||
| Clients may use, but *should be robust and not* depend on the Problem | ||||||||||||||
| properties being present or having specific values of specific types. | ||||||||||||||
| The examples of such cases are: | ||||||||||||||
|
|
||||||||||||||
| - response might be created by infrastructure components (and have a different | ||||||||||||||
| response format, comparing to the guidelines) | ||||||||||||||
| - response might be created by a service that is unable to comply with the | ||||||||||||||
| guidelines due to certain error situations | ||||||||||||||
|
|
||||||||||||||
| In cases where the Problem Object lacks the required information, clients must | ||||||||||||||
| implement fallback mechanisms, defaulting to reasonable behavior similar to | ||||||||||||||
| handling errors without a Problem Object provided. | ||||||||||||||
|
|
||||||||||||||
| The OpenAPI schema definition of the Problem JSON object can be found | ||||||||||||||
| https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.1.yaml[on | ||||||||||||||
| GitHub]. You can reference it by using: | ||||||||||||||
|
|
||||||||||||||
| [source,yaml] | ||||||||||||||
| ---- | ||||||||||||||
| responses: | ||||||||||||||
| 503: | ||||||||||||||
| description: Service Unavailable | ||||||||||||||
| content: | ||||||||||||||
| "application/problem+json": | ||||||||||||||
| schema: | ||||||||||||||
| $ref: 'https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.1.yaml#/Problem' | ||||||||||||||
| ---- | ||||||||||||||
|
|
||||||||||||||
|
Comment on lines
+622
to
+636
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be moved to the Problem object Specification above. |
||||||||||||||
| *Hint:* The media type `application/problem+json` is often not implemented as | ||||||||||||||
| a subset of `application/json` by libraries and services, thus clients need to | ||||||||||||||
| include `application/problem+json` in the {Accept}-Header to trigger delivery | ||||||||||||||
| of the extended failure information. | ||||||||||||||
|
|
||||||||||||||
| ==== Client processing of Problem Object | ||||||||||||||
| Problem details are often not described explicitly in the API and may evolve | ||||||||||||||
| over time. | ||||||||||||||
|
|
||||||||||||||
| Unless the API defines and enumerates stable values for `type` and `instance` | ||||||||||||||
| with clear semantics, these fields *should not* be relied upon for client-side | ||||||||||||||
| automated decisions. | ||||||||||||||
|
|
||||||||||||||
| The following guidelines offer best practices for utilizing type in automated | ||||||||||||||
| processing: | ||||||||||||||
|
|
||||||||||||||
| 1. Property `type` may be used by clients to make automatic decisions in | ||||||||||||||
| certain failure modes. The `title` property serves as a concise, | ||||||||||||||
| human-readable summary of the type. It is particularly helpful for debugging | ||||||||||||||
| and serves as an engineer-readable shorthand for the problem type. | ||||||||||||||
|
|
||||||||||||||
| 2. Clients may use these fields to drive automated actions if the API | ||||||||||||||
| explicitly defines the semantics of `type` and `instance` and enumerates | ||||||||||||||
| stable values. This can be achieved by extending the Problem JSON object and | ||||||||||||||
| associating an x-extensible-enum with the type property. | ||||||||||||||
|
|
||||||||||||||
| 3. Clients must handle scenarios where the type is absent or unrecognized and | ||||||||||||||
| fallback to default behaviors. | ||||||||||||||
|
|
||||||||||||||
| 4. For collections of related APIs, using shared type values for similar errors | ||||||||||||||
| and distinct values for different errors simplifies automated processing and | ||||||||||||||
| error handling for clients working across APIs. | ||||||||||||||
|
Comment on lines
+666
to
+668
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not a hint for the clients, but for the servers is it? |
||||||||||||||
|
|
||||||||||||||
| *Note:* Include descriptions for each known error that can happen directly in | ||||||||||||||
| the specification or reference external documentation to clarify their meanings | ||||||||||||||
| and intended use. | ||||||||||||||
|
|
||||||||||||||
| ==== Extensions of Problem Object schema | ||||||||||||||
| APIs can define custom fields in the Problem Object to provide more context | ||||||||||||||
| to meet specific application needs. | ||||||||||||||
| The custom fields should not conflict with the standard fields. | ||||||||||||||
| To extend the Problem Object, the API specification must define the custom | ||||||||||||||
| Problem, which would include Problem object members and custom ones. The | ||||||||||||||
| custom Problem can be used in the API specification as a reference, same as | ||||||||||||||
| a standard Problem object. | ||||||||||||||
| Example: | ||||||||||||||
| [source,yaml] | ||||||||||||||
| ---- | ||||||||||||||
| components: | ||||||||||||||
| schemas: | ||||||||||||||
| Problem: | ||||||||||||||
| type: object | ||||||||||||||
| properties: | ||||||||||||||
| type: | ||||||||||||||
| type: string | ||||||||||||||
| format: uri | ||||||||||||||
| example: "https://example.com/errors/invalid-parameter" | ||||||||||||||
| title: | ||||||||||||||
| type: string | ||||||||||||||
| example: "Invalid Request Parameter" | ||||||||||||||
| status: | ||||||||||||||
| type: integer | ||||||||||||||
| example: 400 | ||||||||||||||
| detail: | ||||||||||||||
| type: string | ||||||||||||||
| example: "The 'color' parameter is invalid" | ||||||||||||||
|
|
||||||||||||||
| CustomProblem: | ||||||||||||||
| allOf: | ||||||||||||||
| - $ref: "#/components/schemas/Problem" | ||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not simply reference to the standard definition? |
||||||||||||||
| properties: | ||||||||||||||
| errorCode: | ||||||||||||||
| type: string | ||||||||||||||
| example: "ERROR12345" | ||||||||||||||
| flowId: | ||||||||||||||
| type: string | ||||||||||||||
| example: "2914eefe-814e-4100-a332-42bac3352524" | ||||||||||||||
| ---- | ||||||||||||||
|
|
||||||||||||||
| *Note:* In case when client does not support some of the fields, | ||||||||||||||
| they should be ignored. | ||||||||||||||
|
|
||||||||||||||
| ==== Handling Multiple Errors in Batch/Bulk Responses | ||||||||||||||
| When an API processes batch requests, multiple errors may occur. | ||||||||||||||
| To ensure clarity and usability, the response should structure these errors | ||||||||||||||
| in a way that allows clients to identify and handle individual failures. | ||||||||||||||
|
|
||||||||||||||
| Depending on the use-case the response can be structured in two ways: | ||||||||||||||
|
|
||||||||||||||
| - as an array of Problem objects where each entry in the array represents an | ||||||||||||||
| individual error related to a specific request item. | ||||||||||||||
| - as a map where associated value contains the corresponding Problem object for | ||||||||||||||
| that specific request item. | ||||||||||||||
|
|
||||||||||||||
| [#177] | ||||||||||||||
| == {MUST} not expose stack traces | ||||||||||||||
|
|
@@ -643,9 +745,9 @@ redirection to migrate clients to a new service location. However, this is | |||||||||||||
| better accomplished by one of the following. | ||||||||||||||
|
|
||||||||||||||
| 1. Changing the clients to use the new location in the first place, avoiding | ||||||||||||||
| the need for redirection. | ||||||||||||||
| the need for redirection. | ||||||||||||||
| 2. Redirecting the traffic behind the API layer (e.g. in the reverse proxy or | ||||||||||||||
| the app itself) without the client having to be involved. | ||||||||||||||
| the app itself) without the client having to be involved. | ||||||||||||||
| 3. Deprecating the endpoint and removing it as described in <<deprecation>>. | ||||||||||||||
|
|
||||||||||||||
| For idempotent {POST} cases, where you want to inform the client that a resource | ||||||||||||||
|
|
||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't remove the leading spaces -- they are needed for formating