From 6aa77bc4912698156467d39d79333e56a82909e3 Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Fri, 6 Jun 2025 13:06:22 -0700 Subject: [PATCH 1/8] Explain Param/Header/Enc example serialization The rules for this have not been clear, and are not always intuitive. This states and explains them directly and ensures that the Style Examples table matches the rules. --- src/oas.md | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/oas.md b/src/oas.md index e91c9cb08a..dedb39b4df 100644 --- a/src/oas.md +++ b/src/oas.md @@ -1026,9 +1026,23 @@ In order to support common ways of serializing simple parameters, a set of `styl See [Appendix E](#appendix-e-percent-encoding-and-form-media-types) for a discussion of percent-encoding, including when delimiters need to be percent-encoded and options for handling collisions with percent-encoded data. +##### Serialization and Examples + +When showing serialized examples, such as with the [Example Object's](#example-object) `serializedValue` or `externalSerializedValue` fields, in most cases the value to show is the value, with all relevant percent-encoding or other encoding/escaping mechanisms, and also including any delimiters produced by the `style` and `explode` configuration. + +For query parameters (`in: "query"` and `in: "querystring"`) and cookies (`in: "cookie"`), the parameter names MUST also be shown, as they are determined in part by `style` and `explode` rather than only by `name`, and the leading `?` or `&` delimiter MUST NOT be shown, as it is not used in all scenarios. + +In particular, these fields are also used in the [Encoding Object](#encoding-object) for `application/x-www-form-urlencoded` request bodies which do not use a leading `?` as that delimiter is part of the URI syntax. +Within URIs, whether each parameter is preceded by the `?` or a `&` is determined by its position relative to other parameters, and may not always be the same for a Parameter Object that is referenced by multiple Operations. +For cookies, neither the `?` nor `&` delimiter is correct (see [Appendix D: Serializing Headers and Cookies](#appendix-d-serializing-headers-and-cookies) for more details). + +Note that RFC6570 form expansion implementations will include either a leading `?` or `&` delimiter, depending on which type of form expansion is used, so in some scenarios it is necessary to strip off or change the leading delimiter. + +The following section illustrates these rules. + ##### Style Examples -Assume a parameter named `color` has one of the following values: +Assume a parameter named `color` has one of the following values, where the value to the right of the `->` is what would be shown in the `dataValue` field of an Example Object: ```js string -> "blue" @@ -1036,13 +1050,12 @@ Assume a parameter named `color` has one of the following values: object -> { "R": 100, "G": 200, "B": 150 } ``` -The following table shows examples, as would be shown with the `example` or `examples` keywords, of the different serializations for each value. +The following table shows serialized examples, as would be shown with the `serializedValue` field of an Example Object, of the different serializations for each value. * The value _empty_ denotes the empty string, and is unrelated to the `allowEmptyValue` field * The behavior of combinations marked _n/a_ is undefined * The `undefined` column replaces the `empty` column in previous versions of this specification in order to better align with [RFC6570](https://www.rfc-editor.org/rfc/rfc6570.html#section-2.3) terminology, which describes certain values including but not limited to `null` as "undefined" values with special handling; notably, the empty string is _not_ undefined -* For `form` and the non-RFC6570 query string styles `spaceDelimited`, `pipeDelimited`, and `deepObject`, each example is shown prefixed with `?` as if it were the only query parameter; see [Appendix C](#appendix-c-using-rfc6570-based-serialization) for more information on constructing query strings from multiple parameters, and [Appendix D](#appendix-d-serializing-headers-and-cookies) for warnings regarding `form` and cookie parameters -* Note that the `?` prefix is not appropriate for serializing `application/x-www-form-urlencoded` HTTP message bodies, and MUST be stripped or (if constructing the string manually) not added when used in that context; see the [Encoding Object](#encoding-object) for more information +* For `form` and the non-RFC6570 query string styles `spaceDelimited`, `pipeDelimited`, and `deepObject`, see [Appendix C](#appendix-c-using-rfc6570-based-serialization) for more information on constructing query strings from multiple parameters, and [Appendix D](#appendix-d-serializing-headers-and-cookies) for warnings regarding `form` and cookie parameters * The examples are percent-encoded as required by RFC6570 and RFC3986; see [Appendix E](#appendix-e-percent-encoding-and-form-media-types) for a thorough discussion of percent-encoding concerns, including why unencoded `|` (`%7C`), `[` (`%5B`), and `]` (`%5D`) seem to work in some environments despite not being compliant. | [`style`](#style-values) | `explode` | `undefined` | `string` | `array` | `object` | @@ -1053,14 +1066,14 @@ The following table shows examples, as would be shown with the `example` or `exa | label | true | . | .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 | ?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 | +| 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_ | ?color=blue%7Cblack%7Cbrown | ?color=R%7C100%7CG%7C200%7CB%7C150 | +| 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 | false | _n/a_ | _n/a_ | _n/a_ | _n/a_ | -| deepObject | true | _n/a_ | _n/a_ | _n/a_ | ?color%5BR%5D=100&color%5BG%5D=200&color%5BB%5D=150 | +| deepObject | true | _n/a_ | _n/a_ | _n/a_ | color%5BR%5D=100&color%5BG%5D=200&color%5BB%5D=150 | ##### Extending Support for Querystring Formats From 3383d8d75c266861b59146cfb7e65106178da75c Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Mon, 9 Jun 2025 10:54:37 -0700 Subject: [PATCH 2/8] Parameter Object example updates --- src/oas.md | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/src/oas.md b/src/oas.md index dedb39b4df..7bb3986005 100644 --- a/src/oas.md +++ b/src/oas.md @@ -1100,6 +1100,10 @@ schema: type: integer format: int64 style: simple +examples: + number: + dataValue: [12345678, 90099] + serializedValue: "12345678,90099" ``` A path parameter of a string value: @@ -1111,6 +1115,13 @@ description: username to fetch required: true schema: type: string +examples: + "Edsger Dijkstra": + dataValue: edijkstra + serializedValue: edijkstra + Diṅnāga: + dataValue: diṅnāga + serializedValue: di%E1%B9%85n%C4%81ga ``` An optional query parameter of a string value, allowing multiple values by repeating the query parameter: @@ -1126,9 +1137,13 @@ schema: type: string style: form explode: true +examples: + stuff: + dataValue: [this, that, theother] + serializedValue: id=this&id=that&id=theother ``` -A free-form query parameter, allowing undefined parameters of a specific type: +A free-form query parameter, allowing undefined parameters of a `type: "string"`: ```yaml in: query @@ -1136,8 +1151,12 @@ name: freeForm schema: type: object additionalProperties: - type: integer + type: string style: form +examples: + freeForm: + dataValue: {"yeah": "I'm", "free": "forming"} + serializedValue: yeah=I%27m&free=forming ``` A complex parameter using `content` to define serialization: @@ -1170,13 +1189,17 @@ content: # Allow an arbitrary JSON object to keep # the example simple type: object - example: { - "numbers": [1, 2], - "flag": null - } + examples: + minimized: + summary: JSON should be serialized with minimal whitespace + dataValue: { + "numbers": [1, 2], + "flag": null + } + serializedValue: '{"numbers":[1,2],"flag":null}' ``` -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: +Assuming a path of `/foo`, a server of `https://example.com`, the full URL incorporating the value from the `serializedValue` field would be: ```uri https://example.com/foo?%7B%22numbers%22%3A%5B1%2C2%5D%2C%22flag%22%3Anull%7D @@ -1191,12 +1214,14 @@ content: application/jsonpath: schema: type: string - example: $.a.b[1:1] + examples: + simpleSelector: + dataValue: $.a.b[1:1] ``` 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. -Assuming a path of `/foo` and a server of `https://example.com`, the full URL incorporating the value from the `example` field would be: +Assuming a path of `/foo` and a server of `https://example.com`, the full URL incorporating the value from the `dataValue` field would be: ```uri https://example.com/foo?%24.a.b%5B1%3A1%5D From 63423e73d7f6adf4713dee06bf990bfa9a89ba9c Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Mon, 9 Jun 2025 11:00:34 -0700 Subject: [PATCH 3/8] Header Object example updates --- src/oas.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/oas.md b/src/oas.md index 7bb3986005..6908919ae4 100644 --- a/src/oas.md +++ b/src/oas.md @@ -2498,6 +2498,10 @@ X-Rate-Limit-Limit: description: The number of allowed requests in the current period schema: type: integer + examples: + OneHundred: + dataValue: 100 + serializedValue: "100" ``` Requiring that a strong `ETag` header (with a value starting with `"` rather than `W/`) is present. Note the use of `content`, because using `schema` and `style` would require the `"` to be percent-encoded as `%22`: From 233424885448bbb495d5fe9355d5499d6a60ec8e Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Tue, 10 Jun 2025 11:49:19 -0700 Subject: [PATCH 4/8] Add a more complex header example --- src/oas.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/oas.md b/src/oas.md index 6908919ae4..5f616bdbdb 100644 --- a/src/oas.md +++ b/src/oas.md @@ -2489,7 +2489,7 @@ Using `content` with a `text/plain` media type is RECOMMENDED for headers where | ---- | :----: | ---- | | 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. | -##### Header Object Example +##### Header Object Examples A simple header of type `integer`: @@ -2516,6 +2516,38 @@ ETag: pattern: ^" ``` +A `Link` header that, if present, must include links with the standard relation types `self`, `first`, `prev`, `next`, and `last`, as might be used on a paginated collection: + +```yaml +Link: + schema: + type: array + uniqueItems: true + minItems: 5 + maxItems: 5 + items: + type: string + anyOf: + - pattern: rel="?first"? + - pattern: rel="?prev"? + - pattern: rel="?self"? + - pattern: rel="?next"? + - pattern: rel="?last"? + style: simple + examples: + CollectionLinks: + dataValue: + - https://example.com/foos?page=1; rel=first + - https://example.com/foos?page=4; rel=prev + - https://example.com/foos?page=5; rel=self + - https://example.com/foos?page=6; rel=next + - https://example.com/foos?page=10; rel=last + serializedValue: https://example.com/foos?page=1; rel=first, https://example.com/foos?page=4; rel=prev, https://example.com/foos?page=5; rel=self, https://example.com/foos?page=6; rel=next, https://example.com/foos?page=10; rel=last +``` + +Note that the `items`, `uniqueItems: true`, and `anyOf` combination allows the links to appear in any order. +If a fixed order is desired, then `prefixItems` could be used and `uniqueItems` would not be necessary. + #### Tag Object Adds metadata to a single tag that is used by the [Operation Object](#operation-object). From 23fc4bed07f5760089a8763d1d887e619c4913ad Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Tue, 10 Jun 2025 12:04:55 -0700 Subject: [PATCH 5/8] Link example needs allowReserved: true --- src/oas.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/oas.md b/src/oas.md index 5f616bdbdb..a33842f641 100644 --- a/src/oas.md +++ b/src/oas.md @@ -2534,6 +2534,10 @@ Link: - pattern: rel="?next"? - pattern: rel="?last"? style: simple + # The ";" character and the URI delimiters are reserved + # but needs to be allowed as headers do not expect these + # to be percent-encoded. + allowReserved: true examples: CollectionLinks: dataValue: From fda8288e1723de0aea033b92d539d23bf917b8aa Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Mon, 9 Jun 2025 11:00:04 -0700 Subject: [PATCH 6/8] Response Object example updates These updates are about header usage in the Response Object. --- src/oas.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/oas.md b/src/oas.md index a33842f641..7fa7940020 100644 --- a/src/oas.md +++ b/src/oas.md @@ -2010,14 +2010,26 @@ headers: description: The number of allowed requests in the current period schema: type: integer + examples: + allowTen: + dataValue: 10 + serializedValue: '10' X-Rate-Limit-Remaining: description: The number of remaining requests in the current period schema: type: integer + examples: + twoRemaining: + dataValue: 2 + serializedValue: '2' X-Rate-Limit-Reset: description: The number of seconds left in the current period schema: type: integer + examples: + oneMinute: + dataValue: 60 + serializedValue: '60' ``` Response with no return value: From 4abf2539cf003c8c6020df3ea84a9e0866ecacd1 Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Tue, 10 Jun 2025 23:49:20 -0700 Subject: [PATCH 7/8] Better implementation of Link Actually ensure each pattern is matched - in the previous way the example was written, the uniqueItems was not sufficient as a link with the same rel but different URI would have satisfied the conditions. Also, the text says "includes" these rels, so there could be more entries. --- src/oas.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/oas.md b/src/oas.md index 7fa7940020..5784e8e75f 100644 --- a/src/oas.md +++ b/src/oas.md @@ -2534,17 +2534,19 @@ A `Link` header that, if present, must include links with the standard relation Link: schema: type: array - uniqueItems: true - minItems: 5 - maxItems: 5 items: type: string - anyOf: - - pattern: rel="?first"? - - pattern: rel="?prev"? - - pattern: rel="?self"? - - pattern: rel="?next"? - - pattern: rel="?last"? + allOf: + - contains: + pattern: rel="?first"? + - contains: + pattern: rel="?prev"? + - contains: + pattern: rel="?self"? + - contains: + pattern: rel="?next"? + - contains: + pattern: rel="?last"? style: simple # The ";" character and the URI delimiters are reserved # but needs to be allowed as headers do not expect these @@ -2561,8 +2563,8 @@ Link: serializedValue: https://example.com/foos?page=1; rel=first, https://example.com/foos?page=4; rel=prev, https://example.com/foos?page=5; rel=self, https://example.com/foos?page=6; rel=next, https://example.com/foos?page=10; rel=last ``` -Note that the `items`, `uniqueItems: true`, and `anyOf` combination allows the links to appear in any order. -If a fixed order is desired, then `prefixItems` could be used and `uniqueItems` would not be necessary. +Note that the `allOf` with `contains` combination allows the links to appear in any order. +If a fixed order is desired, then `prefixItems` could be used and the `allof` would not be necessary. #### Tag Object From da7b2fa568358035003f75afe34147d1d2d352ce Mon Sep 17 00:00:00 2001 From: "Henry H. Andrews" Date: Mon, 23 Jun 2025 12:21:09 -0700 Subject: [PATCH 8/8] Remove likely obsolete examples, improve other The `Link` header is now addressed in another PR. Make the first example a real header instead of an `X-`. Also provide a link to the Header Object for special cases that will be documented there in other PRs. --- src/oas.md | 46 ++++++---------------------------------------- 1 file changed, 6 insertions(+), 40 deletions(-) diff --git a/src/oas.md b/src/oas.md index 5784e8e75f..185d81ea88 100644 --- a/src/oas.md +++ b/src/oas.md @@ -1038,6 +1038,8 @@ For cookies, neither the `?` nor `&` delimiter is correct (see [Appendix D: Seri Note that RFC6570 form expansion implementations will include either a leading `?` or `&` delimiter, depending on which type of form expansion is used, so in some scenarios it is necessary to strip off or change the leading delimiter. +See the [Header Object](#header-object) for special rules for showing examples of the `Set-Cookie` response header, which violates the normal rules for multiple header values. + The following section illustrates these rules. ##### Style Examples @@ -2506,8 +2508,10 @@ Using `content` with a `text/plain` media type is RECOMMENDED for headers where A simple header of type `integer`: ```yaml -X-Rate-Limit-Limit: - description: The number of allowed requests in the current period +Retry-After: + description: | + The number of seconds to wait before retrying the operation. + This Header Object does not allow the HTTP date format syntax. schema: type: integer examples: @@ -2528,44 +2532,6 @@ ETag: pattern: ^" ``` -A `Link` header that, if present, must include links with the standard relation types `self`, `first`, `prev`, `next`, and `last`, as might be used on a paginated collection: - -```yaml -Link: - schema: - type: array - items: - type: string - allOf: - - contains: - pattern: rel="?first"? - - contains: - pattern: rel="?prev"? - - contains: - pattern: rel="?self"? - - contains: - pattern: rel="?next"? - - contains: - pattern: rel="?last"? - style: simple - # The ";" character and the URI delimiters are reserved - # but needs to be allowed as headers do not expect these - # to be percent-encoded. - allowReserved: true - examples: - CollectionLinks: - dataValue: - - https://example.com/foos?page=1; rel=first - - https://example.com/foos?page=4; rel=prev - - https://example.com/foos?page=5; rel=self - - https://example.com/foos?page=6; rel=next - - https://example.com/foos?page=10; rel=last - serializedValue: https://example.com/foos?page=1; rel=first, https://example.com/foos?page=4; rel=prev, https://example.com/foos?page=5; rel=self, https://example.com/foos?page=6; rel=next, https://example.com/foos?page=10; rel=last -``` - -Note that the `allOf` with `contains` combination allows the links to appear in any order. -If a fixed order is desired, then `prefixItems` could be used and the `allof` would not be necessary. - #### Tag Object Adds metadata to a single tag that is used by the [Operation Object](#operation-object).