Skip to content

v3.2: Provide guidance for the Set-Cookie response header #4748

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

Open
wants to merge 4 commits into
base: v3.2-dev
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions src/oas.md
Original file line number Diff line number Diff line change
Expand Up @@ -2451,6 +2451,75 @@ Using `content` with a `text/plain` media type is RECOMMENDED for headers where
| ---- | :----: | ---- |
| <a name="header-content"></a>content | Map[`string`, [Media Type Object](#media-type-object)] | A map containing the representations for the header. The key is the media type and the value describes it. The map MUST only contain one entry. |

##### Representing the `Set-Cookie` Header

As noted in [[!RFC9110]] [Section 5.3](https://www.rfc-editor.org/rfc/rfc9110.html#section-5.3) the `Set-Cookie` response header violates the requirements for representing multiple values as a comma-separated list, as `style: "simple"` produces.

```http
Set-Cookie: lang=en-US; Expires=Wed, 09 Jun 2021 10:18:14 GMT
Set-Cookie: foo=bar; Expires=Wed, 09 Jun 2021 10:18:14 GMT
```

If these values were to be placed on a single line using `style: "simple"`, the result would be `lang=en-US; Expires=Wed, 09 Jun 2021 10:18:14 GMT,foo=bar; Expires=Wed, 09 Jun 2021 10:18:14 GMT`, which when split would then produce four values: `lang=en-US; Expires=Wed`, `09 Jun 2021 10:18:14 GMT`, `foo=bar; Expires=Wed`, and `09 Jun 2021 10:18:14 GMT`.
While the two dates (`09...`) are not valid `Set-Cookie` values on their own, [[?RFC6265]] does not provide any guarantee that all such embedded uses of commas will produce detectable errors when split in this way.

RFC9110 therefore advises recipients to 'handle "Set-Cookie" as a special case while processing fields,' so the OAS similarly applies a special case to its handling of `Set-Cookie`.

When an OAS implementation is mapping directly between the multi-`Set-Cookie:` header line format and an array representation, without any intermediate single string holding the multiple values, no special handling is needed as the behavior is the same as for headers that can be either on a single line with comma-separated values or on multiple lines.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wasn't instantly clear to me. Multi-header? Multi-line? I think we want to explain that we're mapping between the format of multiple set-cookie headers and an array representation but I may have confused myself by now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lornajane yeah this is a bit weird and I could use some help streamlining it. It might take a bit before I can come back and explain because I want to update PR #4673 to be more clear, which I think will help explain this. Or at least help me sort out my thoughts.


However, if a multi-value text representation is needed, such as for a `text/plain` representation (using the `content` field) or in an Example Object, the following special handling is required:

For the `Set-Cookie` response header _**only**_, `style: "simple"` MUST be treated as producing a newline-delimited list instead of a comma-separated list, with each line corresponding to the value of a single `Set-Cookie:` header field.
This newline-delimited format MUST be used whenever a string representing the values is required, including in the [Example Object's](#example-object) serialized example fields, and when using `content` with a `text/plain` [Media Type Object](#media-type-object) as is necessary to prevent percent-encoding whitespace.

The following example shows two different ways to describe `Set-Cookie` headers that require cookies named `"lang"` and `"foo"`. The first uses `content` to preserve the necessary whitespace in the `"Expires"` cookie attribute, while the second shows the use of `style: "simple"` and forbids whitespace to ensure that values work with this serialization approach:

```yaml
components:
headers:
SetCookieWithExpires:
# Spaces within the Expires values prevent the use of `schema` and
# `style` as they would be percent-encoded, even with `allowReserved`.
content:
text/plain:
schema:
type: string
allOf:
- pattern: "^lang=[^;];.*Expires="
- pattern: "^foo=[^;];.*Expires="
examples:
WithExpires:
# This demonstrates that the text is required to be provided
# in the final format, and is not changed by serialization.
# In practice, it is not necessary to show both fields here.
dataValue: |
lang=en-US; Expires=Wed, 09 Jun 2021 10:18:14 GMT
foo=bar; Expires=Wed, 09 Jun 2021 10:18:14 GMT
serializedValue: |
lang=en-US; Expires=Wed, 09 Jun 2021 10:18:14 GMT
foo=bar; Expires=Wed, 09 Jun 2021 10:18:14 GMT
SetCookieWithNoSpaces:
schema:
type: object
required:
- lang
- foo
additionalProperties:
type: string
pattern: "^[^[:space:]]$"
style: simple
explode: true
examples:
SetCookies:
dataValue: {
"lang": "en-US",
"foo": "bar"
}
serializedValue: |
lang=en-US
foo=bar
```

##### Header Object Example

A simple header of type `integer`:
Expand Down