Skip to content

Commit a43f132

Browse files
authored
Merge pull request #4590 from handrews/querystring
v3.2: Add `in: "querystring"` parameter location treating the entire query string as one chunk of content
2 parents 68eee22 + bb32b97 commit a43f132

File tree

2 files changed

+89
-14
lines changed

2 files changed

+89
-14
lines changed

src/oas.md

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -950,7 +950,8 @@ See [Appendix E](#appendix-e-percent-encoding-and-form-media-types) for a detail
950950
There are four possible parameter locations specified by the `in` field:
951951

952952
* 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`.
953-
* query - Parameters that are appended to the URL. For example, in `/items?id=###`, the query parameter is `id`.
953+
* 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 as an `in: "querystring"` parameter.
954+
* 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 as any `in: "query"` parameters.
954955
* 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.
955956
* cookie - Used to pass a specific cookie value to the API.
956957

@@ -966,8 +967,8 @@ These fields MAY be used with either `content` or `schema`.
966967

967968
| Field Name | Type | Description |
968969
| ---- | :----: | ---- |
969-
| <a name="parameter-name"></a>name | `string` | **REQUIRED**. The name of the parameter. Parameter names are _case sensitive_. <ul><li>If [`in`](#parameter-in) is `"path"`, the `name` field MUST correspond to a template expression occurring within the [path](#paths-path) field in the [Paths Object](#paths-object). See [Path Templating](#path-templating) for further information.<li>If [`in`](#parameter-in) is `"header"` and the `name` field is `"Accept"`, `"Content-Type"` or `"Authorization"`, the parameter definition SHALL be ignored.<li>For all other cases, the `name` corresponds to the parameter name used by the [`in`](#parameter-in) field.</ul> |
970-
| <a name="parameter-in"></a>in | `string` | **REQUIRED**. The location of the parameter. Possible values are `"query"`, `"header"`, `"path"` or `"cookie"`. |
970+
| <a name="parameter-name"></a>name | `string` | **REQUIRED**. The name of the parameter. Parameter names are _case sensitive_. <ul><li>If [`in`](#parameter-in) is `"path"`, the `name` field MUST correspond to a template expression occurring within the [path](#paths-path) field in the [Paths Object](#paths-object). See [Path Templating](#path-templating) for further information.<li>If [`in`](#parameter-in) is `"header"` and the `name` field is `"Accept"`, `"Content-Type"` or `"Authorization"`, the parameter definition SHALL be ignored.<li>If `in` is `"querystring"`, or for [certain combinations](#style-examples) of [`style`](#parameter-style) and [`explode`](#parameter-explode), the value of `name` is not used in the parameter serialization.<li>For all other cases, the `name` corresponds to the parameter name used by the [`in`](#parameter-in) field.</ul> |
971+
| <a name="parameter-in"></a>in | `string` | **REQUIRED**. The location of the parameter. Possible values are `"query"`, `"querystring"`, `"header"`, `"path"` or `"cookie"`. |
971972
| <a name="parameter-description"></a>description | `string` | A brief description of the parameter. This could contain examples of use. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. |
972973
| <a name="parameter-required"></a>required | `boolean` | Determines whether this parameter is mandatory. If the [parameter location](#parameter-in) is `"path"`, this field is **REQUIRED** and its value MUST be `true`. Otherwise, the field MAY be included and its default value is `false`. |
973974
| <a name="parameter-deprecated"></a> deprecated | `boolean` | Specifies that a parameter is deprecated and SHOULD be transitioned out of usage. Default value is `false`. |
@@ -983,6 +984,8 @@ For simpler scenarios, a [`schema`](#parameter-schema) and [`style`](#parameter-
983984
When `example` or `examples` are provided in conjunction with the `schema` field, the example SHOULD match the specified schema and follow the prescribed serialization strategy for the parameter.
984985
The `example` and `examples` fields are mutually exclusive, and if either is present it SHALL _override_ any `example` in the schema.
985986

987+
These fields MUST NOT be used with `in: "querystring"`.
988+
986989
Serializing with `schema` is NOT RECOMMENDED for `in: "cookie"` parameters, `in: "header"` parameters that use HTTP header parameters (name=value pairs following a `;`) in their values, or `in: "header"` parameters where values might have non-URL-safe characters; see [Appendix D](#appendix-d-serializing-headers-and-cookies) for details.
987990

988991
| Field Name | Type | Description |
@@ -1001,6 +1004,8 @@ See also [Appendix C: Using RFC6570-Based Serialization](#appendix-c-using-rfc65
10011004
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.
10021005
Using `content` with a `text/plain` media type is RECOMMENDED for `in: "header"` and `in: "cookie"` parameters where the `schema` strategy is not appropriate.
10031006

1007+
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).
1008+
10041009
| Field Name | Type | Description |
10051010
| ---- | :----: | ---- |
10061011
| <a name="parameter-content"></a>content | Map[`string`, [Media Type Object](#media-type-object)] | A map containing the representations for the parameter. The key is the media type and the value describes it. The map MUST only contain one entry. |
@@ -1057,6 +1062,16 @@ The following table shows examples, as would be shown with the `example` or `exa
10571062
| deepObject | false | _n/a_ | _n/a_ | _n/a_ | _n/a_ |
10581063
| deepObject | true | _n/a_ | _n/a_ | _n/a_ | <span style="white-space: nowrap;">?color%5BR%5D=100&color%5BG%5D=200&color%5BB%5D=150</span> |
10591064

1065+
##### Extending Support for Querystring Formats
1066+
1067+
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.
1068+
1069+
As these are not standards, and often contradict each other, the OAS does not attempt to support them directly.
1070+
Two avenues are available for supporting such formats with `in: "querystring"`:
1071+
1072+
* Use `content` and `text/plain` with a schema of `type: "string"` and define the format outside of OpenAPI. While this requires more work to document and construct or parse the format, which is seen as a plain string from the OpenAPI perspective, it provides the easiest flexible option
1073+
* Define a media type (which need not necessarily be [IANA-registered](https://www.rfc-editor.org/rfc/rfc6838.html)) and a process for mapping in-memory data to the serialized media type. To increase the likelihood of support across multiple tools, submit a registration for the media type and process to the OpenAPI Initiative's [Media Type Registry](#media-type-registry).
1074+
10601075
##### Parameter Object Examples
10611076

10621077
A header parameter with an array of 64-bit integer numbers:
@@ -1131,6 +1146,49 @@ content:
11311146
type: number
11321147
```
11331148

1149+
A querystring parameter that uses JSON for the entire string (not as a single query parameter value):
1150+
1151+
```yaml
1152+
in: querystring
1153+
name: json
1154+
content:
1155+
application/json:
1156+
schema:
1157+
# Allow an arbitrary JSON object to keep
1158+
# the example simple
1159+
type: object
1160+
example: {
1161+
"numbers": [1, 2],
1162+
"flag": null
1163+
}
1164+
```
1165+
1166+
Assuming a path of `/foo`, a server of `https://example.com`, the full URL incorporating the value from the `example` field (with whitespace minimized) would be:
1167+
1168+
```uri
1169+
https://example.com/foo?%7B%22numbers%22%3A%5B1%2C2%5D%2C%22flag%22%3Anull%7D
1170+
```
1171+
1172+
A querystring parameter that uses JSONPath:
1173+
1174+
```yaml
1175+
in: querystring
1176+
name: selector
1177+
content:
1178+
application/jsonpath:
1179+
schema:
1180+
type: string
1181+
example: $.a.b[1:1]
1182+
```
1183+
1184+
As there is not, as of this writing, a [registered](#media-type-registry) mapping between the JSON Schema data model and JSONPath, the details of the string's allowed structure would need to be conveyed either in a human-readable `description` field, or through a mechanism outside of the OpenAPI Description, such as a JSON Schema for the data structure to be queried.
1185+
1186+
Assuming a path of `/foo` and a server of `https://example.com`, the full URL incorporating the value from the `example` field would be:
1187+
1188+
```uri
1189+
https://example.com/foo?%24.a.b%5B1%3A1%5D
1190+
```
1191+
11341192
#### Request Body Object
11351193

11361194
Describes a single request body.

src/schemas/validation/schema.yaml

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ $defs:
339339
in:
340340
enum:
341341
- query
342+
- querystring
342343
- header
343344
- path
344345
- cookie
@@ -364,17 +365,33 @@ $defs:
364365
- schema
365366
- required:
366367
- content
367-
if:
368-
properties:
369-
in:
370-
const: query
371-
required:
372-
- in
373-
then:
374-
properties:
375-
allowEmptyValue:
376-
default: false
377-
type: boolean
368+
allOf:
369+
- if:
370+
properties:
371+
in:
372+
const: query
373+
required:
374+
- in
375+
then:
376+
properties:
377+
allowEmptyValue:
378+
default: false
379+
type: boolean
380+
- if:
381+
properties:
382+
in:
383+
const: querystring
384+
required:
385+
- in
386+
then:
387+
required:
388+
- content
389+
not:
390+
required:
391+
- schema
392+
- style
393+
- explode
394+
- allowReserved
378395
dependentSchemas:
379396
schema:
380397
properties:

0 commit comments

Comments
 (0)