Skip to content
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

Do we need to clarify what a response missing content means #3536

Open
philsturgeon opened this issue Jan 31, 2024 · 7 comments
Open

Do we need to clarify what a response missing content means #3536

philsturgeon opened this issue Jan 31, 2024 · 7 comments
Labels
clarification requests to clarify, but not change, part of the spec media and encoding Issues regarding media type support and how to encode data (outside of query/path params)

Comments

@philsturgeon
Copy link
Contributor

I've been writing up guides for contract testing with OpenAPI in a bunch of different languages, and the Ruby on Rails one using https://github.com/mkon/openapi_contracts/ gave this great example, letting me know an empty response has been defined, but a response has been provided by the API implementation.

1) widgets POST /widgets responds with 201 when valid
    Failure/Error: expect(response).to match_openapi_doc(OPENAPI_DOC)
      * Expected empty response body
    # ./spec/requests/widgets_spec.rb:17:in `block (3 levels) in <top (required)>'

Here's some OpenAPI for visual people:

post:
  summary: Create Widget
  operationId: create-widget
  requestBody:
    description: Widget to create
    required: true
    content:
      application/json:
        schema:
          $ref: "../components/schema/widget.yaml"
  responses:
    '201':
      description: Created

Does this mean "There is definitely no content" or "I haven't bothered defining it but dont worry about it"?

There are ways to define a "dont worry about it" thats a bit more specific, like:

post:
  summary: Create Widget
  operationId: create-widget
  requestBody:
    description: Widget to create
    required: true
    content:
      application/json:
        schema:
          $ref: "../components/schema/widget.yaml"
  responses:
    '201':
      description: Created
      content:
        application/json:
          schema:
            type: object

Or you can pop an example in instead of worrying about defining a schema but still providing something tangible for docs/mocks to think about.

Scrabbling round the spec I coudn't find anything in 3.0 or 3.1 but the SmartBear Guide on Describing Responses does explicitly say:

Some responses, such as 204 No Content, have no body. To indicate the response body is empty, do not specify a content for the response:

This leads me to think all responses missing a content should have no body, because otherwise there's going to be some weird logic going "If 204 then missing means definitely no body but otherwise it just means I dunno!"

Would that be a breaking change to 3.1.x if its clarifying intent? Or does this have to go to Moonwalk?

@handrews handrews added the media and encoding Issues regarding media type support and how to encode data (outside of query/path params) label Jan 31, 2024
@handrews
Copy link
Member

handrews commented Jan 31, 2024

@handrews handrews added the clarification requests to clarify, but not change, part of the spec label Jan 31, 2024
@iglosiggio
Copy link

Hi! I need the same clarification:

Does this mean "There is definitely no content" or "I haven't bothered defining it but don't worry about it"?

I'm working on some scaffolding tools that have to extract meaning from these kinds of situations. My original interpretation was "will have a response with something" but that obviously breaks the intention when 204 - No Content is meant.

So:

  • How can we specify "There's no content on this response"?
  • How can we specift "This response may have anything as its contents"?
  • What's the interpretation for a content:-less response?

I saw the discussion at #2236 but that's outside my current scope because we are not intending to support optionally present responses (yet).

@karenetheridge
Copy link
Member

karenetheridge commented Jul 25, 2024

How can we specify "There's no content on this response"?

It depends on what you mean...

  • Do you mean "There must not be a Content-Type response header"? If so, you can specify that, by defining a header with a false schema.
  • Do you mean "There must not be a Content-Length response header"? If so, see above.
  • Do you mean "Okay, there could be a Content-Length header, but if it exists, it must be zero"? If so, you can specify that too, with "required": false and "schema": "const": "0".

@lornajane
Copy link
Contributor

Discussion in TDC this week, we don't think we can infer from an absence of response information in an API description whether this means there is no response expected, or the response information is missing from the API description file.

@karenetheridge
Copy link
Member

karenetheridge commented Jul 25, 2024

How can we specift "This response may have anything as its contents"?

I would do that with...

responses:
  2xx:
    content:
      */*:
        schema: {}

..but responses isn't a required part of an openapi specification, so you can just omit it entirely if you like. You would only need to do the above if you want to be more specific for error responses (e.g. 4xx) and leave the 2xx response as more lax.

@karenetheridge
Copy link
Member

karenetheridge commented Jul 25, 2024

Given the questions in this thread, we might need to be more explicit in the specification that absence of a specification does NOT indicate that a particular component must be absent; rather the lack of a specification for a thing means that anything is allowed. I'm sure there is some kind of strict language in RFC-style that can be used here, rather than doing it colloquially.

@iglosiggio
Copy link

iglosiggio commented Jul 26, 2024

Thanks for the detailed response!

  • Do you mean "There must not be a Content-Type response header"? If so, you can specify that, by defining a header with a false schema.
  • Do you mean "There must not be a Content-Length response header"? If so, see above.

So something like:

responses:
  200:
    description: "Everything went OK!"
    content:
      */*:
        schema: false

Right?

Is an exception like "A 204 response without schema can be interpreted as a false schema" viable? I know this is ugly, but I saw multiple APIs do:

responses:
  204:
    description: "Don't expect any content from me lol. I'm a 204"
  • Do you mean "Okay, there could be a Content-Length header, but if it exists, it must be zero"? If so, you can specify that too, with "required": false and "schema": "const": "0".

You mean that as a schema for the Content-Length header, right?

Given the questions in this thread, we might need to be more explicit in the specification that absence of a specification does NOT indicate that a particular component must be absent; rather the lack of a specification for a thing means that anything is allowed. I'm sure there is some kind of strict language in RFC-style that can be used here, rather than doing it colloquially.

Maybe something like:

4.8.17.1 Fixed Fields

Field Name Type Description
content Map[string, Media Type Object] A map containing descriptions of potential response payloads. The key is a media type or media type range and the value describes it. For responses that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/*. For responses that match no key a Media Type Object with a true schema SHOULD be applied.

If we want a 204 exception:

4.8.17.1 Fixed Fields

Field Name Type Description
content Map[string, Media Type Object] A map containing descriptions of potential response payloads. The key is a media type or media type range and the value describes it. For responses that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/*. For responses that match no key a default Media Type Object SHOULD be applied, its schema depends on the status code of the response: false for 204 and true for any other.

The biggest issue with the exception is that it breaks reusability of responses via de $ref mechanism (because now the interpretation of a Response Object depends on the Operation Object that embeds it. Alternatively we can use that the exception is a MAY thing where implementations are allowed but not required to interpret 204 responses in a more strict fashion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clarification requests to clarify, but not change, part of the spec media and encoding Issues regarding media type support and how to encode data (outside of query/path params)
Projects
None yet
Development

No branches or pull requests

5 participants