-
Notifications
You must be signed in to change notification settings - Fork 9.1k
Description
Forgive me for the nebulous issue, but as we head towards a v.Next document, I believe that understanding the scope of what OpenAPI is trying to define will help in making the many decisions that need to be made to get to v.Next.
The terms Open World and Closed World seem to have reasonable definitions on Wikipedia. Let me try and apply the concepts to Open API.
Consider any arbitrary Open API document that describes an API. It is assumed that the document accurately describes the API. We sometimes use the word contract to define the role that the Open API document plays between the client and the server.
Is the OpenAPI document still valid if
- there exists a resource in the API that is not described?
- a resource accepts a parameter that is not described?
- a resource supports a representation format that is not described?
- a resource returns a status code that is not described?
In a closed world, the API Description describes exactly what is supported, if it is not described, then it must not exist. In an open world we cannot make assumptions about what is not described. There may be other resources, other supported formats, other parameters.
I get the feeling from the conversations I have had with people who use OpenAPI that many perceive it to be a closed world description. Certainly I believe that many people would say that returning an unspecified status code would be a contract violation.
Which brings us to the challenge. Closed world systems work well when the entire system is under the control of the creator. However, in the world of network based HTTP systems, many parts of the system are not under the control of the API designer. It is quite common for intermediary components to return status codes and media types that the API designer may have no knowledge of. It is quite common for APIs to change in ways that are additive and non-breaking and should not be considered a contract violation.
For this reason I do not believe that OpenAPI can be a truly closed world specification. My fear is that we continue to pretend that it is a closed world specification and client developers continue building clients based on a false assumption that the only thing that is true is what is described in the specification document. I am convinced this is a common cause of buggy client applications.
Another less than ideal outcome would be if we try and hold some middle ground where some parts of the specification must be exhaustively described, whereas other parts only describe some subset of what is possible. This is going to further challenge us when it comes to identifying what should be considered a breaking change and therefore require a version change.
I would like to see wording in the Open API specification that states that what is being described is what can happen, but the behavior of the API is not limited by the description document. It would be reasonable to state that behaviour that is described will not be removed without a corresponding version change. Obviously no such guarantee is made about the availability of undescribed behavior!
My guess is that many people reading this will not object to undocumented resources, undocumented parameters and undocumented response media types. However, I expect that many will feel that it is unreasonable to allow undocumented response status codes. How can a client be expected to consume an API if the API can return status codes that are not documented?
Well, first let us recall that there are an unknown number of intermediaries that may sit between your client and your API that may return statuses like 407, 502, 504, 511. The reality is that it already happens.
Second, and more importantly, let me quote RFC 7231,
HTTP clients are not required to
understand the meaning of all registered status codes, though such
understanding is obviously desirable. However, a client MUST
understand the class of any status code, as indicated by the first
digit, and treat an unrecognized status code as being equivalent to
the x00 status code of that class
The HTTP specification says that ALL clients of an HTTP API must be designed to deal with all status codes. If a client gets a 413 and it doesn't have any special handling code for that status code, then it can treat it as if it were a 400. This means that clients need to handle 200,300,400, and 500 at a minimum to be compliant with the HTTP specification.
Once you can accept this as a requirement of building a HTTP client, then the ability for an API request to return a unexpected status code gets a whole lot less concerning.
If the OpenAPI specification can be accepted as an Open World specification, then we gain a significant amount of flexibility. If we want to implement rate limiting in an API, we are no longer required to add a 429 description to every response object. And we can have a certain amount of confidence that existing client applications will not crash because if they have followed the rules, then they already know how to treat the 429 as if it were a 400.
Being open world doesn't prevent someone choosing to explicitly describe every operation in detail if they choose to. However, it opens the possibility for those of us that wish to build a more self-descriptive API, can limit what is being explicitly described. We may even be able to lift the requirement that a response object must be present with at least one response.
Taking this path makes it easier to take the decision that adding a capability to an OpenAPI description should never be considered a breaking change.
I'm sure there many other impacts of committing to this approach. Perhaps some of them may be negative. I look forward to hearing all the opinions.