-
Notifications
You must be signed in to change notification settings - Fork 9.1k
Add $self
for self-identifying documents
#4389
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
Changes from 11 commits
6e129a2
604789f
5e3c600
f469211
43cb464
1294a86
2e5bfbc
e0a2cb6
d68683c
7568b58
34fb6d6
8d1c6be
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -308,21 +308,104 @@ Note that some URI fields are named `url` for historical reasons, but the descri | |
|
||
Unless specified otherwise, all fields that are URIs MAY be relative references as defined by [RFC3986](https://tools.ietf.org/html/rfc3986#section-4.2). | ||
|
||
Relative references in [Schema Objects](#schema-object), including any that appear as `$id` values, use the nearest parent `$id` as a Base URI, as described by [JSON Schema Specification Draft 2020-12](https://www.ietf.org/archive/id/draft-bhutton-json-schema-01.html#section-8.2). | ||
#### Establishing the Base URI | ||
|
||
Relative URI references in other Objects, and in Schema Objects where no parent schema contains an `$id`, MUST be resolved using the referring document's base URI, which is determined in accordance with [[RFC3986]] [Section 5.1.2 – 5.1.4](https://tools.ietf.org/html/rfc3986#section-5.1.2). | ||
In practice, this is usually the retrieval URI of the document, which MAY be determined based on either its current actual location or a user-supplied expected location. | ||
Relative URI references are resolved using the appropriate base URI, which MUST be determined in accordance with [[RFC3986]] [Section 5.1.1 – 5.1.4](https://tools.ietf.org/html/rfc3986#section-5.1.1). | ||
RFC3986 Section 5.1.1 requires determining the base URI from within a resource's contents, which for the OAS means the `$self` field of the [OpenAPI Object](#openapi-object) for an [OpenAPI Document](#openapi-document), or the `$id` JSON Schema keyword in [Schema Objects](#schema-object). | ||
Within an OpenAPI Document, a Schema Object that does not have its base URI set by `$id` takes its base URI from the OpenAPI Object's `$self` field the same as any other Object, treating the OpenAPI Document as the "encapsulating entity" in accordance with RFC3986 Section 5.1.2. | ||
See [JSON Schema draft 2020-12 Section 8.2](https://www.ietf.org/archive/id/draft-bhutton-json-schema-01.html#section-8.2) for more information about base URIs in Schema Objects. | ||
|
||
The most common base URI source in the absence of `$self` or `$id` is the retrieval URI, in accordance with RFC3986 Section 5.1.3. | ||
|
||
Note that these rules mean that different fields in the document, particularly those in Schema Objects vs other kinds of Objects, can have different base URIs. | ||
Relative URI references in `$self` or `$id` are resolved against the base URI appropriate for their location in the document. | ||
|
||
Implementations SHOULD allow users to provide the intended retrieval URI along with each document, as this is necessary in situations including: | ||
|
||
* Implementations that do not support direct retrieval, which requires additional dependencies and security considerations | ||
* Network configurations or conditions that prevent direct retrieval | ||
* Test configurations that need to simulate the document being hosted in a production location | ||
* Documents that exist only in-memory and have no readily identifiable location (although for a single document without references to other documents, an application-specific default base URI in accordance with RFC3986 Section 5.1.4 would also be suitable) | ||
|
||
Base URIs for documents containing OpenAPI content without an OpenAPI Object at the root ignore the `$self` rule, as no `$self` can be present in such documents. | ||
|
||
##### Examples of Base URI Determination and Reference Resolution | ||
|
||
Given a retrieval URI of `https://example.com/foo/bar/openapi.yaml`, and the following OpenAPI Document: | ||
|
||
```YAML | ||
openapi: 3.2.0 | ||
$self: /openapi | ||
info: | ||
title: Example API | ||
version: 1.0 | ||
handrews marked this conversation as resolved.
Show resolved
Hide resolved
|
||
components: | ||
pathItems: | ||
Foo: | ||
$ref: "./shared#/components/pathItems/Foo" | ||
``` | ||
|
||
1. The base URI used to resolve `$self` is the retrieval URI, resulting in an effective `$self` value of `https://example.com/openapi` (OADs that use HTTP content negotiation to provide both JSON and YAML representations typically do not use a file extension in their self-assigned URI, to avoid needing to change URIs based on the format). | ||
2. The base URI for the `$ref` comes from `$self` (`https://example.com/openapi`), producing a resolved URI of `https://example.com/shared#/components/pathItems/Foo`. | ||
|
||
Relative `$self` values are often used for APIs deployed in multiple locations, such as a device management API that is hosted on each device. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm going to reveal my ignorance here, but this seems like the exact situation where you want to use absolute $self value. I thought the idea of distinguishing URIs -- identifiers -- from URLs -- locators -- is that you could have the same document in multiple locations and would want to make clear that it is the same document -- with a single identifier -- even though it could be retrieved from multiple locations. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mikekistler I just did I do not have a use case where you would want the identity to change based on the location, although I'm sure I could construct one where it's somehow beneficial. But maybe not so beneficial as to be worth discarding the simplicity of requiring an absolute URI. Notably, the newly proposed JSON Schema replacement JSON Structure requires an absolute There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have filed issue #4548 to debate the absolute-URI idea, along with several other spin-off issues previously filed. Although perhaps it is worth taking a step back and looking at all of those "spin-off" issues comprehensively. Honestly I'm not sure where to go with this as people keep having fundamental objections that could substantially change the whole thing, and those aren't good questions to resolve in a PR. Those are discussion or issue questions, really. |
||
|
||
In the next example, the retrieval URI is irrelevant, because `$self` is already a fully resolved URI rather than a relative URI-reference: | ||
|
||
```YAML | ||
openapi: 3.2.0 | ||
$self: https://example.com/openapi | ||
info: | ||
title: Example API | ||
version: 1.0 | ||
components: | ||
schemas: | ||
Foo: | ||
$id: ./schemas/foo | ||
properties: | ||
bar: | ||
$ref: bar | ||
Bar: | ||
$id: ./schemas/bar | ||
``` | ||
|
||
In this example, both Schema Objects use `https://example.com/openapi` as their base URI for resolving their relative `$id` values to `https://example.com/schemas/foo` and `https://example.com/schemas/bar`. The `$ref` under `properties` is resolved against the `$id`-provided base URI `https://example.com/schemas/foo`, producing `https://example.com/schemas/bar`, which is the `$id`-assigned URI of the `Bar` schema component. | ||
|
||
Note that using embedded `$id` keywords would prevent using `$ref: "#/components/schemas/Bar"` in the `properties` keyword's `$ref` because the base URI for such fragments is set by the `$id`. Therefore, a `$ref: "#/components/schemas/Bar"` would resolve to `"https://example.com/schemas/foo#/components/schemas/Bar"`, rather than the presumably-intended location of `"https://example.com/openapi#/components/schemas/Bar"`. | ||
|
||
#### Resolving URI fragments | ||
|
||
If a URI contains a fragment identifier, then the fragment should be resolved per the fragment resolution mechanism of the referenced document. If the representation of the referenced document is JSON or YAML, then the fragment identifier SHOULD be interpreted as a JSON-Pointer as per [RFC6901](https://tools.ietf.org/html/rfc6901). | ||
|
||
#### Relative URI References in CommonMark Fields | ||
|
||
Relative references in CommonMark hyperlinks are resolved in their rendered context, which might differ from the context of the API description. | ||
|
||
### Relative References in API URLs | ||
|
||
API endpoints are by definition accessed as locations, and are described by this specification as **_URLs_**. | ||
|
||
Unless specified otherwise, all fields that are URLs MAY be relative references as defined by [RFC3986](https://tools.ietf.org/html/rfc3986#section-4.2). | ||
Unless specified otherwise, relative references are resolved using the URLs defined in the [Server Object](#server-object) as a Base URL. Note that these themselves MAY be relative to the referring document. | ||
Unless specified otherwise, relative references are resolved using the URLs defined in the [Server Object](#server-object) as a Base URL. Note that these themselves MAY be relative to the referring document (**NOT** the [OpenAPI Object's](#openapi-object) `$self` field). | ||
karenetheridge marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
#### Examples of API Base URL Determination | ||
|
||
Assume a retrieval URL of `https://device1.example.com` for the following OpenAPI Document: | ||
|
||
```YAML | ||
openapi: 3.2.0 | ||
$self: https://apidescriptions.example.com/foo | ||
info: | ||
title: Example API | ||
version: 1.0 | ||
servers: | ||
- url: . | ||
description: The production API on this device | ||
- url: ./test | ||
description: The test API on this device | ||
``` | ||
|
||
For API URLs, the `$self` field, which identifies the OpenAPI Document, is ignored, and the retrieval URL is used instead. This produces a normalized production URL of `https://device1.example.com`, and a normalized test URL of `https://device1.example.com/test`. | ||
handrews marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This may be a nit but here we use "retrieval URL" but above (line 323) we use "retrieval URI". I'm guessing that these are referring to the same thing, and if so I think we should try to use consistent terminology. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah generally a retrieval URI is a URL by definition, but it gets weird when you are passing the retrieval URI explicitly, because in that context it might not be usable as a URL (e.g. you are passing it explicitly so that the tool treats it as if it came from a location that is currently inaccessible due to network conditions or whatever). |
||
|
||
### Schema | ||
|
||
|
@@ -342,6 +425,7 @@ This is the root object of the [OpenAPI Description](#openapi-description). | |
| Field Name | Type | Description | | ||
| ---- | :----: | ---- | | ||
| <a name="oas-version"></a>openapi | `string` | **REQUIRED**. This string MUST be the [version number](#versions) of the OpenAPI Specification that the OpenAPI Document uses. The `openapi` field SHOULD be used by tooling to interpret the OpenAPI Document. This is _not_ related to the API [`info.version`](#info-version) string. | | ||
| <a name="oas-self"></a>$self | `string` | This string MUST be in the form of a URI-reference, MUST NOT be an empty string, and MUST NOT contain a fragment (empty or otherwise). The `$self` field provides the self-assigned URI of this document, which also serves as its base URI in accordance with [[RFC3986]] [Section 5.1.1](https://www.rfc-editor.org/rfc/rfc3986#section-5.1.1). Implementations MUST support identifying the targets of [API description URIs](#relative-references-in-api-description-uris) using the resolved URI defined by this field, as shown under [Examples of Base URI Determination and Reference Resolution](#examples-of-base-uri-determination-and-reference-resolution). | | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be good to explain -- or point to the explanation of -- the expected behavior when this field is not present. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mikekistler if that's covered under "Examples of Base URI Detrermination.." is that sufficient? |
||
| <a name="oas-info"></a>info | [Info Object](#info-object) | **REQUIRED**. Provides metadata about the API. The metadata MAY be used by tooling as required. | | ||
| <a name="oas-json-schema-dialect"></a> jsonSchemaDialect | `string` | The default value for the `$schema` keyword within [Schema Objects](#schema-object) contained within this OAS document. This MUST be in the form of a URI. | | ||
| <a name="oas-servers"></a>servers | [[Server Object](#server-object)] | An array of Server Objects, which provide connectivity information to a target server. If the `servers` field is not provided, or is an empty array, the default value would be a [Server Object](#server-object) with a [url](#server-url) value of `/`. | | ||
|
@@ -475,7 +559,7 @@ An object representing a Server. | |
|
||
| Field Name | Type | Description | | ||
| ---- | :----: | ---- | | ||
| <a name="server-url"></a>url | `string` | **REQUIRED**. A URL to the target host. This URL supports Server Variables and MAY be relative, to indicate that the host location is relative to the location where the document containing the Server Object is being served. Variable substitutions will be made when a variable is named in `{`braces`}`. | | ||
| <a name="server-url"></a>url | `string` | **REQUIRED**. A URL to the target host. This URL supports Server Variables and MAY be relative, to indicate that the host location is relative to the location where the document containing the Server Object is being served. Variable substitutions will be made when a variable is named in `{`braces`}`. Note that the [OpenAPI Object's](#openapi-object) `$self` field is **NOT** used for relative URL reference resolution. | | ||
| <a name="server-description"></a>description | `string` | An optional string describing the host designated by the URL. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. | | ||
| <a name="server-name"></a>name | `string` | An optional unique string to refer to the host designated by the URL. | | ||
| <a name="server-variables"></a>variables | Map[`string`, [Server Variable Object](#server-variable-object)] | A map between a variable name and its value. The value is used for substitution in the server's URL template. | | ||
|
@@ -484,6 +568,8 @@ This object MAY be extended with [Specification Extensions](#specification-exten | |
|
||
##### Server Object Example | ||
|
||
See also [Examples of API Base URL Determination](#examples-of-api-base-url-determination) for examples of resolving relative server URLs. | ||
|
||
A single server would be described as: | ||
|
||
```json | ||
|
Uh oh!
There was an error while loading. Please reload this page.