Skip to content
Open
Show file tree
Hide file tree
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
55 changes: 29 additions & 26 deletions src/oas.md
Original file line number Diff line number Diff line change
Expand Up @@ -769,14 +769,14 @@ See [Appendix E](#appendix-e-percent-encoding-and-form-media-types) for a detail
There are five possible parameter locations specified by the `in` field:

* path - Used together with [Path Templating](#path-templating), where the parameter value is actually part of the operation's URL. This does not include the host or base path of the API. For example, in `/items/{itemId}`, the path parameter is `itemId`.
* query - Parameters that are appended to the URL. For example, in `/items?id=###`, the query parameter is `id`; MUST NOT appear in the same operation (or in the operation's path-item) as an `in: "querystring"` parameter.
* query - Parameters that are appended to the URL with the `?` character (or for subsequent query parameters, with the `&` character); MUST NOT appear in the same operation (or in the operation's path-item) as an `in: "querystring"` parameter.
* querystring - A parameter that treats the entire URL query string as a value which MUST be specified using the `content` field, most often with media type `application/x-www-form-urlencoded` using [Encoding Objects](#encoding-object) in the same way as with request bodies of that media type; MUST NOT appear more than once, and MUST NOT appear in the same operation (or in the operation's path-item) as any `in: "query"` parameters.
* header - Custom headers that are expected as part of the request. Note that [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#section-5.1) states header names are case-insensitive.
* cookie - Used to pass a specific cookie value to the API.

#### Fixed Fields

The rules for serialization of the parameter are specified in one of two ways.
The rules for serialization and deserialization of the parameter are specified in one of two ways.
Parameter Objects MUST include either a `content` field or a `schema` field, but not both.
See [Appendix B](#appendix-b-data-type-conversion) for a discussion of converting values of various types to string representations.

Expand Down Expand Up @@ -819,8 +819,8 @@ In these cases, implementations MUST pass values through unchanged rather than a
| ---- | :----: | ---- |
| <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). |
| <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`. |
| <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. |
| <a name="parameter-schema"></a>schema | [Schema Object](#schema-object) | The schema defining the type used for the parameter. |
| <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 (that is: `in: path`, `in: query`, and `in: cookie` with `style: form`). |
| <a name="parameter-schema"></a>schema | [Schema Object](#schema-object) | The schema defining the type and other constraints used for the parameter. |

See also [Appendix C: Using RFC6570-Based Serialization](#appendix-c-using-rfc6570-based-serialization) for additional guidance.

Expand Down Expand Up @@ -923,19 +923,19 @@ The following table shows serialized examples, as would be shown with the `seria
| label | true | _empty_ | .blue | .blue.black.brown | .R=100.G=200.B=150 |
| simple | false | _empty_ | blue | blue,black,brown | R,100,G,200,B,150 |
| simple | true | _empty_ | blue | blue,black,brown | R=100,G=200,B=150 |
| form | 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> |
| form | 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> |
| spaceDelimited</span> | false | _n/a_ | _n/a_ | <span style="white-space: nowrap;">color=blue%20black%20brown</span> | <span style="white-space: nowrap;">color=R%20100%20G%20200%20B%20150</span> |
| form | false | color= | color=blue | color=blue,black,brown | color=R,100,G,200,B,150 |
| form | true | color= | color=blue | color=blue&color=black&color=brown | R=100&G=200&B=150 |
| spaceDelimited | false | _n/a_ | _n/a_ | color=blue%20black%20brown | color=R%20100%20G%20200%20B%20150 |
| spaceDelimited | true | _n/a_ | _n/a_ | _n/a_ | _n/a_ |
| 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> |
| pipeDelimited | false | _n/a_ | _n/a_ | color=blue%7Cblack%7Cbrown | color=R%7C100%7CG%7C200%7CB%7C150 |
| pipeDelimited | true | _n/a_ | _n/a_ | _n/a_ | _n/a_ |
| 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> |
| 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> |
| 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> |
| deepObject | _n/a_ | _n/a_ | _n/a_ | _n/a_ | color%5BR%5D=100&color%5BG%5D=200&color%5BB%5D=150 |
| cookie | false | color= | color=blue | color=blue,black,brown | color=R,100,G,200,B,150 |
| cookie | true | color= | color=blue | color=blue; color=black; color=brown | R=100; G=200; B=150 |

#### Extending Support for Querystring Formats

Many frameworks define query string syntax for complex values, such as appending array indices to parameter names or indicating multiple levels of of nested objects, which go well beyond the capabilities of the `deepObject` style.
Many frameworks define query string syntax for complex values, such as appending array indices to parameter names or indicating multiple levels of nested objects, which go well beyond the capabilities of the `deepObject` style.

As these are not standards, and often contradict each other, the OAS does not attempt to support them directly.
Two avenues are available for supporting such formats with `in: "querystring"`:
Expand Down Expand Up @@ -1070,7 +1070,7 @@ examples:
dataValue:
page: 4
pageSize: 50
serializeValue: page=4&pageSize=50
serializedValue: page=4&pageSize=50
```

A complex parameter using `content` to define serialization, with multiple levels and types of examples shown to make the example usage options clear — note that `dataValue` is the same at both levels and does not need to be shown in both places in normal usage, but `serializedValue` is different:
Expand All @@ -1091,15 +1091,17 @@ content:
long:
type: number
examples:
dataValue:
lat: 10
long: 60
serializedValue: '{"lat":10,"long":60}'
'New York':
dataValue:
lat: 40.6
long: -73.9
serializedValue: '{"lat":40.6,"long":-73.9}'
examples:
dataValue:
lat: 10
long: 60
serializedValue: coordinates=%7B%22lat%22%3A10%2C%22long%22%3A60%7D
'New York':
dataValue:
lat: 40.6
long: -73.9
serializedValue: coordinates=%7B%22lat%22%3A40.6%2C%22long%22%3A-73.9%7D
```

A querystring parameter using regular form encoding, but managed with a Media Type Object.
Expand All @@ -1108,6 +1110,7 @@ Examples are shown at both the media type and parameter level to emphasize that,

```yaml
in: querystring
name: metadata
content:
application/x-www-form-urlencoded:
schema:
Expand Down Expand Up @@ -2383,7 +2386,7 @@ The `serializedValue` and `externalValue` fields both MUST show the serialized f
For Media Type Objects, this is a document of the appropriate media type, with any Encoding Object effects applied.
For Parameter and Header Objects using `schema` and `style` rather than a Media Type Object, see [Style Examples](#style-examples) for what constitutes a serialized value.

##### Criteria for `serializedExample`
##### Criteria for `serializedValue`

A serialization can be represented as a valid Unicode string in `serializedValue` if any of the following are true of the serialization:

Expand Down Expand Up @@ -2858,7 +2861,7 @@ components:
In an HTTP message, the serialized example would look like:

```http
Set-Cookie: lang=en-US; Expires=Wed, 09 Jun 2021 10:18:14 GM
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
Set-Cookie: urlSafeData=Hello%2C%20world%21
```
Expand Down Expand Up @@ -4449,8 +4452,7 @@ application/xml:
- Some text
- unit: cubits
value: 42
null
]
- null
externalValue: ./examples/OneTwoThree.xml
```

Expand Down Expand Up @@ -4909,7 +4911,7 @@ parameters:
type: string
```

This example is equivalent to RFC6570's `{?foo*,bar}`, and **NOT** `{?foo*}{&bar}`. The latter is problematic because if `foo` is not defined, the result will be an invalid URI.
This example is equivalent to RFC6570's `{?foo*,bar}`, and **NOT** `{?foo*}{&bar}`. The latter is problematic because if `foo` is not defined (see [RFC6570 §2.3](https://www.rfc-editor.org/rfc/rfc6570#section-2.3) for details on what is considered undefined), the result will be an invalid URI.
The `&` prefix operator has no equivalent in the Parameter Object.

Note that RFC6570 does not specify behavior for compound values beyond the single level addressed by `explode`. The result of using objects or arrays where no behavior is clearly specified for them is implementation-defined.
Expand Down Expand Up @@ -4971,6 +4973,7 @@ parameters:
type: array
items:
type: string
explode: false
```

This translates to the following URI Template:
Expand Down
42 changes: 29 additions & 13 deletions src/schemas/validation/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -421,15 +421,11 @@ $defs:
type: string
explode:
type: boolean
allowReserved:
default: false
type: boolean
allOf:
- $ref: '#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-path'
- $ref: '#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-header'
- $ref: '#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-query'
- $ref: '#/$defs/parameter/dependentSchemas/schema/$defs/styles-for-cookie'
- $ref: '#/$defs/styles-for-form'

$defs:
styles-for-path:
Expand All @@ -439,6 +435,8 @@ $defs:
const: path
then:
properties:
name:
pattern: '^[^{}]+$'
style:
default: simple
enum:
Expand All @@ -447,6 +445,11 @@ $defs:
- simple
required:
const: true
explode:
default: false
allowReserved:
type: boolean
default: false
required:
- required

Expand All @@ -460,6 +463,8 @@ $defs:
style:
default: simple
const: simple
explode:
default: false

styles-for-query:
if:
Expand All @@ -475,6 +480,10 @@ $defs:
- spaceDelimited
- pipeDelimited
- deepObject
allowReserved:
type: boolean
default: false
$ref: '#/$defs/explode-for-form'

styles-for-cookie:
if:
Expand All @@ -488,6 +497,17 @@ $defs:
enum:
- form
- cookie
explode:
default: true
if:
properties:
style:
const: form
then:
properties:
allowReserved:
type: boolean
default: false

unevaluatedProperties: false

Expand Down Expand Up @@ -615,6 +635,7 @@ $defs:
properties:
allowReserved:
default: false
$ref: '#/$defs/explode-for-form'
explode:
properties:
style:
Expand All @@ -625,9 +646,8 @@ $defs:
properties:
style:
default: form
allOf:
- $ref: '#/$defs/specification-extensions'
- $ref: '#/$defs/styles-for-form'
$ref: '#/$defs/explode-for-form'
$ref: '#/$defs/specification-extensions'
unevaluatedProperties: false

responses:
Expand Down Expand Up @@ -808,9 +828,6 @@ $defs:
explode:
default: false
type: boolean
allowReserved:
default: false
type: boolean
allOf:
- $ref: '#/$defs/examples'
- $ref: '#/$defs/specification-extensions'
Expand Down Expand Up @@ -1118,13 +1135,12 @@ $defs:
additionalProperties:
type: string

styles-for-form:
explode-for-form:
$comment: for encoding objects, and query and cookie parameters, style=form is the default
if:
properties:
style:
const: form
required:
- style
then:
properties:
explode:
Expand Down
12 changes: 12 additions & 0 deletions tests/schema/fail/header-object-allowReserved.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
openapi: 3.2.0
info:
title: allowReserved only permitted with in and style values that percent-encode
version: 1.0.0
components:
headers:
Style:
schema:
type: array
style: simple
explode: true
allowReserved: true
12 changes: 12 additions & 0 deletions tests/schema/fail/parameter-object-cookie-allowReserved.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
openapi: 3.2.0
info:
title: allowReserved only permitted with in and style values that percent-encode
version: 1.0.0
components:
parameters:
my_cookie:
name: my_cookie
in: cookie
style: cookie
allowReserved: true
schema: {}
11 changes: 11 additions & 0 deletions tests/schema/fail/parameter-object-header-allowReserved.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
openapi: 3.2.0
info:
title: allowReserved only permitted with in and style values that percent-encode
version: 1.0.0
components:
parameters:
header:
name: my-header
in: header
allowReserved: false
schema: {}
1 change: 0 additions & 1 deletion tests/schema/pass/header-object-examples.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,3 @@ components:
type: array
style: simple
explode: true
allowReserved: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
openapi: 3.2.0
info:
title: allowReserved only permitted with in and style values that percent-encode
version: 1.0.0
components:
parameters:
style_form:
name: my_form_cookie
in: cookie
# default style is form, therefore allowReserved is allowed
allowReserved: true
schema: {}
style_cookie:
name: my_cookie_cookie
in: cookie
style: cookie
# no percent decoding for style=cookie, therefore allowReserved is not allowed
schema: {}
12 changes: 8 additions & 4 deletions tests/schema/pass/parameter-object-examples.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,23 @@ paths:
in: header
description: token to be passed as a header
required: true
explode: false
schema:
type: array
items:
type: integer
format: int64
style: simple
- name: username
- name: usernames
in: path
description: username to fetch
description: usernames to fetch
required: true
explode: false
schema:
type: string
type: array
- name: id
in: query
description: ID of the object to fetch
description: IDs of the object to fetch
required: false
schema:
type: array
Expand Down Expand Up @@ -55,10 +57,12 @@ paths:
- in: cookie
name: my_cookie1
style: form
explode: false
schema: {}
- in: cookie
name: my_cookie2
style: cookie
explode: true
schema: {}
/user:
parameters:
Expand Down
12 changes: 12 additions & 0 deletions tests/schema/pass/parameter-object-path-allowReserved.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
openapi: 3.2.0
info:
title: api
version: 1.0.0
components:
parameters:
path:
name: my-path
in: path
required: true
allowReserved: false
schema: {}
11 changes: 11 additions & 0 deletions tests/schema/pass/parameter-object-query-allowReserved.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
openapi: 3.2.0
info:
title: allowReserved only permitted with in and style values that percent-encode
version: 1.0.0
components:
parameters:
my_query:
name: my_query
in: query
allowReserved: true
schema: {}
Loading