Skip to content

Commit 7ee1ca2

Browse files
handrewsdarrelmillerMike Kistler
authored
Fix, clarify, and simplify content type schemas (#2351)
* Fix, clarify, and simplify content type schemas This fixes #2349, which caught that an encoded PNG image is encoded into a text media type. In the process I realized some other errors, and simplified things. * HTTP `Content-Type` is always handled by OAS * Media Type Object key in most cases * Encoding object (possibly inferred from schema) in `multipart/form-data` * HTTP-level `Content-Encoding` is always handled by the OAS Header Object * JSON Schema "content*" is used for embedding one media type into another * the encoded resource is of media type `text/plain` * `"contentMediaType"` is the embedded media type after decoding * `"contentEncoding"` is how to encode/decode binary to/from text This removes any chance of `"contentMediaType"` conflicting with the Media Type Object key or with `contentType` in the Encoding Object, as they now always do different things. Likewise, the HTTP `Content-Encoding` header (with values like gzip, deflate, etc.) does different things than `"contentEncoding"` (which has values like base64, base64url, quoted-printable, etc.). The deprecated part header `Content-Transfer-Encoding` is likewise handled in the Encoding Object, but is probably never used. * Fix Content-Type to indicate semantics ...rather than literal content format on the wire. * Update 3.1.0.md Fixed a typo and changed a SHOULD to MAY. * Update versions/3.1.0.md * clarify default encoding content type value. * Describe interaction between JSON Schema contentEncoding and HTTP Content-Encoding header Co-authored-by: Mike Kistler <[email protected]> Co-authored-by: Darrel <[email protected]> Co-authored-by: Mike Kistler <[email protected]>
1 parent 5c8a0b6 commit 7ee1ca2

File tree

1 file changed

+20
-16
lines changed

1 file changed

+20
-16
lines changed

versions/3.1.0.md

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,14 +1446,15 @@ application/json:
14461446

14471447
##### Considerations for File Uploads
14481448

1449-
In contrast with the 2.0 specification, `file` input/output content in OpenAPI is described with the same semantics as any other schema type. In contrast with the 3.0 specification, such schemas use the `contentEncoding` JSON Schema keyword rather than the `format` keyword. This keyword supports all encodings defined in [RFC4648](https://tools.ietf.org/html/rfc4648), including "base64" and "base64url", as well as "quoted-printable" from [RFC2045](https://tools.ietf.org/html/rfc2045#section-6.7).
1449+
In contrast with the 2.0 specification, `file` input/output content in OpenAPI is described with the same semantics as any other schema type.
14501450

1451-
JSON Schema also offers a `contentMediaType` keyword. However, when the media type is already specified by the
1452-
Media Type Object's key, or by the `contentType` field of an [Encoding Object](#encodingObject), the `contentMediaType` keyword SHALL be ignored if present.
1451+
In contrast with the 3.0 specification, the `format` keyword has no effect on the content-encoding of the schema. JSON Schema offers a `contentEncoding` keyword, which may be used to specify the `Content-Encoding` for the schema. The `contentEncoding` keyword supports all encodings defined in [RFC4648](https://tools.ietf.org/html/rfc4648), including "base64" and "base64url", as well as "quoted-printable" from [RFC2045](https://tools.ietf.org/html/rfc2045#section-6.7). The encoding specified by the `contentEncoding` keyword is independent of an encoding specified by the `Content-Type` header in the request or response or metadata of a multipart body -- when both are present, the encoding specified in the `contentEncoding` is applied first and then the encoding specified in the `Content-Type` header.
1452+
1453+
JSON Schema also offers a `contentMediaType` keyword. However, when the media type is already specified by the Media Type Object's key, or by the `contentType` field of an [Encoding Object](#encodingObject), the `contentMediaType` keyword SHALL be ignored if present.
14531454

14541455
Examples:
14551456

1456-
Content transferred in binary (octet-stream) SHOULD omit `schema`, as no JSON Schema type is suitable:
1457+
Content transferred in binary (octet-stream) MAY omit `schema`:
14571458

14581459
```yaml
14591460
# a PNG image as a binary file:
@@ -1474,9 +1475,12 @@ content:
14741475
image/png:
14751476
schema:
14761477
type: string
1478+
contentMediaType: image/png
14771479
contentEncoding: base64
14781480
```
14791481

1482+
Note that the `Content-Type` remains `image/png`, describing the semantics of the payload. The JSON Schema `type` and `contentEncoding` fields explain that the payload is transferred as text. The JSON Schema `contentMediaType` is technically redundant, but can be used by JSON Schema tools that may not be aware of the OpenAPI context.
1483+
14801484
These examples apply to either input payloads of file uploads or response payloads.
14811485

14821486
A `requestBody` for submitting a file in a `POST` operation may look like the following example:
@@ -1509,10 +1513,11 @@ requestBody:
15091513
# The property name 'file' will be used for all files.
15101514
file:
15111515
type: array
1512-
items:
1513-
contentMediaType: application/octet-stream
1516+
items: {}
15141517
```
15151518

1519+
As seen in the section on `multipart/form-data` below, the empty schema for `items` indicates a media type of `application/octet-stream`.
1520+
15161521
##### Support for x-www-form-urlencoded Request Bodies
15171522

15181523
To submit content using form url encoding via [RFC1866](https://tools.ietf.org/html/rfc1866), the following
@@ -1549,9 +1554,8 @@ When passing in `multipart` types, boundaries MAY be used to separate sections o
15491554
* If the property is a primitive, or an array of primitive values, the default Content-Type is `text/plain`
15501555
* If the property is complex, or an array of complex values, the default Content-Type is `application/json`
15511556
* If the property is a `type: string` with a `contentEncoding`, the default Content-Type is `application/octet-stream`
1552-
* If the JSON Schema keyword `contentMediaType` is used and no Encoding Object is present, then the Content-Type is that which is specified by `contentMediaType`, however if an Encoding Object is present, then `contentMediaType` SHALL be ignored
15531557

1554-
As with non-multipart request or response bodies, when using `contentMediaType` to specify a binary Content-Type without also using `contentEncoding`, the JSON Schema `type` keyword is omitted.
1558+
Per the JSON Schema specification, `contentMediaType` without `contentEncoding` present is treated as if `contentEncoding: identity` were present. While useful for embedding text documents such as `text/html` into JSON strings, it is not useful for a `multipart/form-data` part, as it just causes the document to be treated as `text/plain` instead of its actual media type. Use the Encoding Object without `contentMediaType` if no `contentEncoding` is required.
15551559

15561560
Examples:
15571561

@@ -1570,15 +1574,17 @@ requestBody:
15701574
type: object
15711575
properties: {}
15721576
profileImage:
1573-
# Content-Type with contentMediaType is the contentMediaType (image/png here)
1577+
# Content-Type for application-level encoded resource is `text/plain`
1578+
type: string
15741579
contentMediaType: image/png
1580+
contentEncoding: base64
15751581
children:
1576-
# default Content-Type for arrays is based on the `inner` type (text/plain here)
1582+
# default Content-Type for arrays is based on the _inner_ type (`text/plain` here)
15771583
type: array
15781584
items:
15791585
type: string
15801586
addresses:
1581-
# default Content-Type for arrays is based on the `inner` type (object shown, so `application/json` in this example)
1587+
# default Content-Type for arrays is based on the _inner_ type (object shown, so `application/json` in this example)
15821588
type: array
15831589
items:
15841590
type: object
@@ -1594,7 +1600,7 @@ A single encoding definition applied to a single schema property.
15941600
##### Fixed Fields
15951601
Field Name | Type | Description
15961602
---|:---:|---
1597-
<a name="encodingContentType"></a>contentType | `string` | The Content-Type for encoding a specific property. Default value depends on the property type: when `type` is absent and `contentMediaType` is present - the value of `contentMediaType`; when both `type` and `contentMediaType` are absent - `application/octet-stream`; for `string` with a `contentEncoding` - `application/octet-string`; for other primitive types – `text/plain`; for `object` - `application/json`; for `array` – the default is defined based on the inner type. The value can be a specific media type (e.g. `application/json`), a wildcard media type (e.g. `image/*`), or a comma-separated list of the two types.
1603+
<a name="encodingContentType"></a>contentType | `string` | The Content-Type for encoding a specific property. Default value depends on the property type: for `object` - `application/json`; for `array` – the default is defined based on the inner type; for all other cases the default is `application/octet-stream`. The value can be a specific media type (e.g. `application/json`), a wildcard media type (e.g. `image/*`), or a comma-separated list of the two types.
15981604
<a name="encodingHeaders"></a>headers | Map[`string`, [Header Object](#headerObject) \| [Reference Object](#referenceObject)] | A map allowing additional information to be provided as headers, for example `Content-Disposition`. `Content-Type` is described separately and SHALL be ignored in this section. This property SHALL be ignored if the request body media type is not a `multipart`.
15991605
<a name="encodingStyle"></a>style | `string` | Describes how a specific property value will be serialized depending on its type. See [Parameter Object](#parameterObject) for details on the [`style`](#parameterStyle) property. The behavior follows the same values as `query` parameters, including default values. This property SHALL be ignored if the request body media type is not `application/x-www-form-urlencoded` or `multipart/form-data`. If a value is explicitly defined, then the value of [`contentType`](#encodingContentType) (implicit or explicit) SHALL be ignored.
16001606
<a name="encodingExplode"></a>explode | `boolean` | When this is true, property 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 properties this property has no effect. When [`style`](#encodingStyle) is `form`, the default value is `true`. For all other styles, the default value is `false`. This property SHALL be ignored if the request body media type is not `application/x-www-form-urlencoded` or `multipart/form-data`. If a value is explicitly defined, then the value of [`contentType`](#encodingContentType) (implicit or explicit) SHALL be ignored.
@@ -1607,7 +1613,7 @@ This object MAY be extended with [Specification Extensions](#specificationExtens
16071613
```yaml
16081614
requestBody:
16091615
content:
1610-
multipart/mixed:
1616+
multipart/form-data:
16111617
schema:
16121618
type: object
16131619
properties:
@@ -1624,9 +1630,7 @@ requestBody:
16241630
description: metadata in XML format
16251631
type: object
16261632
properties: {}
1627-
profileImage:
1628-
type: string
1629-
contentMediaType: image/jpeg
1633+
profileImage: {}
16301634
encoding:
16311635
historyMetadata:
16321636
# require XML Content-Type in utf-8 encoding

0 commit comments

Comments
 (0)