From 75d9908cec9af37536572bd4b1051f1ca153373b Mon Sep 17 00:00:00 2001 From: luckybroman5 Date: Wed, 3 Mar 2021 22:04:34 -0800 Subject: [PATCH 1/7] proposal 5 --- proposals/005_RequestBody-Links.md | 121 +++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 proposals/005_RequestBody-Links.md diff --git a/proposals/005_RequestBody-Links.md b/proposals/005_RequestBody-Links.md new file mode 100644 index 0000000000..433bd86055 --- /dev/null +++ b/proposals/005_RequestBody-Links.md @@ -0,0 +1,121 @@ + +# Feature name + + +## Metadata + +|Tag |Value | +|---- | ---------------- | +|Proposal |[005](https://github.com/luckybroman5/OpenAPI-Specification/tree/master/proposals/005_RequestBody-Links.md)| +|Authors|[@luckybroman5](https://github.com/luckybroman5)| +|Review Manager |TBD | +|Status |Proposal| +|Issues |[1594](https://github.com/OAI/OpenAPI-Specification/issues/1594) [2196](https://github.com/OAI/OpenAPI-Specification/issues/2196) [1593](https://github.com/OAI/OpenAPI-Specification/issues/1593) [2122](https://github.com/OAI/OpenAPI-Specification/issues/1593)| +|Previous Revisions | N/A | + +## Change Log + +|Date |Responsible Party |Description | +|---- | ---------------- | ---------- | +| 2nd March 2021 | Kade Green | Initial Draft | + +## Introduction + +This proposal is to support `Link` objects on `Operation` objects. Simply put, if *Response A* returns a property called *Foo*, and *Foo* is intended to be used in *Request B*'s request body as property *Bar*, one would define a `Link` in *Bar*'s operation to indicate the value of *Bar* is **sourced** from *Foo*. + +## Motivation + +In an ideal world, integration with Web API's could be done entirely automatically. While the current OAS Specification does have *some* support defining dependencies between requests using [links](https://swagger.io/docs/specification/links/), it is currently not possible to define relationships between response data and request data for separate requests. Although in practice many parameters are used this way, perhaps the more prelevant use case is for **refresh tokens**. In most modern authentication mechanisms, a user is allowed the best of both words in terms of security and usability in that they are issued short lived authentication tokens along with longer lived refresh tokens for re-authentication later. All though this relationship is somewhat obvious to a human, there are cases where it might be ambiguous. Further, it's impossible for a generated sdk to account for this connection. By including a way to document these dependencies among data, generated clients could better serve their end users, there would be no ambiguidy for human readers, and would open the door for richer forms of documentation like a dependency graph visualization. + +## Proposed solution + +Allow [Link](https://swagger.io/docs/specification/links/) objects to exist at the root level of an [Operation](https://swagger.io/specification/#operation-object). This would allow for describing from where dependent parameters get their information to make the request. In addition, a new poperty would be added to the `Link` object that would be called `fragments`. This new property would contain [runtime expressions](https://swagger.io/specification/#runtime-expression) that would evaluate which *fragments* to extract data from, and which *fragments* to populate that data with. + +Some Explanations: +1. The request based `Link` object would allow for OpenAPI authors to reference response properties from Specifications they themselves do not own. For Example; A company named Foo handles billing through paypal. This company has a billing API, and updates a plan using the paypal [user_id](https://developer.paypal.com/docs/api/identity/v1/#userinfo-get-response). An author at company Foo could reference Paypal's swagger spec in theirs, opening the door for even richer sdk generation as well as many other possibilities. +2. The `Fragments` property is more discrete than having separate properties to define whether a given response fragment belongs in a subsequent request's header, body, or path. For example: `$response.header.req_id` mapping to `$request.body#requestId` or `$response.header.req_id` mapping to `$request.header.requestId`. +3. It's easier to think about dependencies of requests from within the request itself. + + +## Detailed design + +### Ammendment to `Link` Object + +`Links` can now exist on `Operation` objects + +#### New Fields: + +**Fragments** +Key: `fragments` +type: Array of `Fragment` objects + +**BodyFragment** +|Field Name |Type |Description | +|---- | ---------------- | ---------- | +| src | runtime expression | expresses from where in the source request to apply to `dest` | +| dest | runtime expression | expresses to where the `src` output should be applied | +| required | boolean | if not obtained, the request should fail. Default is false | + +#### Examples: + +``` +'/user/{id}/bestfriend': + ... + get: + description: Gets a user's best friend + operationId: getUserBestFriend + responses: + '200': null + description: pet response + content: + application/json: null + schema: + type: object + properties: + Id: + type: integer + format: int64 + +... + +'/user/{id}/message': + ... + put: + description: send a happy greeting to a friend + operationId: sendMessage + links: # <-- Links can now exist here + arbitraryName: + operationId: getUserBestFriend + fragments: # <-- New Property for links + - src: '$response.body#/id' + dest: '$request.body#/from' + required: true + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + from: + type: string + description: another user's id from where the message originates + message: + type: string + description: the message to send to the user +``` + +## Backwards compatibility + +Since the modifications to existing Objects is purely additive and positional, there shouldn't be any issues with backwards compatibility. Should a `fragments` array be defined within a response's `Links` as the current standard supports, the effect is exactly the same. + +It's acceptable for parameters to be defined in either `fragments` OR `parameters` within the `link` object, and is up to preference of the individual spec's author. Perhaps in later versions of OAS should this proposal become accepted, `parameters` might be deprecated. + +## Alternatives considered + +There are multiple ways to solve this problem that other people have suggested that are in fact extremely valid. This Proposal is trying to make all parties happy by addressing each of the three major points each alternative independently address: + +1 - Allow for OpenAPI authors to reference response properties from Specifications they themselves do not own. aka ["Backlinks"](https://apigraph.readthedocs.io/en/latest/reference/openapi-extensions.html#x-apigraph-backlinks-components) +2 - Set a field in the target operation's request body [Proposal](https://apigraph.readthedocs.io/en/latest/reference/openapi-extensions.html#x-apigraph-requestbodyparameters) + +While this proposal is very similar to the proposal for both 1 & 2, efforts to reach out them have failed, so I have gone forward with my own more condenced and concise version. I do feel that consideration of these alternative solutions is extremely important as the larger issue is support for these points in general. \ No newline at end of file From 962055bf26a1015f08ee320fcc663418a842b571 Mon Sep 17 00:00:00 2001 From: luckybroman5 Date: Wed, 3 Mar 2021 22:15:49 -0800 Subject: [PATCH 2/7] Fixed Typos and Layout --- proposals/005_RequestBody-Links.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/proposals/005_RequestBody-Links.md b/proposals/005_RequestBody-Links.md index 433bd86055..bc81e94bb4 100644 --- a/proposals/005_RequestBody-Links.md +++ b/proposals/005_RequestBody-Links.md @@ -21,15 +21,19 @@ ## Introduction -This proposal is to support `Link` objects on `Operation` objects. Simply put, if *Response A* returns a property called *Foo*, and *Foo* is intended to be used in *Request B*'s request body as property *Bar*, one would define a `Link` in *Bar*'s operation to indicate the value of *Bar* is **sourced** from *Foo*. +This proposal is to support [`Link`]((https://swagger.io/docs/specification/links/)) objects on [`Operation`]((https://swagger.io/specification/#operation-object)) objects. Simply put, if *Response A* returns a property called *Foo*, and *Foo* is intended to be used in *Request B*'s request body as property *Bar*, one would define a `Link` in *Bar*'s operation to indicate the value of *Bar* is **sourced** from *Foo*. ## Motivation -In an ideal world, integration with Web API's could be done entirely automatically. While the current OAS Specification does have *some* support defining dependencies between requests using [links](https://swagger.io/docs/specification/links/), it is currently not possible to define relationships between response data and request data for separate requests. Although in practice many parameters are used this way, perhaps the more prelevant use case is for **refresh tokens**. In most modern authentication mechanisms, a user is allowed the best of both words in terms of security and usability in that they are issued short lived authentication tokens along with longer lived refresh tokens for re-authentication later. All though this relationship is somewhat obvious to a human, there are cases where it might be ambiguous. Further, it's impossible for a generated sdk to account for this connection. By including a way to document these dependencies among data, generated clients could better serve their end users, there would be no ambiguidy for human readers, and would open the door for richer forms of documentation like a dependency graph visualization. +In an ideal world, integration with Web API's could be done entirely automatically. While the current OAS Specification does have *some* support defining dependencies between requests using [links](https://swagger.io/docs/specification/links/), it is currently not possible to define relationships between response data and request data in the body for separate requests. + +Perhaps the more prelevant use case for this is for **refresh tokens**. In most modern authentication mechanisms, a user is allowed the best of both words in terms of security and usability in that they are issued short lived authentication tokens along with longer lived refresh tokens for later. Although this relationship is somewhat obvious to a human, there are cases where it might be ambiguous. Further, it's impossible for a generated sdk to account for this connection. + +By including a way to document these dependencies among data, generated clients could better serve their end users, there would be no ambiguidy for human readers, and would open the door for richer forms of documentation like a dependency graph visualization. ## Proposed solution -Allow [Link](https://swagger.io/docs/specification/links/) objects to exist at the root level of an [Operation](https://swagger.io/specification/#operation-object). This would allow for describing from where dependent parameters get their information to make the request. In addition, a new poperty would be added to the `Link` object that would be called `fragments`. This new property would contain [runtime expressions](https://swagger.io/specification/#runtime-expression) that would evaluate which *fragments* to extract data from, and which *fragments* to populate that data with. +Allow [Links](https://swagger.io/docs/specification/links/) to exist at the root level of an [Operation](https://swagger.io/specification/#operation-object), rather than solely in a [Response](https://swagger.io/specification/#response-object) object. When defined at the `Operation` Level, each link would represent a link to a request from where to source information. The `link.operationId` would reference the "source" request. This would allow for describing from where dependent parameters get their information to make the request. In addition, a new poperty would be added to the `Link` object that would be called `fragments`. This new property would contain [runtime expressions](https://swagger.io/specification/#runtime-expression) that would evaluate which *fragments* to extract data from, and which *fragments* to populate that data with. Some Explanations: 1. The request based `Link` object would allow for OpenAPI authors to reference response properties from Specifications they themselves do not own. For Example; A company named Foo handles billing through paypal. This company has a billing API, and updates a plan using the paypal [user_id](https://developer.paypal.com/docs/api/identity/v1/#userinfo-get-response). An author at company Foo could reference Paypal's swagger spec in theirs, opening the door for even richer sdk generation as well as many other possibilities. From 352764ff2969e3ddf33df4c0b96ee9b988d29173 Mon Sep 17 00:00:00 2001 From: luckybroman5 Date: Wed, 3 Mar 2021 22:18:08 -0800 Subject: [PATCH 3/7] Renamed to Fragment --- proposals/005_RequestBody-Links.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/005_RequestBody-Links.md b/proposals/005_RequestBody-Links.md index bc81e94bb4..38ae0d4ea3 100644 --- a/proposals/005_RequestBody-Links.md +++ b/proposals/005_RequestBody-Links.md @@ -53,7 +53,7 @@ Some Explanations: Key: `fragments` type: Array of `Fragment` objects -**BodyFragment** +**Fragment** |Field Name |Type |Description | |---- | ---------------- | ---------- | | src | runtime expression | expresses from where in the source request to apply to `dest` | From 81b20a0548f3b2d1a79334952d64a69380f51cd8 Mon Sep 17 00:00:00 2001 From: luckybroman5 Date: Wed, 3 Mar 2021 22:20:17 -0800 Subject: [PATCH 4/7] better markdown --- proposals/005_RequestBody-Links.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/005_RequestBody-Links.md b/proposals/005_RequestBody-Links.md index 38ae0d4ea3..5f9cb06bde 100644 --- a/proposals/005_RequestBody-Links.md +++ b/proposals/005_RequestBody-Links.md @@ -117,9 +117,9 @@ It's acceptable for parameters to be defined in either `fragments` OR `parameter ## Alternatives considered -There are multiple ways to solve this problem that other people have suggested that are in fact extremely valid. This Proposal is trying to make all parties happy by addressing each of the three major points each alternative independently address: +There are multiple ways to solve this problem that other people have suggested that are in fact extremely valid. This Proposal is trying to make all parties happy by addressing each of the major points each alternative independently address: -1 - Allow for OpenAPI authors to reference response properties from Specifications they themselves do not own. aka ["Backlinks"](https://apigraph.readthedocs.io/en/latest/reference/openapi-extensions.html#x-apigraph-backlinks-components) -2 - Set a field in the target operation's request body [Proposal](https://apigraph.readthedocs.io/en/latest/reference/openapi-extensions.html#x-apigraph-requestbodyparameters) +1. Allow for OpenAPI authors to reference response properties from Specifications they themselves do not own. aka ["Backlinks"](https://apigraph.readthedocs.io/en/latest/reference/openapi-extensions.html#x-apigraph-backlinks-components) +2. Set a field in the target operation's request body [Proposal](https://apigraph.readthedocs.io/en/latest/reference/openapi-extensions.html#x-apigraph-requestbodyparameters) While this proposal is very similar to the proposal for both 1 & 2, efforts to reach out them have failed, so I have gone forward with my own more condenced and concise version. I do feel that consideration of these alternative solutions is extremely important as the larger issue is support for these points in general. \ No newline at end of file From d3c2e40ded6537bc31e5089b6d894529b7e5ea3e Mon Sep 17 00:00:00 2001 From: Marsh Gardiner Date: Thu, 4 Mar 2021 10:01:47 -0800 Subject: [PATCH 5/7] basic editing pass Referencing the OAI documentation directly and some minor wordsmithing. --- proposals/005_RequestBody-Links.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proposals/005_RequestBody-Links.md b/proposals/005_RequestBody-Links.md index 5f9cb06bde..b569baf897 100644 --- a/proposals/005_RequestBody-Links.md +++ b/proposals/005_RequestBody-Links.md @@ -21,11 +21,11 @@ ## Introduction -This proposal is to support [`Link`]((https://swagger.io/docs/specification/links/)) objects on [`Operation`]((https://swagger.io/specification/#operation-object)) objects. Simply put, if *Response A* returns a property called *Foo*, and *Foo* is intended to be used in *Request B*'s request body as property *Bar*, one would define a `Link` in *Bar*'s operation to indicate the value of *Bar* is **sourced** from *Foo*. +This proposal is to support [`Link`](http://spec.openapis.org/oas/v3.1.0#link-object) objects on [`Operation`](http://spec.openapis.org/oas/v3.1.0#operationObject) objects. Simply put, if *Response A* returns a property called *Foo*, and *Foo* is intended to be used in *Request B*'s request body as property *Bar*, one would define a `Link` in *Bar*'s operation to indicate the value of *Bar* is **sourced** from *Foo*. ## Motivation -In an ideal world, integration with Web API's could be done entirely automatically. While the current OAS Specification does have *some* support defining dependencies between requests using [links](https://swagger.io/docs/specification/links/), it is currently not possible to define relationships between response data and request data in the body for separate requests. +In an ideal world, integration with Web APIs could be done entirely automatically. While the current OpenAPI Specification does have *some* support defining dependencies between requests using [links](http://spec.openapis.org/oas/v3.1.0#link-object), it is currently not possible to define relationships between response data and request data in the body for separate requests. Perhaps the more prelevant use case for this is for **refresh tokens**. In most modern authentication mechanisms, a user is allowed the best of both words in terms of security and usability in that they are issued short lived authentication tokens along with longer lived refresh tokens for later. Although this relationship is somewhat obvious to a human, there are cases where it might be ambiguous. Further, it's impossible for a generated sdk to account for this connection. @@ -33,10 +33,10 @@ By including a way to document these dependencies among data, generated clients ## Proposed solution -Allow [Links](https://swagger.io/docs/specification/links/) to exist at the root level of an [Operation](https://swagger.io/specification/#operation-object), rather than solely in a [Response](https://swagger.io/specification/#response-object) object. When defined at the `Operation` Level, each link would represent a link to a request from where to source information. The `link.operationId` would reference the "source" request. This would allow for describing from where dependent parameters get their information to make the request. In addition, a new poperty would be added to the `Link` object that would be called `fragments`. This new property would contain [runtime expressions](https://swagger.io/specification/#runtime-expression) that would evaluate which *fragments* to extract data from, and which *fragments* to populate that data with. +Allow [Links](http://spec.openapis.org/oas/v3.1.0#link-object) to exist at the root level of an [Operation](http://spec.openapis.org/oas/v3.1.0#operationObject), rather than solely in a [Response](http://spec.openapis.org/oas/v3.1.0#responses-object) object. When defined at the `Operation` Level, each link would represent a link to a request from where to source information. The `link.operationId` would reference the "source" request. This would allow for describing from where dependent parameters get their information to make the request. In addition, a new poperty would be added to the `Link` object that would be called `fragments`. This new property would contain [runtime expressions](http://spec.openapis.org/oas/v3.1.0#runtime-expressions) that would evaluate which *fragments* to extract data from, and which *fragments* to populate that data with. Some Explanations: -1. The request based `Link` object would allow for OpenAPI authors to reference response properties from Specifications they themselves do not own. For Example; A company named Foo handles billing through paypal. This company has a billing API, and updates a plan using the paypal [user_id](https://developer.paypal.com/docs/api/identity/v1/#userinfo-get-response). An author at company Foo could reference Paypal's swagger spec in theirs, opening the door for even richer sdk generation as well as many other possibilities. +1. The request based `Link` object would allow for OpenAPI authors to reference response properties from OpenAPI documents they themselves do not own. For Example; A company named Foo handles billing through PayPal. This company has a billing API, and updates a plan using the PayPal [user_id](https://developer.paypal.com/docs/api/identity/v1/#userinfo-get-response). An author at company Foo could reference PayPal's OpenAPI document in theirs, opening the door for even richer sdk generation as well as many other possibilities. 2. The `Fragments` property is more discrete than having separate properties to define whether a given response fragment belongs in a subsequent request's header, body, or path. For example: `$response.header.req_id` mapping to `$request.body#requestId` or `$response.header.req_id` mapping to `$request.header.requestId`. 3. It's easier to think about dependencies of requests from within the request itself. @@ -122,4 +122,4 @@ There are multiple ways to solve this problem that other people have suggested t 1. Allow for OpenAPI authors to reference response properties from Specifications they themselves do not own. aka ["Backlinks"](https://apigraph.readthedocs.io/en/latest/reference/openapi-extensions.html#x-apigraph-backlinks-components) 2. Set a field in the target operation's request body [Proposal](https://apigraph.readthedocs.io/en/latest/reference/openapi-extensions.html#x-apigraph-requestbodyparameters) -While this proposal is very similar to the proposal for both 1 & 2, efforts to reach out them have failed, so I have gone forward with my own more condenced and concise version. I do feel that consideration of these alternative solutions is extremely important as the larger issue is support for these points in general. \ No newline at end of file +While this proposal is very similar to the proposal for both 1 & 2, efforts to reach out them have failed, so I have gone forward with my own more condenced and concise version. I do feel that consideration of these alternative solutions is extremely important as the larger issue is support for these points in general. From 5400ad612161e4dbe320c9b1335b35289ba0ff93 Mon Sep 17 00:00:00 2001 From: luckybroman5 Date: Thu, 4 Mar 2021 22:44:34 -0800 Subject: [PATCH 6/7] Minor Edits, plus enhanced Alternatives section. --- proposals/005_RequestBody-Links.md | 35 ++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/proposals/005_RequestBody-Links.md b/proposals/005_RequestBody-Links.md index b569baf897..96b9959efe 100644 --- a/proposals/005_RequestBody-Links.md +++ b/proposals/005_RequestBody-Links.md @@ -1,6 +1,6 @@ - # Feature name +### Isomorphic Request Body Links ## Metadata @@ -27,23 +27,23 @@ This proposal is to support [`Link`](http://spec.openapis.org/oas/v3.1.0#link-ob In an ideal world, integration with Web APIs could be done entirely automatically. While the current OpenAPI Specification does have *some* support defining dependencies between requests using [links](http://spec.openapis.org/oas/v3.1.0#link-object), it is currently not possible to define relationships between response data and request data in the body for separate requests. -Perhaps the more prelevant use case for this is for **refresh tokens**. In most modern authentication mechanisms, a user is allowed the best of both words in terms of security and usability in that they are issued short lived authentication tokens along with longer lived refresh tokens for later. Although this relationship is somewhat obvious to a human, there are cases where it might be ambiguous. Further, it's impossible for a generated sdk to account for this connection. +Perhaps the more prevalent use case for this is for **refresh tokens**. In most modern authentication mechanisms, a user is allowed the best of both words in terms of security and usability in that they are issued short lived authentication tokens along with longer lived refresh tokens for later. Although this relationship is somewhat obvious to a human, there are cases where it might be ambiguous. Further, it's impossible for a generated sdk to account for this connection. -By including a way to document these dependencies among data, generated clients could better serve their end users, there would be no ambiguidy for human readers, and would open the door for richer forms of documentation like a dependency graph visualization. +By including a way to document these dependencies among data, generated clients could better serve their end users, there would be no ambiguity for human readers, and would open the door for richer forms of documentation like a dependency graph visualization. ## Proposed solution -Allow [Links](http://spec.openapis.org/oas/v3.1.0#link-object) to exist at the root level of an [Operation](http://spec.openapis.org/oas/v3.1.0#operationObject), rather than solely in a [Response](http://spec.openapis.org/oas/v3.1.0#responses-object) object. When defined at the `Operation` Level, each link would represent a link to a request from where to source information. The `link.operationId` would reference the "source" request. This would allow for describing from where dependent parameters get their information to make the request. In addition, a new poperty would be added to the `Link` object that would be called `fragments`. This new property would contain [runtime expressions](http://spec.openapis.org/oas/v3.1.0#runtime-expressions) that would evaluate which *fragments* to extract data from, and which *fragments* to populate that data with. +Allow [Links](http://spec.openapis.org/oas/v3.1.0#link-object) to exist at the root level of an [Operation](http://spec.openapis.org/oas/v3.1.0#operationObject), rather than solely in a [Response](http://spec.openapis.org/oas/v3.1.0#responses-object) object. When defined at the `Operation` Level, each link would represent a link to a request from where to source information. The `link.operationId` would reference the "source" request. This would allow for describing from where dependent parameters get their information to make the request. In addition, a new property would be added to the `Link` object that would be called `fragments`. This new property would contain [runtime expressions](http://spec.openapis.org/oas/v3.1.0#runtime-expressions) that would evaluate which *fragments* to extract data from, and which *fragments* to populate that data with. Some Explanations: 1. The request based `Link` object would allow for OpenAPI authors to reference response properties from OpenAPI documents they themselves do not own. For Example; A company named Foo handles billing through PayPal. This company has a billing API, and updates a plan using the PayPal [user_id](https://developer.paypal.com/docs/api/identity/v1/#userinfo-get-response). An author at company Foo could reference PayPal's OpenAPI document in theirs, opening the door for even richer sdk generation as well as many other possibilities. -2. The `Fragments` property is more discrete than having separate properties to define whether a given response fragment belongs in a subsequent request's header, body, or path. For example: `$response.header.req_id` mapping to `$request.body#requestId` or `$response.header.req_id` mapping to `$request.header.requestId`. +2. The `Fragments` property is more discreet than having separate properties to define whether a given response fragment belongs in a subsequent request's header, body, or path. For example: `$response.header.req_id` mapping to `$request.body#requestId` or `$response.header.req_id` mapping to `$request.header.requestId`. 3. It's easier to think about dependencies of requests from within the request itself. ## Detailed design -### Ammendment to `Link` Object +### Amendment to `Link` Object `Links` can now exist on `Operation` objects @@ -111,15 +111,28 @@ type: Array of `Fragment` objects ## Backwards compatibility -Since the modifications to existing Objects is purely additive and positional, there shouldn't be any issues with backwards compatibility. Should a `fragments` array be defined within a response's `Links` as the current standard supports, the effect is exactly the same. +Since the modifications to existing Objects are purely additive and positional, there shouldn't be any issues with backwards compatibility. Should a `fragments` array be defined within a response's `Links` as the current standard supports, the effect is exactly the same. It's acceptable for parameters to be defined in either `fragments` OR `parameters` within the `link` object, and is up to preference of the individual spec's author. Perhaps in later versions of OAS should this proposal become accepted, `parameters` might be deprecated. ## Alternatives considered -There are multiple ways to solve this problem that other people have suggested that are in fact extremely valid. This Proposal is trying to make all parties happy by addressing each of the major points each alternative independently address: +There are multiple ways to solve this problem that other people have suggested that are in fact extremely valid. Admittedly, this proposal is largely inspired from the ideas expressed by @anentropic. @anentropic's **proposal will from here on be referred to as ["apigraph"](https://apigraph.readthedocs.io/en/latest/reference/openapi-extensions.html)**, which is certainly a valid alternative. The proposal outlined here in this current markdown document, will be referred to as "this proposal". + + +Some differences between *this proposal* and *apigraph*, along with reasonings: +1. This proposal *reuses* the links object, allowing it be defined on the Operation level for a consuming request. Apigraph creates an entirely new object called `backLinks` that serves the same purpose. +- Most of the fields in the apigraph's `backlinks` object are repetitive, and already defined on the existing `Link` Object. **Isomorphism is probably simpler than overlapping-duplication**. +2. Apigraph includes `requestBodyParameters` that contains `map[JSONPointer]runTimeExpression`, while this proposal's equivilent contains a `src` and `dest` runtime expressions. +- The apigraph solution doesn't account for instances where a single response parameter should be fed into multiple request parameters. +- This proposal allows for parameters to be mapped to the target operation, allowing for more general usage than only pertaining to the requestBody +3. ApiGraph introduces a field called `chainId` to its `backlinks` object +- This is not a necessary change, and is proprietary to apigraph itself. +4. Apigraph introduces a field called `responseRef` +- There are now too many mutually exclusive ways to link back to the response, and this adds unnecessary bloat to the spec that tooling would need to support. (OperationId, OperationRef, ResponseRf, Response) -1. Allow for OpenAPI authors to reference response properties from Specifications they themselves do not own. aka ["Backlinks"](https://apigraph.readthedocs.io/en/latest/reference/openapi-extensions.html#x-apigraph-backlinks-components) -2. Set a field in the target operation's request body [Proposal](https://apigraph.readthedocs.io/en/latest/reference/openapi-extensions.html#x-apigraph-requestbodyparameters) +The general sentiment around ApiGraph and this proposal are the same in addressing these points: +1. `Inversion of Control` for the links object, or the ability for the request that requires the data to define the link, rather than the response that provides it +2. Ability to target specific request body elements from the link object. -While this proposal is very similar to the proposal for both 1 & 2, efforts to reach out them have failed, so I have gone forward with my own more condenced and concise version. I do feel that consideration of these alternative solutions is extremely important as the larger issue is support for these points in general. +Overall, this proposal aims to be a more concise and trimmed version of Apigraph. As previously mentioned in the TSC meeting on 4 March 2021, the adoption of links has been low perhaps due to complexity in their usage. From 712745ce9985a7f49619119e628d28270f2ff94f Mon Sep 17 00:00:00 2001 From: luckybroman5 Date: Thu, 4 Mar 2021 22:51:05 -0800 Subject: [PATCH 7/7] Renamed `fragments` and `fragment` objects --- proposals/005_RequestBody-Links.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/proposals/005_RequestBody-Links.md b/proposals/005_RequestBody-Links.md index 96b9959efe..bd2f32df6b 100644 --- a/proposals/005_RequestBody-Links.md +++ b/proposals/005_RequestBody-Links.md @@ -33,11 +33,11 @@ By including a way to document these dependencies among data, generated clients ## Proposed solution -Allow [Links](http://spec.openapis.org/oas/v3.1.0#link-object) to exist at the root level of an [Operation](http://spec.openapis.org/oas/v3.1.0#operationObject), rather than solely in a [Response](http://spec.openapis.org/oas/v3.1.0#responses-object) object. When defined at the `Operation` Level, each link would represent a link to a request from where to source information. The `link.operationId` would reference the "source" request. This would allow for describing from where dependent parameters get their information to make the request. In addition, a new property would be added to the `Link` object that would be called `fragments`. This new property would contain [runtime expressions](http://spec.openapis.org/oas/v3.1.0#runtime-expressions) that would evaluate which *fragments* to extract data from, and which *fragments* to populate that data with. +Allow [Links](http://spec.openapis.org/oas/v3.1.0#link-object) to exist at the root level of an [Operation](http://spec.openapis.org/oas/v3.1.0#operationObject), rather than solely in a [Response](http://spec.openapis.org/oas/v3.1.0#responses-object) object. When defined at the `Operation` Level, each link would represent a link to a request from where to source information. The `link.operationId` would reference the "source" request. This would allow for describing from where dependent parameters get their information to make the request. In addition, a new property would be added to the `Link` object that would be called `mappings`. This new property would contain [runtime expressions](http://spec.openapis.org/oas/v3.1.0#runtime-expressions) that would evaluate which *mappings* to extract data from, and which *mappings* to populate that data with. Some Explanations: 1. The request based `Link` object would allow for OpenAPI authors to reference response properties from OpenAPI documents they themselves do not own. For Example; A company named Foo handles billing through PayPal. This company has a billing API, and updates a plan using the PayPal [user_id](https://developer.paypal.com/docs/api/identity/v1/#userinfo-get-response). An author at company Foo could reference PayPal's OpenAPI document in theirs, opening the door for even richer sdk generation as well as many other possibilities. -2. The `Fragments` property is more discreet than having separate properties to define whether a given response fragment belongs in a subsequent request's header, body, or path. For example: `$response.header.req_id` mapping to `$request.body#requestId` or `$response.header.req_id` mapping to `$request.header.requestId`. +2. The `mappings` property is more discreet than having separate properties to define whether a given response mapping belongs in a subsequent request's header, body, or path. For example: `$response.header.req_id` mapping to `$request.body#requestId` or `$response.header.req_id` mapping to `$request.header.requestId`. 3. It's easier to think about dependencies of requests from within the request itself. @@ -49,11 +49,11 @@ Some Explanations: #### New Fields: -**Fragments** -Key: `fragments` -type: Array of `Fragment` objects +**mappings** +Key: `mappings` +type: Array of `mapping` objects -**Fragment** +**mapping** |Field Name |Type |Description | |---- | ---------------- | ---------- | | src | runtime expression | expresses from where in the source request to apply to `dest` | @@ -90,7 +90,7 @@ type: Array of `Fragment` objects links: # <-- Links can now exist here arbitraryName: operationId: getUserBestFriend - fragments: # <-- New Property for links + mappings: # <-- New Property for links - src: '$response.body#/id' dest: '$request.body#/from' required: true @@ -111,9 +111,9 @@ type: Array of `Fragment` objects ## Backwards compatibility -Since the modifications to existing Objects are purely additive and positional, there shouldn't be any issues with backwards compatibility. Should a `fragments` array be defined within a response's `Links` as the current standard supports, the effect is exactly the same. +Since the modifications to existing Objects are purely additive and positional, there shouldn't be any issues with backwards compatibility. Should a `mappings` array be defined within a response's `Links` as the current standard supports, the effect is exactly the same. -It's acceptable for parameters to be defined in either `fragments` OR `parameters` within the `link` object, and is up to preference of the individual spec's author. Perhaps in later versions of OAS should this proposal become accepted, `parameters` might be deprecated. +It's acceptable for parameters to be defined in either `mappings` OR `parameters` within the `link` object, and is up to preference of the individual spec's author. Perhaps in later versions of OAS should this proposal become accepted, `parameters` might be deprecated. ## Alternatives considered