Refactoring variable substitution into runtime expression
MODIFY
versions/3.0.md
versions/3.0.md
@@ -1808,7 +1808,7 @@ This object can be extended with [Specification Extensions](#specificationExtens
The key used to identify the [Path Item Object](#pathItemObject) is a variable expression that can be evaluated in the context of a runtime HTTP request/response to identify the URL to be used for the callback request.
A simple example might be `$request.body#/url`.
-However, using [variable substitution](#variableSubstitution) syntax the complete HTTP message can be accessed.
+However, using a [variable substitution](#runtimeExpression) syntax the complete HTTP message can be accessed.
This includes accessing any part of a body that can be accessed using a JSON Pointer [RFC6901](https://tools.ietf.org/html/rfc6901).
For example, given the following HTTP request:
@@ -1830,7 +1830,6 @@ Content-Length: 123
201 Created
Location: http://example.org/subscription/1
-
```
Here are the examples of how the various expressions evaluate, assuming a the callback operation has a path parameter named `eventType` and a query parameter named `queryUrl`.
@@ -1849,12 +1848,13 @@ $response.header.Location | http://example.org/subscription/1
##### Callback Object Example
-A callback to the URL specified by the `url` parameter in the request
+A callback to the URL specified by the `url` property in the request body.
```yaml
myWebhook:
'$request.body#/url':
+ 'http://notificationServer.com?transactionId={$request#/body}&email={$request.body#/email}}'
post:
requestBody:
description: Callback payload
@@ -2000,9 +2000,9 @@ schemas:
The links object represents a set of possible design-time links for a response.
The presence of a link does not guarantee the caller's ability to successfully invoke it, rather it provides a known relationship and traversal mechanism between responses and other operations.
-As opposed to _dynamic_ links (links provided **in** the response payload), the OAS linking mechanism does not require that link information be provided in a specific response format at runtime.
+As opposed to _dynamic_ links (i.e. links provided **in** the response payload), the OAS linking mechanism does not require that link information be provided in a specific response format at runtime.
-For computing links, and providing instructions to execute them, [variable substitution](#variableSubstitution) is used for accessing values in a response and using them as values while invoking the linked operation.
+For computing links, and providing instructions to execute them, a [runtime expression](#runtimeExpression) is used for accessing values in a response and using them as parameters while invoking the linked operation.
##### Patterned Fields
Field Pattern | Type | Description
@@ -2019,7 +2019,6 @@ Field Name | Type | Description
<a name="linkOperationRef"></a>operationRef | `string` | a relative or absolute reference to an OAS operation. This field is mutually exclusive with the `operationId` field, and must point to the fragment of a valid OAS definition.
<a name="linkOperationId"></a>operationId | `string` | the name of an _existing_, resolvable OAS operation, as defined with a unique `operationId`. This field is mutually exclusive with the `operationRef` field. Relative `operationRef` values MAY be used to locate an existing [Operation Object](#operationObject) in the OAS.
<a name="linkParameters"></a>parameters | [Link Parameters Object](#linkParametersObject) | an object representing parameters to pass to an operation as specified with `operationId` or identified via `operationRef`.
-<a name="linkHeaders"></a>headers | [Headers Object](#headersObject) | an object representing headers to pass to the linked resource. Where conflicts occur between these headers, and those defined in the related operation, these headers override.
<a name="linkDescription"></a>description | `string` | a description of the link, supports [CommonMark syntax](http://spec.commonmark.org/).
<a name="linkServer"></a>server | [Server Object](#serverObject) | a server object to be used by the target operation.
@@ -2030,88 +2029,6 @@ In the case of an `operationId`, it MUST be unique and resolved in the scope of
Because of the potential for name clashes, consider the `operationRef` syntax as the preferred
method for specifications with external references.
-##### <a name="responsePayload"></a>Response Payload Values
-
-Payload values are only available in parsable response payloads which match the advertised media
-type and for media types that can be referenced using a JSON Pointer fragment Id. In all cases,
-if a value does _not_ exist, the parameter will be considered a `null` value (as opposed to an
-empty value) and _not_ passed as a parameter to the linked resource. In cases where a value is
-required, and a parameter is not supplied, the client MAY choose to not follow the link definition.
-
-##### Example
-
-Response payload:
-```json
-{
- "id": "df71a505-07bc-458a-a5c0-73c0340d1ec7",
- "firstname": "Ash",
- "lastname": "Williams"
-}
-```
-
-Payload Variables:
-```yaml
-id: df71a505-07bc-458a-a5c0-73c0340d1ec7
-firstname: Ash
-lastname: Williams
-missingValue: null
-```
-
-In situations where variables appear in an array, an array of variables will be extracted.
-For example:
-
-```json
-[
- { "color": "red" },
- { "color": "green" },
- { "color": "blue" }
-]
-```
-
-will be extracted as such:
-
-```json
-color: ["red", "green", "blue"]
-```
-
-The variables generated can be used in locations prescribed by the definition.
-
-
-##### <a name="variableSubstitution"></a>Variable Substitution
-In all cases, _variables_ from request and responses may be substituted for link generation.
-The table below provides examples of variable expressions and examples of their use in a value:
-
-Source Location | variable expression | example reference | notes
----|:---|:---|:---
-HTTP Method | `$method` | `/users/{$method}` | The allowable values for the `$method` will be those for the HTTP operation
-Requested content type | `$request.header.accept` | `/users/3?format={$request.header.accept}` |
-Request parameter | `$request.path.id` | `/users/{$request.path.id}` | Request parameters MUST be declared in the `parameters` section for the operation or they cannot be used in substitution. This includes request headers
-Request body | `$request.body` | `/users/{$request.body#/user/uuid}` | For operations which accept payloads, references may be made to portions of the `requestBody` or the entire body itself
-Request URL | `$url` | `/track?url={$url}` |
-Response value | `$response.body` | `{$response.body#/uuid}` | Only the payload in the response can be accessed with the `$response` syntax.
-Response header | `$response.header` | `{$response.header.Server}` | Single header values only are available
-
-From the request, the `parameter`s used in calling the operation are made available through the `$request` syntax.
-For responses, the response payload may be used with the `$response` syntax.
-For both requests and responses, values will be substituted in the link in sections designated with a variable expression, surrounded by curly brackets `{}`.
-
-The variable expression is defined by the following [ABNF](https://tools.ietf.org/html/rfc5234) syntax
-
-```
- expression = ( "$url" | "$method" | "$request." [ source ] | "$response." [ source ])
- source = ( header-reference | query-reference | path-reference | body-reference )
- header-reference = "header." token
- query-reference = "query." name
- path-reference = "path." name
- body-reference = "body#" fragment
- fragment = a JSON Pointer [RFC 6901](https://tools.ietf.org/html/rfc6901)
- name = *( char )
- char = as per RFC [7159](https://tools.ietf.org/html/rfc7159#section-7)
- token = as per RFC [7230](https://tools.ietf.org/html/rfc7230#section-3.2.6)
-```
-
-The `name` identifier is case-sensitive, whereas `token` is not.
-
##### Request Parameter Example
Computing a link from a request operation like this:
@@ -2147,7 +2064,7 @@ Addresses:
operationId: getUserAddress
parameters:
# get the `id` field from the request path parameter named `id`
- userId: '{$request.path.id}'
+ userId: $request.path.id
```
Where the `$request.path.id` is the value passed in the request to `/users/{id}`.
@@ -2155,24 +2072,22 @@ Where the `$request.path.id` is the value passed in the request to `/users/{id}`
##### Response Payload Example
```yaml
-Addresses:
+AddressesLink:
operationId: getUserAddressByUUID
parameters:
# get the `id` field from the request path parameter named `id`
- userUuid: '{$response.body#/uuid}'
+ userUuid: $response.body#/uuid
```
And the array example:
```yaml
-ColorSelection:
+ColorSelectionLink:
operationId: getColorSample
parameters:
- colorName: '{$response.body#/color}'
+ colorName: $response.body#/color
```
-Would produce three links with the `colorName` of `red`, `green`, and `blue`:
-
As with all links, it is at the clients' discretion to follow them, neither
permissions nor the ability to make a successful call to that link is guaranteed
solely by the existence of a relationship.
@@ -2394,7 +2309,9 @@ components:
links:
UserRepositories:
# returns array of '#/components/schemas/repository'
- operationRef: '#paths~12.0~1repositories~1{$response.body#/username}'
+ operationRef: '#paths~12.0~1repositories~1/{username}'
+ parameters:
+ username: $response.body#/username
```
or an absolute `operationRef`:
@@ -2404,14 +2321,15 @@ components:
links:
UserRepositories:
# returns array of '#/components/schemas/repository'
- href: 'https://na2.gigantic-server.com/#/paths/~12.0~1repositories~1{$response.body#/username}'
+ operationRef: 'https://na2.gigantic-server.com/#/paths/~12.0~1repositories~1{username}'
+ parameters:
+ username: $response.body#/username
```
Note that in the use of `operationRef`, the _escaped forward-slash_ is necessary when
using JSON references.
#### <a name="linkParametersObject"></a>Link Parameters Object
-Using the `operationId` to reference an operation in the definition has many benefits, including the ability to define media type options, security requirements, response and error payloads.
Many operations require parameters to be passed, and these MAY be dynamic depending on the response itself.
To specify parameters required by the operation, we can use a **Link Parameters Object**.
@@ -2420,7 +2338,10 @@ This object contains parameter names along with static or dynamic values:
##### Patterned Fields
Field Pattern | Type | Description
---|:---:|---
-<a name="linkParameterName"></a> {name} | Any \| [{expression}](#variableSubstitution) | A constant value or expression to be evaluated and passed to the linked operation.
+<a name="linkParameterName"></a> {name} | Any \| [{runtime expression}](#runtimeExpression) | A constant value or expression to be evaluated and passed to the linked operation.
+
+When a runtime expression evaluates to null, no parameter value is passed to the target operation.
+
```yaml
paths:
@@ -2449,6 +2370,49 @@ components:
In the above, the link for `UserCommitHistory` points to the operation `getUserCommitHistory`, and passes the `username` value from the response payload as well as the static scalar value `0`.
+##### <a name="runtimeExpression"></a>Runtime Expressions
+
+Runtime expressions allow defining values based on information that will only available within the HTTP message in an actual API call. This mechanism is used by [Link Parameters Objects](#linkParmeterObject) and [Callback Objects](#callbackObject).
+
+The runtime expression is defined by the following [ABNF](https://tools.ietf.org/html/rfc5234) syntax
+
+```
+ expression = ( "$url" | "$method" | "$request." [ source ] | "$response." [ source ])
+ source = ( header-reference | query-reference | path-reference | body-reference )
+ header-reference = "header." token
+ query-reference = "query." name
+ path-reference = "path." name
+ body-reference = "body#" fragment
+ fragment = a JSON Pointer [RFC 6901](https://tools.ietf.org/html/rfc6901)
+ name = *( char )
+ char = as per RFC [7159](https://tools.ietf.org/html/rfc7159#section-7)
+ token = as per RFC [7230](https://tools.ietf.org/html/rfc7230#section-3.2.6)
+```
+
+The `name` identifier is case-sensitive, whereas `token` is not.
+
+The table below provides examples of runtime expressions and examples of their use in a value:
+
+##### <a name="runtimeExpressionExamples"></a>Examples
+
+Source Location | example expression | notes
+---|:---|:---|:---
+HTTP Method | `$method` | The allowable values for the `$method` will be those for the HTTP operation
+Requested media type | `$request.header.accept` |
+Request parameter | `$request.path.id` | Request parameters MUST be declared in the `parameters` section for the parent operation or they cannot be evaluated. This includes request headers.
+Request body property | `$request.body#/user/uuid` | For operations which accept payloads, references may be made to portions of the `requestBody` or the entire body itself
+Request URL | `$url` |
+Response value | `$response.body#/status` | Only the payload in the response can be accessed with the `$response` syntax.
+Response header | `$response.header.Server` | Single header values only are available
+
+Runtime expressions preserve the type of the referenced value.
+Expression values can be embeded into string values by surrounding the expression with `{}` curly braces.
+
+`$request.body`and `$response.body`expressions are only available in payloads which that can be accessed using a JSON Pointer.
+If a value does _not_ exist, the result of the expression will be considered a `null` value (as opposed to an empty value).
+
+
+
#### <a name="headerObject"></a>Header Object
The Header Object follows the structure of the [Parameter Object](#parameterObject), with the following changes:

Refactoring variable substitution into runtime expression