Skip to content

Commit b78f66a

Browse files
committed
Add style: cookie, explain pct-encoding
This adds a `style: cookie` to provide a non-percent-encoding option for managing cookie parameters. It also explains the conditions under which automatic percent-encoding with `style: form` might work, and also links to a draft update of the cookie RFC that explains that things that look like percent-encoding should _not_ be decoded for storage, which means that `style: cookie` is providing the most compliant behavior for that updated guidance.
1 parent 49d1c51 commit b78f66a

File tree

1 file changed

+65
-21
lines changed

1 file changed

+65
-21
lines changed

src/oas.md

Lines changed: 65 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,15 +1148,13 @@ For simpler scenarios, a [`schema`](#parameter-schema) and [`style`](#parameter-
11481148

11491149
These fields MUST NOT be used with `in: "querystring"`.
11501150
1151-
When serializing `in: "header"` parameters with `schema`, URI percent-encoding MUST NOT be applied; if using an RFC6570 implementation that automatically applies it, it MUST be removed before use.
1152-
Implementations MUST pass header values through unchanged rather than attempting to automatically quote header values, as the quoting rules vary too widely among different headers; see [Appendix D](#appendix-d-serializing-headers-and-cookies) for guidance on quoting and escaping.
1153-
1154-
Serializing with `schema` is NOT RECOMMENDED for `in: "cookie"` parameters; see [Appendix D](#appendix-d-serializing-headers-and-cookies) for details.
1151+
When serializing `in: "header"` or `in: "cookie", style: "cookie"` parameters with `schema`, URI percent-encoding MUST NOT be applied, and when parsing any apparent percent-encoding MUST NOT be decoded; if using an RFC6570 implementation that automatically performs these steps, the steps MUST be reversed before use.
1152+
In these cases, implementations MUST pass values through unchanged rather than attempting to quote or escape them, as the quoting rules for headers and escaping conventions for cookies vary too widely to be performed automatically; see [Appendix D](#appendix-d-serializing-headers-and-cookies) for guidance on quoting and escaping.
11551153

11561154
| Field Name | Type | Description |
11571155
| ---- | :----: | ---- |
1158-
| <a name="parameter-style"></a>style | `string` | Describes how the parameter value will be serialized depending on the type of the parameter value. Default values (based on value of `in`): for `"query"` - `"form"`; for `"path"` - `"simple"`; for `"header"` - `"simple"`; for `"cookie"` - `"form"`. |
1159-
| <a name="parameter-explode"></a>explode | `boolean` | When this is true, parameter values of type `array` or `object` generate separate parameters for each value of the array or key-value pair of the map. For other types of parameters, or when [`style`](#parameter-style) is `"deepObject"`, this field has no effect. When `style` is `"form"`, the default value is `true`. For all other styles, the default value is `false`. |
1156+
| <a name="parameter-style"></a>style | `string` | Describes how the parameter value will be serialized depending on the type of the parameter value. Default values (based on value of `in`): for `"query"` - `"form"`; for `"path"` - `"simple"`; for `"header"` - `"simple"`; for `"cookie"` - `"form"` (for compatibility reasons; note that `style: "cookie"` SHOULD be used with `in: "cookie"`; see [Appendix D](#appendix-d-serializing-headers-and-cookies) for details). |
1157+
| <a name="parameter-explode"></a>explode | `boolean` | When this is true, parameter values of type `array` or `object` generate separate parameters for each value of the array or key-value pair of the map. For other types of parameters, or when [`style`](#parameter-style) is `"deepObject"`, this field has no effect. When `style` is `"form"` or `"cookie"`, the default value is `true`. For all other styles, the default value is `false`. |
11601158
| <a name="parameter-allow-reserved"></a>allowReserved | `boolean` | When this is true, parameter values are serialized using reserved expansion, as defined by [RFC6570](https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.3), which allows [RFC3986's reserved character set](https://datatracker.ietf.org/doc/html/rfc3986#section-2.2), as well as percent-encoded triples, to pass through unchanged, while still percent-encoding all other disallowed characters (including `%` outside of percent-encoded triples). Applications are still responsible for percent-encoding reserved characters that are not allowed by the rules of the `in` destination or media type, or are [not allowed in the path by this specification](#path-templating); see [URL Percent-Encoding](#url-percent-encoding) for details. The default value is `false`. This field only applies to `in` and `style` values that automatically percent-encode. |
11611159
| <a name="parameter-schema"></a>schema | [Schema Object](#schema-object) | The schema defining the type used for the parameter. |
11621160

@@ -1165,7 +1163,6 @@ See also [Appendix C: Using RFC6570-Based Serialization](#appendix-c-using-rfc65
11651163
###### Fixed Fields for use with `content`
11661164

11671165
For more complex scenarios, the [`content`](#parameter-content) field can define the media type and schema of the parameter, as well as give examples of its use.
1168-
Using `content` with a `text/plain` media type is RECOMMENDED for `in: "cookie"` parameters where the `schema` strategy's percent-encoding and/or delimiter rules are not appropriate.
11691166

11701167
For use with `in: "querystring"` and `application/x-www-form-urlencoded`, see [Encoding the `x-www-form-urlencoded` Media Type](#encoding-the-x-www-form-urlencoded-media-type).
11711168

@@ -1186,6 +1183,7 @@ In order to support common ways of serializing simple parameters, a set of `styl
11861183
| spaceDelimited | `array`, `object` | `query` | Space separated array values or object properties and values. This option replaces `collectionFormat` equal to `ssv` from OpenAPI 2.0. |
11871184
| pipeDelimited | `array`, `object` | `query` | Pipe separated array values or object properties and values. This option replaces `collectionFormat` equal to `pipes` from OpenAPI 2.0. |
11881185
| deepObject | `object` | `query` | Allows objects with scalar properties to be represented using form parameters. The representation of array or object properties is not defined (but see [Extending Support for Querystring Formats](#extending-support-for-querystring-formats) for alternatives). |
1186+
| cookie | `primitive`, `array`, `object` | `cookie` | Analogous to `form`, but following [[RFC6265]] `Cookie` syntax rules, meaning that name-value pairs are separated by a semicolon followed by a single space (e.g. `n1=v1; n2=v2`), and no percent-encoding or other escaping is applied; data values that require any sort of escaping MUST be provided in escaped form. |
11891187

11901188
##### URL Percent-Encoding
11911189

@@ -1211,7 +1209,11 @@ Reserved characters MUST NOT be percent-encoded when being used for reserved pur
12111209
The result of inserting non-percent-encoded delimiters into data using manual percent-encoding, including via RFC6570's reserved expansion rules, is undefined and will likely prevent implementations from parsing the results back into the correct data structures.
12121210
In some cases, such as inserting `/` into path parameter values, doing so is [explicitly forbidden](#path-templating) by this specification.
12131211

1214-
See [Appendix E](#appendix-e-percent-encoding-and-form-media-types) for a thorough discussion of percent-encoding options, compatibility, and OAS-defined delimiters that are not allowed by RFC3986, and [Appendix C](#appendix-c-using-rfc6570-based-serialization) for guidance on using RFC6570 implementations.
1212+
See also:
1213+
1214+
* [Appendix C](#appendix-c-using-rfc6570-based-serialization) for guidance on using or simulating RFC6570 implementations.
1215+
* [Appendix D](#appendix-d-serializing-headers-and-cookies) for guidance on percent-encoding and cookies, as well as other escaping approaches for headers and cookies
1216+
* [Appendix E](#appendix-e-percent-encoding-and-form-media-types) for a thorough discussion of percent-encoding options, compatibility, and handling OAS-defined delimiters that are not allowed by RFC3986
12151217

12161218
##### Serialization and Examples
12171219

@@ -1265,6 +1267,8 @@ The following table shows serialized examples, as would be shown with the `seria
12651267
| pipeDelimited | false | _n/a_ | _n/a_ | <span style="white-space: nowrap;">color=blue%7Cblack%7Cbrown</span> | <span style="white-space: nowrap;">color=R%7C100%7CG%7C200%7CB%7C150</span> |
12661268
| pipeDelimited | true | _n/a_ | _n/a_ | _n/a_ | _n/a_ |
12671269
| deepObject | _n/a_ | _n/a_ | _n/a_ | _n/a_ | <span style="white-space: nowrap;">color%5BR%5D=100&color%5BG%5D=200&color%5BB%5D=150</span> |
1270+
| cookie | false | <span style="white-space: nowrap;">color=</span> | <span style="white-space: nowrap;">color=blue</span> | <span style="white-space: nowrap;">color=blue,black,brown</span> | <span style="white-space: nowrap;">color=R,100,G,200,B,150</span> |
1271+
| cookie | true | <span style="white-space: nowrap;">color=</span> | <span style="white-space: nowrap;">color=blue</span> | <span style="white-space: nowrap;">color=blue; color=black; color=brown</span> | <span style="white-space: nowrap;">R=100; G=200; B=150</span> |
12681272

12691273
##### Extending Support for Querystring Formats
12701274

@@ -1297,6 +1301,54 @@ examples:
12971301
serializedValue: "12345678,90099"
12981302
```
12991303

1304+
1305+
A cookie parameter with an exploded object (the default for `style: "cookie"`):
1306+
1307+
```yaml
1308+
name: cookie
1309+
in: cookie
1310+
style: cookie
1311+
schema:
1312+
type: object
1313+
properties:
1314+
greeting:
1315+
type: string
1316+
code:
1317+
type: integer
1318+
minimum: 0
1319+
examples:
1320+
Object:
1321+
description: |
1322+
Note that the comma (,) has been pre-percent-encoded
1323+
to "%2C" in the data, as it is forbidden in
1324+
cookie values. However, the exclamation point (!)
1325+
is legal in cookies, so it can be left unencoded.
1326+
dataValue: {
1327+
"greeting": "Hello%2C world!",
1328+
"code": 42
1329+
}
1330+
serializedValue: "greeting=Hello%2C world!; code: 42"
1331+
```
1332+
1333+
A cookie parameter relying on the percent-encodingn behavior of the default `style: "form"`:
1334+
1335+
```yaml
1336+
name: greeting
1337+
in: cookie
1338+
schema:
1339+
type: string
1340+
examples:
1341+
Greeting:
1342+
description: |
1343+
Note that in this approach, RFC6570's percent-encoding
1344+
process applies, so unsafe characters are not
1345+
pre-percent-encoded. This results in all non-URL-safe
1346+
characters, rather than just the one non-cookie-safe
1347+
character, getting percent-encoded.
1348+
dataValue: "Hello, world!"
1349+
serializedValue: "greeting=Hello%2C%20world%21"
1350+
```
1351+
13001352
A path parameter of a string value:
13011353

13021354
```yaml
@@ -5127,22 +5179,14 @@ For this reason, any data being passed to a header by way of a [Parameter](#para
51275179

51285180
### Percent-Encoding and Cookies
51295181

5130-
_**Note:** OAS v3.0.4 and v3.1.1 applied the advice in this section to avoid RFC6570-style serialization to both headers and cookies.
5131-
However, further research has indicated that percent-encoding was never intended to apply to headers, so this section has been corrected to apply only to cookies._
5132-
51335182
[RFC6570](https://www.rfc-editor.org/rfc/rfc6570)'s percent-encoding behavior is not always appropriate for `in: "cookie"` parameters.
5134-
In many cases, it is more appropriate to use `content` with a media type such as `text/plain` and require the application to assemble the correct string.
5135-
Other media types, such as `application/linkset` (see [Modeling Link Headers](#modeling-link-headers)), are directly suitable for use as `content` for specific headers.
5136-
5137-
In some cases, setting `allowReserved: true` will be sufficient to avoid incorrect encoding, however many characters are still percent-encoded with this field enabled, so care must be taken to ensure no unexpected percent-encoding will take place.
5138-
5139-
[RFC6265](https://www.rfc-editor.org/rfc/rfc6265) recommends (but does not strictly required) base64 encoding (`contentEncoding: "base64"`) if "arbitrary data" will be stored in a cookie.
5140-
Note that the standard base64-encoding alphabet includes non-URL-safe characters that are percent-encoded by RFC6570 expansion; serializing values through both encodings is NOT RECOMMENDED.
5141-
While `contentEncoding` also supports the `base64url` encoding, which is URL-safe, the header and cookie RFCs do not mention this encoding.
5183+
While percent-encoding seems more common as an escaping mechanism than the base64 encoding (`contentEncoding`: "base64") recommended by [[RFC6265]], [section 5.6 of draft-ietf-httpbis-rfc6265bis-20](https://www.ietf.org/archive/id/draft-ietf-httpbis-rfc6265bis-20.html#section-5.6), the proposed update to that RFC, notes that cookies sent in the `Set-Cookie` response header that appear to be percent-encoded MUST NOT be decoded when stored by the client, which would mean that they are already encoded when retrieved from that storage for use in the `Cookie` request header.
5184+
The behavior of `style: "cookie"` assumes this usage, and _does not_ apply or remove percent-encoding.
51425185

5186+
If automatic percent-encoding is desired, `style: "form"` with a primitive value or with the non-default `explode` value of `false` provides this behavior.
5187+
However, note that the default value of `explode: true` for `style: "form"` with non-primitive values uses the wrong delimiter for cookies (`&` instead of `;` followed by a single space) to set multiple cookie values.
51435188
Using `style: "form"` with `in: "cookie"` via an RFC6570 implementation requires stripping the `?` prefix, as when producing `application/x-www-form-urlencoded` message bodies.
5144-
5145-
For multiple values, `style: "form"` is always incorrect, even if no characters are subject to percent-encoding, as name=value pairs in cookies are delimited by a semicolon followed by a space character rather than `&`.
5189+
To allow the full use of `style: "form"` with `in: "cookie"`, the `allowReserved` field is now supported for cookies.
51465190

51475191
## Appendix E: Percent-Encoding and Form Media Types
51485192

0 commit comments

Comments
 (0)