From 06ca1cf2b00339eb8aad4b48fd65c32851e0ebdd Mon Sep 17 00:00:00 2001 From: Darrel Date: Fri, 12 May 2017 08:54:13 -0700 Subject: [PATCH 1/9] Refactoring variable substitution into runtime expression --- versions/3.0.md | 162 +++++++++++++++++++----------------------------- 1 file changed, 63 insertions(+), 99 deletions(-) diff --git a/versions/3.0.md b/versions/3.0.md index 264f4da0be..da95a57b6f 100644 --- a/versions/3.0.md +++ b/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 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. 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. parameters | [Link Parameters Object](#linkParametersObject) | an object representing parameters to pass to an operation as specified with `operationId` or identified via `operationRef`. -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. description | `string` | a description of the link, supports [CommonMark syntax](http://spec.commonmark.org/). 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. -##### 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. - - -##### 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. #### 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 ---|:---:|--- - {name} | Any \| [{expression}](#variableSubstitution) | A constant value or expression to be evaluated and passed to the linked operation. + {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`. +##### 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: + +##### 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). + + + #### Header Object The Header Object follows the structure of the [Parameter Object](#parameterObject), with the following changes: From 3105843b8a50d55cfb2bde7969b29d3ae2033531 Mon Sep 17 00:00:00 2001 From: Darrel Date: Fri, 12 May 2017 08:58:05 -0700 Subject: [PATCH 2/9] webhook key with embedded runtime expression --- versions/3.0.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/versions/3.0.md b/versions/3.0.md index da95a57b6f..ad8855a01c 100644 --- a/versions/3.0.md +++ b/versions/3.0.md @@ -1853,8 +1853,7 @@ 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}}' + 'http://notificationServer.com?transactionId={$request.body#/id}&email={$request.body#/email}}': post: requestBody: description: Callback payload From 47a18623a45219db86fd69577ccf282fb1069233 Mon Sep 17 00:00:00 2001 From: Darrel Date: Fri, 12 May 2017 09:47:21 -0700 Subject: [PATCH 3/9] fixed a variable substitution --- versions/3.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions/3.0.md b/versions/3.0.md index ad8855a01c..3296f0e5c7 100644 --- a/versions/3.0.md +++ b/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 a [variable substitution](#runtimeExpression) syntax the complete HTTP message can be accessed. +However, using a [runtime expression](#runtimeExpression) 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: From d69b3b53925cf4437643c7de7f3dcf39f9cec7cf Mon Sep 17 00:00:00 2001 From: Darrel Date: Mon, 5 Jun 2017 23:30:36 -0400 Subject: [PATCH 4/9] Cleaned up link examples --- examples/v3.0/link-example.yaml | 203 +++++++++++++++++++++ versions/3.0.md | 312 ++++---------------------------- 2 files changed, 236 insertions(+), 279 deletions(-) create mode 100644 examples/v3.0/link-example.yaml diff --git a/examples/v3.0/link-example.yaml b/examples/v3.0/link-example.yaml new file mode 100644 index 0000000000..5837d705ee --- /dev/null +++ b/examples/v3.0/link-example.yaml @@ -0,0 +1,203 @@ +openapi: 3.0.0 +info: + title: Link Example + version: 1.0.0 +paths: + /2.0/users/{username}: + get: + operationId: getUserByName + parameters: + - name: username + in: path + required: true + schema: + type: string + responses: + '200': + description: The User + content: + application/json: + schema: + $ref: '#/components/schemas/user' + links: + userRepositories: + $ref: '#/components/links/UserRepositories' + /2.0/repositories/{username}: + get: + operationId: getRepositoriesByOwner + parameters: + - name: username + in: path + required: true + schema: + type: string + responses: + '200': + description: repositories owned by the supplied user + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/repository' + links: + userRepository: + $ref: '#/components/links/UserRepository' + /2.0/repositories/{username}/{slug}: + get: + operationId: getRepository + parameters: + - name: username + in: path + required: true + schema: + type: string + - name: slug + in: path + required: true + schema: + type: string + responses: + '200': + description: The repository + content: + application/json: + schema: + $ref: '#/components/schemas/repository' + links: + repositoryPullRequests: + $ref: '#/components/links/RepositoryPullRequests' + /2.0/repositories/{username}/{slug}/pullrequests: + get: + operationId: getPullRequestsByRepository + parameters: + - name: username + in: path + required: true + schema: + type: string + - name: slug + in: path + required: true + schema: + type: string + - name: state + in: query + schema: + type: string + enum: + - open + - merged + - declined + responses: + '200': + description: an array of pull request objects + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/pullrequest' + /2.0/repositories/{username}/{slug}/pullrequests/{pid}: + get: + operationId: getPullRequestsById + parameters: + - name: username + in: path + required: true + schema: + type: string + - name: slug + in: path + required: true + schema: + type: string + - name: pid + in: path + required: true + schema: + type: string + responses: + '200': + description: a pull request object + content: + application/json: + schema: + $ref: '#/components/schemas/pullrequest' + links: + pullRequestMerge: + $ref: '#/components/links/PullRequestMerge' + /2.0/repositories/{username}/{slug}/pullrequests/{pid}/merge: + post: + operationId: mergePullRequest + parameters: + - name: username + in: path + required: true + schema: + type: string + - name: slug + in: path + required: true + schema: + type: string + - name: pid + in: path + required: true + schema: + type: string + responses: + '204': + description: the PR was successfully merged +components: + links: + UserRepositories: + # returns array of '#/components/schemas/repository' + operationId: getRepositoriesByOwner + parameters: + username: $response.body#/username + UserRepository: + # returns '#/components/schemas/repository' + operationId: getRepository + parameters: + username: $response.body#/owner/username + slug: $response.body#/slug + RepositoryPullRequests: + # returns '#/components/schemas/pullrequest' + operationId: getPullRequestsByRepository + parameters: + username: $response.body#/owner/username + slug: $response.body#/slug + PullRequestMerge: + # executes /2.0/repositories/{username}/{slug}/pullrequests/{pid}/merge + operationId: mergePullRequest + parameters: + username: $response.body#/author/username + slug: $response.body#/repository/slug + pid: $response.body#/id + schemas: + user: + type: object + properties: + username: + type: string + uuid: + type: string + repository: + type: object + properties: + slug: + type: string + owner: + $ref: '#/components/schemas/user' + pullrequest: + type: object + properties: + id: + type: integer + title: + type: string + repository: + $ref: '#/components/schemas/repository' + author: + $ref: '#/components/schemas/user' diff --git a/versions/3.0.md b/versions/3.0.md index 3ac098da79..9676ebad04 100644 --- a/versions/3.0.md +++ b/versions/3.0.md @@ -1892,7 +1892,7 @@ Field Name | Type | Description ---|:---:|--- 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. 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. -parameters | Map[`string` \| Any \| [{expression}](#runtimeExpression) | A map representing parameters to pass to an operation as specified with `operationId` or identified via `operationRef`. The key is the parameter name to be used, whereas the value can be a constant or an expression to be evaluated and passed to the linked operation. +parameters | Map[`string` \| Any \| [{expression}](#runtimeExpression)] | A map representing parameters to pass to an operation as specified with `operationId` or identified via `operationRef`. The key is the parameter name to be used, whereas the value can be a constant or an expression to be evaluated and passed to the linked operation. description | `string` | a description of the link, supports [CommonMark syntax](http://spec.commonmark.org/). server | [Server Object](#serverObject) | a server object to be used by the target operation. @@ -1904,8 +1904,9 @@ Because of the potential for name clashes, consider the `operationRef` syntax as method for specifications with external references. -##### Request Parameter Example -Computing a link from a request operation like this: +##### Examples + +Computing a link from a request operation where the `$request.path.id` is used to pass a request parameter to the linked operation. ```yaml paths: @@ -1928,39 +1929,26 @@ paths: uuid: the unique user id type: string format: uuid + links: + Address: + # the target link operationId + operationId: getUserAddress + parameters: + # get the `id` field from the request path parameter named `id` + userId: $request.path.id ``` -Can be used in a link like this: - -```yaml -Addresses: - # the target link operationId - operationId: getUserAddress - parameters: - # get the `id` field from the request path parameter named `id` - userId: $request.path.id -``` - -Where the `$request.path.id` is the value passed in the request to `/users/{id}`. When a runtime expression evaluates to null, no parameter value is passed to the target operation. -##### Response Payload Example - -```yaml -AddressesLink: - operationId: getUserAddressByUUID - parameters: - # get the `id` field from the request path parameter named `id` - userUuid: $response.body#/uuid -``` - -And the array example: +Values from the response body can be used to drive a linked operation. ```yaml -ColorSelectionLink: - operationId: getColorSample - parameters: - colorName: $response.body#/color +links: + addressesLink: + operationId: getUserAddressByUUID + parameters: + # get the `id` field from the request path parameter named `id` + userUuid: $response.body#/uuid ``` As with all links, it is at the clients' discretion to follow them, neither @@ -1968,273 +1956,39 @@ permissions nor the ability to make a successful call to that link is guaranteed solely by the existence of a relationship. - -##### Example - -The example below shows how relationships in the BitBucket API can be represented -with the link schema. This example uses `operationId` values to link responses to -possible operations. - -```yaml -paths: - /2.0/users/{username}: - get: - operationId: getUserByName - parameters: - - name: username - in: path - required: true - schema: - type: string - responses: - '200': - description: The User - content: - application/json: - schema: - $ref: '#/components/schemas/user' - links: - userRepositories: - $ref: '#/components/links/UserRepositories' - /2.0/repositories/{username}: - get: - operationId: getRepositoriesByOwner - parameters: - - name: username - in: path - required: true - schema: - type: string - responses: - '200': - description: repositories owned by the supplied user - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/repository' - links: - userRepository: - $ref: '#/components/links/UserRepository' - /2.0/repositories/{username}/{slug}: - get: - operationId: getRepository - parameters: - - name: username - in: path - required: true - schema: - type: string - - name: slug - in: path - required: true - schema: - type: string - responses: - '200': - description: The repository - content: - application/json: - schema: - $ref: '#/components/schemas/repository' - links: - repositoryPullRequests: - $ref: '#/components/links/RepositoryPullRequests' - /2.0/repositories/{username}/{slug}/pullrequests: - get: - operationId: getPullRequestsByRepository - parameters: - - name: username - in: path - required: true - schema: - type: string - - name: slug - in: path - required: true - schema: - type: string - - name: state - in: query - schema: - type: string - enum: - - open - - merged - - declined - responses: - '200': - description: an array of pull request objects - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/pullrequest' - /2.0/repositories/{username}/{slug}/pullrequests/{pid}: - get: - operationId: getPullRequestsById - parameters: - - name: username - in: path - required: true - schema: - type: string - - name: slug - in: path - required: true - schema: - type: string - - name: pid - in: path - required: true - schema: - type: string - responses: - '200': - description: a pull request object - content: - application/json: - schema: - $ref: '#/components/schemas/pullrequest' - links: - pullRequestMerge: - $ref: '#/components/links/PullRequestMerge' - /2.0/repositories/{username}/{slug}/pullrequests/{pid}/merge: - post: - operationId: mergePullRequest - parameters: - - name: username - in: path - required: true - schema: - type: string - - name: slug - in: path - required: true - schema: - type: string - - name: pid - in: path - required: true - schema: - type: string - responses: - '204': - description: the PR was successfully merged -components: - links: - UserRepositories: - # returns array of '#/components/schemas/repository' - operationId: getRepositoriesByOwner - parameters: - username: $response.body#/username - UserRepository: - # returns '#/components/schemas/repository' - operationId: getRepository - parameters: - username: $response.body#/owner/username - slug: $response.body#/slug - RepositoryPullRequests: - # returns '#/components/schemas/pullrequest' - operationId: getPullRequestsByRepository - parameters: - username: $response.body#/owner/username - slug: $response.body#/slug - PullRequestMerge: - # executes /2.0/repositories/{username}/{slug}/pullrequests/{pid}/merge - operationId: mergePullRequest - parameters: - username: $response.body#/author/username - slug: $response.body#/repository/slug - pid: $response.body#/id - schemas: - user: - type: object - properties: - username: - type: string - uuid: - type: string - repository: - type: object - properties: - slug: - type: string - owner: - $ref: '#/components/schemas/user' - pullrequest: - type: object - properties: - id: - type: integer - title: - type: string - repository: - $ref: '#/components/schemas/repository' - author: - $ref: '#/components/schemas/user' -``` +##### OperationRef Examples As references to `operationId` MAY NOT be possible (the `operationId` is an optional value), references MAY also be made through a relative `operationRef`: ```yaml -components: - links: - UserRepositories: - # returns array of '#/components/schemas/repository' - operationRef: '#paths~12.0~1repositories~1/{username}' - parameters: - username: $response.body#/username +links: + UserRepositories: + # returns array of '#/components/schemas/repository' + operationRef: '#paths~12.0~1repositories~1/{username}' + parameters: + username: $response.body#/username ``` or an absolute `operationRef`: ```yaml -components: - links: - UserRepositories: - # returns array of '#/components/schemas/repository' - operationRef: 'https://na2.gigantic-server.com/#/paths/~12.0~1repositories~1{username}' - parameters: - username: $response.body#/username +links: + UserRepositories: + # returns array of '#/components/schemas/repository' + 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. -```yaml -paths: - /user/{username}: # ... - /user/{username}/commits: - get: - operationId: userCommitHistory - parameters: - - name: username - in: path - type: string - required: true - - name: page - type: integer - format: int32 - required: true - responses: { ... } -components: - links: - UserCommitHistory: - operationId: userCommitHistory - parameters: - username: $response.body#/user/username - page: 0 -``` - -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`. ##### 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). +Runtime expressions allow defining values based on information that will only be available within the HTTP message in an actual API call. +This mechanism is used by [Link Objects](#linkObject) and [Callback Objects](#callbackObject). The runtime expression is defined by the following [ABNF](https://tools.ietf.org/html/rfc5234) syntax From ffa2946244676ca61275b0849de5a64c633cd262 Mon Sep 17 00:00:00 2001 From: Darrel Date: Mon, 5 Jun 2017 23:42:33 -0400 Subject: [PATCH 5/9] More example corrections --- versions/3.0.md | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/versions/3.0.md b/versions/3.0.md index 9676ebad04..ca8885927e 100644 --- a/versions/3.0.md +++ b/versions/3.0.md @@ -1915,27 +1915,43 @@ paths: - name: id in: path required: true - description: the user identifier, as userId or username + description: the user identifier, as userId schema: type: string - responses: - '200': - description: the user being returned - content: - application/json: - schema: - type: object - properties: - uuid: the unique user id - type: string - format: uuid + get: + responses: + '200': + description: the user being returned + content: + application/json: + schema: + type: object + properties: + uuid: the unique user id + type: string + format: uuid links: - Address: + address: # the target link operationId operationId: getUserAddress parameters: # get the `id` field from the request path parameter named `id` userId: $request.path.id + # the path item of the linked operation + /users/{userid}/address: + parameters: + - name: userid + in: path + required: true + description: the user identifier, as userId + schema: + type: string + # linked operation + get: + operationId: getUserAddress + responses: + '200': + description: the user's address ``` When a runtime expression evaluates to null, no parameter value is passed to the target operation. @@ -1944,7 +1960,7 @@ Values from the response body can be used to drive a linked operation. ```yaml links: - addressesLink: + address: operationId: getUserAddressByUUID parameters: # get the `id` field from the request path parameter named `id` From 1597a0bb8ee760ff48899e9881f96f74b9a4c1fb Mon Sep 17 00:00:00 2001 From: Darrel Date: Fri, 9 Jun 2017 18:35:27 +0200 Subject: [PATCH 6/9] Fixed variable expression text --- versions/3.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions/3.0.md b/versions/3.0.md index ca8885927e..c38b5b4f26 100644 --- a/versions/3.0.md +++ b/versions/3.0.md @@ -1737,7 +1737,7 @@ This object can be extended with [Specification Extensions](#specificationExtens ##### Key Expression -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. +The key used to identify the [Path Item Object](#pathItemObject) is a [runtime expression](#runtimeExpression) 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 a [runtime expression](#runtimeExpression) 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). From a845c008d5b8d887804115eefb169c31e409c5a5 Mon Sep 17 00:00:00 2001 From: Darrel Date: Thu, 15 Jun 2017 12:06:17 -0400 Subject: [PATCH 7/9] Updates based comments. --- versions/3.0.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/versions/3.0.md b/versions/3.0.md index c38b5b4f26..6c467c84f5 100644 --- a/versions/3.0.md +++ b/versions/3.0.md @@ -1752,7 +1752,7 @@ Content-Length: 123 { "failedUrl" : "http://clientdomain.com/failed" - "successUrls : [ + "successUrls" : [ "http://clientdomain.com/fast", "http://clientdomain.com/medium", "http://clientdomain.com/slow" @@ -1779,12 +1779,12 @@ $response.header.Location | http://example.org/subscription/1 ##### Callback Object Example -A callback to the URL specified by the `url` property in the request body. +A callback to the URL specified by the `id` and `email` property in the request body. ```yaml myWebhook: - 'http://notificationServer.com?transactionId={$request.body#/id}&email={$request.body#/email}}': + 'http://notificationServer.com?transactionId={$request.body#/id}&email={$request.body#/email}': post: requestBody: description: Callback payload @@ -1884,15 +1884,15 @@ The presence of a link does not guarantee the caller's ability to successfully i 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, a [runtime expression](#runtimeExpression) is used for accessing values in a response and using them as parameters while invoking the linked operation. +For computing links, and providing instructions to execute them, a [runtime expression](#runtimeExpression) is used for accessing values in an operation and using them as parameters while invoking the linked operation. ##### Fixed Fields Field Name | Type | Description ---|:---:|--- -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. +operationRef | `string` | a relative or absolute reference to an OAS operation. This field is mutually exclusive with the `operationId` field, and MUST point to an [Operation Object](#operationObject). 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. -parameters | Map[`string` \| Any \| [{expression}](#runtimeExpression)] | A map representing parameters to pass to an operation as specified with `operationId` or identified via `operationRef`. The key is the parameter name to be used, whereas the value can be a constant or an expression to be evaluated and passed to the linked operation. +parameters | Map[`string`, Any \| [{expression}](#runtimeExpression)] | A map representing parameters to pass to an operation as specified with `operationId` or identified via `operationRef`. The key is the parameter name to be used, whereas the value can be a constant or an expression to be evaluated and passed to the linked operation. description | `string` | a description of the link, supports [CommonMark syntax](http://spec.commonmark.org/). server | [Server Object](#serverObject) | a server object to be used by the target operation. From 72d15fd2498f2d935cd9a74afdb6412bf6357c95 Mon Sep 17 00:00:00 2001 From: Darrel Date: Thu, 15 Jun 2017 14:22:07 -0400 Subject: [PATCH 8/9] Updates based on TDC Call --- versions/3.0.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/versions/3.0.md b/versions/3.0.md index 6c467c84f5..ec834c7641 100644 --- a/versions/3.0.md +++ b/versions/3.0.md @@ -1954,7 +1954,7 @@ paths: description: the user's address ``` -When a runtime expression evaluates to null, no parameter value is passed to the target operation. +When a runtime expression fails to evaluate, no parameter value is passed to the target operation. Values from the response body can be used to drive a linked operation. @@ -1981,7 +1981,7 @@ value), references MAY also be made through a relative `operationRef`: links: UserRepositories: # returns array of '#/components/schemas/repository' - operationRef: '#paths~12.0~1repositories~1/{username}' + operationRef: '#/paths~12.0~1repositories~1/{username}/get' parameters: username: $response.body#/username ``` @@ -1992,7 +1992,7 @@ or an absolute `operationRef`: links: UserRepositories: # returns array of '#/components/schemas/repository' - operationRef: 'https://na2.gigantic-server.com/#/paths/~12.0~1repositories~1{username}' + operationRef: 'https://na2.gigantic-server.com/#/paths/~12.0~1repositories~1{username}/get' parameters: username: $response.body#/username ``` @@ -2009,7 +2009,7 @@ This mechanism is used by [Link Objects](#linkObject) and [Callback Objects](#ca The runtime expression is defined by the following [ABNF](https://tools.ietf.org/html/rfc5234) syntax ``` - expression = ( "$url" | "$method" | "$request." [ source ] | "$response." [ source ]) + expression = ( "$url" | "$method" | "$statusCode" | "$request." source | "$response." source ) source = ( header-reference | query-reference | path-reference | body-reference ) header-reference = "header." token query-reference = "query." name @@ -2028,7 +2028,7 @@ The table below provides examples of runtime expressions and examples of their u ##### 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. From 9cf27781fa452ad2d0a4d57e806fd8ecbae529c4 Mon Sep 17 00:00:00 2001 From: Darrel Date: Fri, 16 Jun 2017 11:49:21 -0400 Subject: [PATCH 9/9] Fixed runtime expression in callback example --- examples/v3.0/callback-example.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/v3.0/callback-example.yaml b/examples/v3.0/callback-example.yaml index 426ee39a76..c698b9704c 100644 --- a/examples/v3.0/callback-example.yaml +++ b/examples/v3.0/callback-example.yaml @@ -32,7 +32,7 @@ paths: onData: # when data is sent, it will be sent to the `callbackUrl` provided # when making the subscription PLUS the suffix `/data` - $request.query.callbackUrl/data: + {$request.query.callbackUrl}/data: post: requestBody: description: subscription payload