Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolving implicit connections (3.0.4 port of #3856) #3906

Merged
merged 10 commits into from
Jun 17, 2024
134 changes: 133 additions & 1 deletion versions/3.0.4.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,50 @@ It is RECOMMENDED that the entry OpenAPI document be named: `openapi.json` or `o

When parsing an OAD, JSON or YAML objects are parsed into specific Objects (such as [Operation Objects](#operationObject), [Response Objects](#responseObject), [Reference Objects](#referenceObject), etc.) based on the parsing context. Depending on how references are arranged, a given JSON or YAML object can be parsed in multiple different contexts:

* As a full OpenAPI Description document (an [OpenAPI Object](#oasObject) taking up an entire document)
* As a complete OpenAPI Description document
* As the Object type implied by its parent Object within the document
* As a reference target, with the Object type matching the reference source's context

If the same JSON/YAML object is parsed multiple times and the respective contexts require it to be parsed as _different_ Object types, the resulting behavior is _implementation defined_, and MAY be treated as an error if detected. An example would be referencing an empty Schema Object under `#/components/schemas` where a Path Item Object is expected, as an empty object is valid for both types. For maximum interoperability, it is RECOMMENDED that OpenAPI Description authors avoid such scenarios.

#### <a name="resolvingImplicitConnections"></a>Resolving Implicit Connections

Several features of this specification require resolution of non-URI-based connections to some other part of the OpenAPI Description (OAD).

These connections are unambiguously resolved in single-document OADs, but the resolution process in multi-document OADs is _implementation-defined_, within the constraints described in this section.
In some cases, an unambiguous URI-based alternative is available, and OAD authors are RECOMMENDED to always use the alternative:

Source | Target | Alternative
------ | ------ | -----------
[Security Requirement Object](#securityRequirementObject) `{name}` | [Security Scheme Object](#securitySchemeObject) name under the [Components Object](#componentsObject) | _n/a_
[Discriminator Object](#discriminatorObject) `mapping` _(implicit, or explicit name syntax)_ | [Schema Object](#schemaObject) name under the Components Object | `mapping` _(explicit URI syntax)_
[Operation Object](#operationObject) `tags` | [Tag Object](#tagObject) `name` (in the Components Object) | _n/a_
[Link Object](#linkObject) `operationId` | [Path Item Object](#pathItemObject) `operationId` | `operationRef`

A fifth implicit connection involves appending the templated URL paths of the [Paths Object](#pathsObject) to the appropriate [Server Object](#serverObject)'s `url` field.
This is unambiguous because only the entry document's Paths Object contributes URLs to the described API.

It is RECOMMENDED to consider all Operation Objects from all parsed documents when resolving any Link Object `operationId`.
This requires parsing all referenced documents prior to determining an `operationId` to be unresolvable.

The implicit connections in the Security Requirement Object and Discriminator Object rely on the _component name_, which is the property name holding the component in the appropriately typed sub-object of the Components Object.
For example, the component name of the Schema Object at `#/components/schemas/Foo` is `Foo`.
The implicit connection of `tags` in the Operation Object uses the `name` field of Tag Objects, which (like the Components Object) are found under the root OpenAPI Object.
This means resolving component names and tag names both depend on starting from the correct OpenAPI Object.

For resolving component and tag name connections from a referenced (non-entry) document, it is RECOMMENDED that tools resolve from the entry document, rather than the current document.
This allows Security Scheme Objects and Tag Objects to be defined with the API's deployment information (the top-level Server Objects), and treated as an interface for referenced documents to access.

The interface approach can also work for Discriminator Objects and Schema Objects, but it is also possible to keep the Discriminator Object's behavior within a single document using the relative URI-reference syntax of `mapping`.

There are no URI-based alternatives for the Security Requirement Object or for the Operation Object's `tags` field.
These limitations are expected to be addressed in a future release.

See [Security Requirement in a Referenced Document](#security-requirement-in-a-referenced-document) for an example of the possible resolutions, including which one is recommended by this section.
The behavior for Discrimator Object non-URI mappings and for the Operation Object's `tags` field operate on the same principles.

Note that no aspect of implicit connection resolution changes how [URLs are resolved](#relativeReferences), or restricts their possible targets.
ralfhandl marked this conversation as resolved.
Show resolved Hide resolved

### <a name="dataTypes"></a>Data Types

Primitive data types in the OAS are based on the types supported by the [JSON Schema Specification Wright Draft 00](https://tools.ietf.org/html/draft-wright-json-schema-00#section-4.2).
Expand Down Expand Up @@ -3762,6 +3798,102 @@ security:
- read:pets
```

###### Security Requirement in a Referenced Document

See [Resolving Implicit Connections](#resolvingImplicitConnections) for more information.

First, our entry document is where parsing begins. It defines the `MySecurity` security scheme to be JWT-based, and it defines a Path Item as a reference to a component in another document:

```HTTP
GET /api/description/openapi HTTP/1.1
Host: www.example.com
Accept: application/openapi+json
```

```json
"components": {
"securitySchemes": {
"MySecurity": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
},
"paths": {
"/foo": {
"$ref": "other#/components/pathItems/Foo"
}
}
```

```HTTP
GET /api/description/openapi HTTP/1.1
Host: www.example.com
Accept: application/openapi+yaml
```

```yaml
components:
securitySchemes:
MySecurity:
type: http
scheme: bearer
bearerFormat: JWT
paths:
/foo:
$ref: "other#/components/pathItems/Foo"
```

Next, we have our referenced document, `other`. The fact that we don't use file extensions gives the client the flexibility to choose an acceptable format on a resource-by-resource basis, assuming both representations are available:

```HTTP
GET /api/description/other HTTP/1.1
Host: www.example.com
Accept: application/openapi+json
```

```json
"components": {
"securitySchemes": {
"MySecurity": {
"type": "http",
"scheme": "basic"
}
},
"pathItems": {
"Foo": {
"get": {
"security": [
"MySecurity": []
]
}
}
}
}
```

```HTTP
GET /api/description/other HTTP/1.1
Host: www.example.com
Accept: application/openapi+yaml
```

```yaml
components:
securitySchemes:
MySecurity:
type: http
scheme: basic
pathItems:
Foo:
get:
security:
- MySecurity: []
```

In the `other` document, the referenced path item has a Security Requirement for a Security Scheme, `MySecurity`. The same Security Scheme exists in the original entry document. As outlined in [Resolving Implicit Connections](#resolvingImplicitConnections), `MySecurity` is resolved with an [implementation-defined behavior](#undefinedAndImplementationDefinedBehavior). However, documented in that section, it is RECOMMENDED that tools resolve component names from the [entry document](#documentStructure). As with all implementation-defined behavior, it is important to check tool documentation to determine which behavior is supported.

### <a name="specificationExtensions"></a>Specification Extensions

While the OpenAPI Specification tries to accommodate most use cases, additional data can be added to extend the specification at certain points.
Expand Down