Skip to content

Commit 68b4fa2

Browse files
committed
Appendix on RFC6570-derived behavior
This is the one of several appendixes to be added to clarify the most obscure details of Parameter Object and Encoding Object serialization. This clarifies the correspondence between OAS fields and RFC6570 operators, and acknowledges that some field values and combinations do not have analogues. It provides further guidance for how to use RFC6570 implementations to support these configurations. This includes a SHOULD directive regarding using RFC6570 expansion with the non-RFC6570 styles, as the use of "explode" and "allowReserved" does not otherwise make any sense. It perhaps could be a MUST. Examples are included to show both typical usage, and how to work around the lack of exact RFC6570 equivalences for certain configurations.
1 parent 1bfe6c3 commit 68b4fa2

File tree

1 file changed

+209
-0
lines changed

1 file changed

+209
-0
lines changed

versions/3.0.4.md

+209
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,8 @@ Field Name | Type | Description
10731073
<a name="parameterExample"></a>example | Any | Example of the parameter's potential value. The example SHOULD match the specified schema and encoding properties if present. The `example` field is mutually exclusive of the `examples` field. Furthermore, if referencing a `schema` that contains an example, the `example` value SHALL _override_ the example provided by the schema. To represent examples of media types that cannot naturally be represented in JSON or YAML, a string value can contain the example with escaping where necessary.
10741074
<a name="parameterExamples"></a>examples | Map[ `string`, [Example Object](#exampleObject) \| [Reference Object](#referenceObject)] | Examples of the parameter's potential value. Each example SHOULD contain a value in the correct format as specified in the parameter encoding. The `examples` field is mutually exclusive of the `example` field. Furthermore, if referencing a `schema` that contains an example, the `examples` value SHALL _override_ the example provided by the schema.
10751075

1076+
See also [Appendix C: Using RFC6570 Implementations](#usingRFC6570Implementations) for additional guidance.
1077+
10761078
###### Fixed Fields and considerations for use with `content`
10771079

10781080
For more complex scenarios, the [`content`](#parameterContent) property can define the media type and schema of the parameter, as well as give examples of its use.
@@ -1622,6 +1624,8 @@ Field Name | Type | Description
16221624

16231625
This object MAY be extended with [Specification Extensions](#specificationExtensions).
16241626

1627+
See also [Appendix C: Using RFC6570 Implementations](#usingRFC6570Implementations) for additional guidance.
1628+
16251629
##### Encoding Object Example
16261630

16271631
`multipart/form-data` allows for binary parts:
@@ -3523,3 +3527,208 @@ Version | Date | Notes
35233527
1.2 | 2014-03-14 | Initial release of the formal document.
35243528
1.1 | 2012-08-22 | Release of Swagger 1.1
35253529
1.0 | 2011-08-10 | First release of the Swagger Specification
3530+
3531+
## <a name="usingRFC6570Implementations"></a>Appendix C: Using RFC6570 Implementations
3532+
3533+
Serialization is defined in terms of RFC6570 URI Templates in two scenarios:
3534+
3535+
Object | Condition
3536+
------ | ---------
3537+
[Parameter Object](#parameterObject) | When `schema` is present
3538+
[Encoding Object](#encodingObject) | When encoding for `application/x-www-form-urlencoded` and any of `style`, `explode`, or `allowReserved` are used
3539+
3540+
Implementations of this specification MAY use an implementation of RFC6570 to perform variable expansion, however, some caveats apply.
3541+
3542+
### Equivalences Between Fields and RFC6570 Operators
3543+
3544+
Certain field values translate to RFC6570 operators (or lack thereof):
3545+
3546+
field | value | equivalent
3547+
----- | ----- | ----------
3548+
style | simple | _n/a_
3549+
style | matrix | `;` prefix operator
3550+
style | label | `.` prefix operator
3551+
style | form | `?` prefix operator
3552+
allowReserved | `false` | _n/a_
3553+
allowReserved | `true` | `+` prefix operator
3554+
explode | `false` | _n/a_
3555+
explode | `true` | `*` modifier suffix
3556+
3557+
Multiple `style: form` parameters are equivalent to a single RFC6570 [variable list](https://www.rfc-editor.org/rfc/rfc6570#section-2.2) using the `?` prefix operator:
3558+
3559+
```YAML
3560+
- name: foo
3561+
in: query
3562+
schema:
3563+
type: object
3564+
explode: true
3565+
- name: bar
3566+
in: query
3567+
schema:
3568+
type: string
3569+
```
3570+
3571+
This example is equivalent to RFC6570's `{?foo*,bar}`, and ***NOT*** `{?foo*}{&bar}`, which is problematic because if `foo` is not defined, the result will be an invalid URI.
3572+
The `&` prefix operator has no equivalent in the Parameter Object.
3573+
3574+
### Non-RFC6570 Field Values and Combinations
3575+
3576+
Configurations with no direct RFC6570 equivalent SHOULD also be handled according to RFC6570.
3577+
Implementations MAY create a properly delimited URI Template with variables for individual names and values using RFC6570 regular or reserved expansion (based on `allowReserved`).
3578+
3579+
This includes:
3580+
* the styles `pipeDelimited`, `spaceDelimited`, and `deepObject`, which have no equivalents at all
3581+
* the combination of the style `form` with `allowReserved: true`, which is not allowed because only one prefix operator can be used at a time
3582+
* any parameter name that is not a legal RFC6570 variable name (alphanumerics, `_`, and percent-encoded characters)
3583+
3584+
The Parameter Object's `name` field has a much more permissive syntax than [RFC6570 variable name syntax](https://www.rfc-editor.org/rfc/rfc6570#section-2.3).
3585+
A parameter name that includes characters outside of the allowed RFC6570 variable character set MUST be percent-encoded before it can be used in a URI Template, and MUST set `allowReserved: true` to avoid double percent-encoding.
3586+
3587+
### Examples
3588+
3589+
Let's say we want to use the following data in a form query string, where `formulas` is exploded, and `words` is not:
3590+
3591+
```YAML
3592+
formulas:
3593+
a: x+y
3594+
b: x/y
3595+
c: x^y
3596+
words:
3597+
- math
3598+
- is
3599+
- fun
3600+
```
3601+
3602+
#### RFC6570-Equivalent Expansion
3603+
3604+
This array of parameter objects uses regular `style: form` expansion, fully supported by RFC6570:
3605+
3606+
```YAML
3607+
- name: formulas
3608+
in: query
3609+
schema:
3610+
type: object
3611+
additionalProperties:
3612+
type: string
3613+
explode: true
3614+
- name: words
3615+
in: query
3616+
schema:
3617+
type: array
3618+
items:
3619+
type: string
3620+
```
3621+
3622+
This translates to the following URI Template:
3623+
3624+
```urlencoded
3625+
{?formulas*,words}
3626+
```
3627+
3628+
when expanded with the data given earlier, we get:
3629+
3630+
```urlencoded
3631+
?a=x%2By&b=x%2Fy&c=x%5Ey&words=math,is,fun
3632+
```
3633+
3634+
#### Expansion With Non-RFC6570-Supported Options
3635+
3636+
But now let's say that (for some reason), we really want that `/` in the `b` formula to show up as-is in the query string, and we want our words to be space-separated like in a written phrase.
3637+
To do that, we'll add `allowReserved: true` to `formulas`, and change to `style: spaceDelimited` for `words`:
3638+
3639+
```YAML
3640+
- name: formulas
3641+
in: query
3642+
schema:
3643+
type: object
3644+
additionalProperties
3645+
type: string
3646+
explode: true
3647+
allowReserved: true
3648+
- name: words
3649+
in: query
3650+
style: spaceDelimited
3651+
schema:
3652+
type: array
3653+
items:
3654+
type: string
3655+
```
3656+
3657+
We can't combine the `?` and `+` RFC6570 prefixes, and there's no way with RFC6570 to replace the `,` separator with a space character.
3658+
So we need to restructure the data to fit a manually constructed URI Template that passes all of the pieces through the right sort of expansion.
3659+
3660+
Here is one such template.
3661+
The exact variable names are unimportant, but in this example "f" and "w" are meant to suggest "formulas" and "words", while "n" and "v" suggest "name" and "value":
3662+
3663+
```urlencoded
3664+
?{+fn0}={+fv0}&{+fn1}={+fv1}&{+fn2}={+fv2}&{wn}={wv0} {wv1} {wv2}
3665+
```
3666+
3667+
We'll also need to pre-process the names and values for `formaulas` because while `/` and most other reserved characters are allowed in the query string by RFC3986, `[`, `]`, and `#` [are not](https://datatracker.ietf.org/doc/html/rfc3986#appendix-A), and `&`, `=`, and `+` all have [special behavior](https://www.rfc-editor.org/rfc/rfc1866#section-8.2.1) in the `application/x-www-form-urlencoded` format, which is what we are using in the query string.
3668+
3669+
Setting `allowReserved: true` does _not_ make reserved characters that are not allowed in URIs allowed, it just allows them to be _passed through expansion unchanged._
3670+
Therefore, any tooling still needs to percent-encode those characters because reserved expansion will not do it, but it _will_ leave the percent-encoded triples unchanged.
3671+
See also Appendix D for further guidance on percent-encoding and form media types, including guidance on handling the delimiter characters for `spaceDelimited`, `pipeDelimited`, and `deepObject` in parameter names and values.
3672+
3673+
So here is our data structure that arranges the names and values to suit the template above, where names and values for `formulas` have `[]#&=+` pre-percent encoded (although only `+` appears in this example):
3674+
3675+
```YAML
3676+
fn0: a
3677+
fv0: x%2By
3678+
fn1: b
3679+
fv1: x/y
3680+
fn2: c
3681+
fv2: x^y
3682+
wn: words
3683+
wv0: math
3684+
wv1: is
3685+
wv2: fun
3686+
```
3687+
3688+
Expanding our manually assembled template with our restructured data yields the following query string:
3689+
3690+
```urlencoded
3691+
?a=x%2By&b=x/y&c=x%5Ey&words=math%20is%20fun
3692+
3693+
```
3694+
The `/` and the pre-percent-encoded `%2B` have been left alone, but the disallowed `^` character (inside a value) and space characters (in the template but outside of the expanded variables) were percent-encoded.
3695+
3696+
#### Undefined Values and Manual URI Template Construction
3697+
3698+
Care must be taken when manually constructing templates to handle the values that [RFC6570 considers to be _undefined_](https://datatracker.ietf.org/doc/html/rfc6570#section-2.3) correctly:
3699+
3700+
```YAML
3701+
formulas: {}
3702+
words:
3703+
- hello
3704+
- world
3705+
```
3706+
3707+
Using this data with our original RFC6570-friendly URI Template, `{?formulas*,words}`, produces the following:
3708+
3709+
3710+
```urlencoded
3711+
?words=hello,world
3712+
```
3713+
3714+
This means that the manually constructed URI Template and restructured data need to leave out the `formulas` object entirely so that the `words` parameter is the first and only parameter in the query string.
3715+
3716+
Restructured data:
3717+
3718+
```YAML
3719+
wn: words
3720+
wv0: hello
3721+
wv1: world
3722+
```
3723+
3724+
Manually constructed URI Template:
3725+
3726+
```urlencoded
3727+
?{wn}={wv0} {wv1}
3728+
```
3729+
3730+
Result:
3731+
3732+
```urlencoded
3733+
?words=hello%20world
3734+
```

0 commit comments

Comments
 (0)