Skip to content

Commit 30c10c6

Browse files
committed
added links proposal
1 parent 6d25b12 commit 30c10c6

File tree

1 file changed

+341
-1
lines changed

1 file changed

+341
-1
lines changed

versions/3.0.md

Lines changed: 341 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,7 @@ default:
938938
```
939939

940940
#### <a name="responseObject"></a>Response Object
941-
Describes a single response from an API Operation.
941+
Describes a single response from an API Operation, including design-time, static `links` to operations based on the response.
942942

943943
##### Fixed Fields
944944
Field Name | Type | Description
@@ -947,6 +947,8 @@ Field Name | Type | Description
947947
<a name="responseSchema"></a>schema | [Schema Object](#schemaObject) | A definition of the response structure. It can be a primitive, an array or an object. If this field does not exist, it means no content is returned as part of the response. As an extension to the [Schema Object](#schemaObject), its root `type` value may also be `"file"`. This SHOULD be accompanied by a relevant `produces` mime-type.
948948
<a name="responseHeaders"></a>headers | [Headers Object](#headersObject) | A list of headers that are sent with the response.
949949
<a name="responseExamples"></a>examples | [Example Object](#exampleObject) | An example of the response message.
950+
<a name="responseLinks"></a>links | [Links Object](#linksObject) | An object representing operations related to the response payload.
951+
950952

951953
##### Patterned Objects
952954

@@ -1123,6 +1125,344 @@ application/json:
11231125
breed: Mixed
11241126
```
11251127

1128+
#### <a name="linksObject"></a>Links Object
1129+
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 call invoke it, rather it provides a known relationship and traversal mechanism between responses and other operations.
1130+
1131+
As opposed to _dynamic_ links--that is, 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.
1132+
1133+
For computing links, and providing instructions to execute them, a mechanism is defined for accessing values in a response and using them as variables while invoking the linked operation.
1134+
1135+
Field Name | Type | Description
1136+
---|:---:|---
1137+
<a name="referenceRef"></a>$ref | `string` | If present, a reference to another Links Object. Note, the presence of `$ref` in the Links Object will cause all _Patterned Objects_ to be ignored.
1138+
1139+
Field Pattern | Type | Description
1140+
---|:---:|---
1141+
<a name="linkName"></a>link name | [Link Object](#linkObject) | A short name for the link, following the naming constraints of the <a href="#definitionsName">definitions name</a>. The link shall reference a single Link Object, or a JSON Reference to a single link object
1142+
1143+
1144+
### Link Object
1145+
The `Link Object` is responsible for defining a possible operation based on a single response.
1146+
1147+
Field Name | Type | Description
1148+
--- | :---: | ---
1149+
href | url | a relative or absolute URL to a linked resource. This field is mutually exclusive with the `operationId` field.
1150+
operationId| string | the name of an _existing_, resolvable OAS operation, as defined with a unique `operationId`. This field is mutually exclusive with the `href` field. Relative `href` values _may_ be used to locate an existing Operation Object in the OAS.
1151+
parameters | Link Parameters Object | an Object representing parameters to pass to an operation as specified with `operationId` or identified via `href`.
1152+
description | string | a description of the link, supports GFM.
1153+
1154+
#### <a name="responsePayload"></a>Response Payload Values
1155+
1156+
Payload values are only available in parseable response payloads which match the advertised media-type. 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.
1157+
1158+
### Example
1159+
1160+
Response payload:
1161+
```json
1162+
{
1163+
"id": "df71a505-07bc-458a-a5c0-73c0340d1ec7",
1164+
"firstname": "Ash",
1165+
"lastname": "Williams"
1166+
}
1167+
```
1168+
1169+
Payload Variables:
1170+
```yaml
1171+
id: df71a505-07bc-458a-a5c0-73c0340d1ec7
1172+
firstname: Ash
1173+
lastname: Williams
1174+
missingValue: null
1175+
```
1176+
1177+
In situations where variables appear in an array, an array of variables will be extracted. For example:
1178+
1179+
```json
1180+
[
1181+
{ "color": "red" },
1182+
{ "color": "green" },
1183+
{ "color": "blue" }
1184+
]
1185+
```
1186+
1187+
will be extracted as such:
1188+
1189+
```json
1190+
color: ["red", "green", "blue"]
1191+
```
1192+
1193+
The variables generated can be used in locations prescribed by the definition.
1194+
1195+
1196+
### Variable substitution
1197+
In all cases, _variables_ identified in the response payload may be substitued **only** in locations prescribed in the link definitions. All such locations are prefixed by a `$response` keyword and surrounded by curly brackets `{}`.
1198+
1199+
### Example
1200+
Computing a link from a response object is performed as follows:
1201+
1202+
```yaml
1203+
Addresses:
1204+
href: /users/{$response.id}/address
1205+
```
1206+
1207+
Where the `$response.id` from the example above would yield the target:
1208+
1209+
```yaml
1210+
href: '/users/df71a505-07bc-458a-a5c0-73c0340d1ec7/address'
1211+
```
1212+
1213+
And the array example:
1214+
1215+
```yaml
1216+
ColorSelection:
1217+
href: 'http://colors.my-server.com/colors/{$response.color}'
1218+
```
1219+
1220+
Would produce the following links:
1221+
1222+
```yaml
1223+
href: 'http://colors.my-server.com/colors/red'
1224+
href: 'http://colors.my-server.com/colors/green'
1225+
href: 'http://colors.my-server.com/colors/blue'
1226+
```
1227+
1228+
As with all links, it at the the clients' discretion to follow them, and permissions and the existence of a value is not guaranteed soley by the existence of a link relationship. [**I assume you mean that the existance of the link relationship does not guarantee a successful response from the call**]
1229+
1230+
1231+
### Example
1232+
1233+
The example below shows how relationships in the BitBucket API can be represented with the proposed OAI link scheme. This example uses `operationId` values to link responses to possible operations.
1234+
1235+
```yaml
1236+
paths:
1237+
/2.0/users/{username}:
1238+
get:
1239+
operationId: getUserByName
1240+
parameters:
1241+
- name: username
1242+
type: string
1243+
in: path
1244+
required: true
1245+
responses:
1246+
200:
1247+
description: The User
1248+
schema:
1249+
$ref: '#/components/definitions/user'
1250+
links:
1251+
userRepositories:
1252+
$ref: '#/components/links/UserRepositories'
1253+
/2.0/repositories/{username}:
1254+
get:
1255+
operationId: getRepositoriesByOwner
1256+
parameters:
1257+
- name: username
1258+
type: string
1259+
in: path
1260+
required: true
1261+
responses:
1262+
200:
1263+
description: repositories owned by the supplied user
1264+
schema:
1265+
type: array
1266+
items:
1267+
$ref: '#/components/definitions/repository'
1268+
links:
1269+
userRepository:
1270+
$ref: '#/components/links/UserRepository'
1271+
/2.0/repositories/{username}/{slug}:
1272+
get:
1273+
operationId: getRepository
1274+
parameters:
1275+
- name: username
1276+
type: string
1277+
in: path
1278+
required: true
1279+
- name: slug
1280+
type: string
1281+
in: path
1282+
required: true
1283+
responses:
1284+
200:
1285+
description: The repository
1286+
schema:
1287+
$ref: '#/components/definitions/repository'
1288+
links:
1289+
repositoryPullRequests:
1290+
$ref: '#/components/links/RepositoryPullRequests'
1291+
/2.0/repositories/{username}/{slug}/pullrequests:
1292+
get:
1293+
operationId: getPullRequestsByRepository
1294+
parameters:
1295+
- name: username
1296+
type: string
1297+
in: path
1298+
required: true
1299+
- name: slug
1300+
type: string
1301+
in: path
1302+
required: true
1303+
- name: state
1304+
type: string
1305+
in: query
1306+
enum:
1307+
- open
1308+
- merged
1309+
- declined
1310+
responses:
1311+
200:
1312+
description: an array of pull request objects
1313+
schema:
1314+
type: array
1315+
items:
1316+
$ref: '#/components/definitions/pullrequest'
1317+
/2.0/repositories/{username}/{slug}/pullrequests/{pid}:
1318+
get:
1319+
operationId: getPullRequestsById
1320+
parameters:
1321+
- name: username
1322+
type: string
1323+
in: path
1324+
required: true
1325+
- name: slug
1326+
type: string
1327+
in: path
1328+
required: true
1329+
- name: pid
1330+
type: string
1331+
in: path
1332+
required: true
1333+
responses:
1334+
200:
1335+
description: a pull request object
1336+
schema:
1337+
$ref: '#/components/definitions/pullrequest'
1338+
links:
1339+
$ref: '#/components/links/PullRequestMerge'
1340+
/2.0/repositories/{username}/{slug}/pullrequests/{pid}/merge:
1341+
post:
1342+
operationId: mergePullRequest
1343+
parameters:
1344+
- name: username
1345+
type: string
1346+
in: path
1347+
required: true
1348+
- name: slug
1349+
type: string
1350+
in: path
1351+
required: true
1352+
- name: pid
1353+
type: string
1354+
in: path
1355+
required: true
1356+
responses:
1357+
204:
1358+
description: the PR was successfully merged
1359+
components:
1360+
links:
1361+
UserRepositories:
1362+
# returns array of '#/components/definitions/repository'
1363+
operationId: getRepositoriesByOwner
1364+
parameters:
1365+
username: $response.username
1366+
UserRepository:
1367+
# returns '#/components/definitions/repository'
1368+
operationId: getRepository
1369+
parameters:
1370+
username: $response.owner.username
1371+
slug: $response.slug
1372+
RepositoryPullRequests:
1373+
# returns '#/components/definitions/pullrequest'
1374+
operationId: getPullRequestsByRepository
1375+
params:
1376+
username: $response.owner.username
1377+
slug: $response.slug
1378+
PullRequestMerge:
1379+
# executes /2.0/repositories/{username}/{slug}/pullrequests/{pid}/merge
1380+
operationId: mergePullRequest
1381+
parameters:
1382+
username: $response.user.username # Should be $response.author.username?
1383+
slug: $response.repository.slug
1384+
pid: $response.id
1385+
definitions:
1386+
user:
1387+
type: object
1388+
properties:
1389+
username:
1390+
type: string
1391+
uuid:
1392+
type: string
1393+
repository:
1394+
type: object
1395+
properties:
1396+
slug:
1397+
type: string
1398+
owner:
1399+
$ref: '#/components/definitions/user'
1400+
pullrequest:
1401+
type: object
1402+
properties:
1403+
id:
1404+
type: integer
1405+
title:
1406+
type: string
1407+
repository:
1408+
$ref: '#/components/definitions/repository'
1409+
author:
1410+
$ref: '#/components/definitions/user'
1411+
```
1412+
1413+
As references to `operationId` may not be possible (the `operationId` is an optional value), references may also be made through a relative `href`:
1414+
1415+
```yaml
1416+
components:
1417+
links:
1418+
UserRepositories:
1419+
# returns array of '#/components/definitions/repository'
1420+
href: '/2.0/repositories/{$response.username}'
1421+
```
1422+
1423+
or an absolute `href`:
1424+
1425+
```yaml
1426+
components:
1427+
links:
1428+
UserRepositories:
1429+
# returns array of '#/components/definitions/repository'
1430+
href: 'https://na2.gigantic-server.com/2.0/repositories/{$response.username}'
1431+
```
1432+
1433+
1434+
### Link Parameters
1435+
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.
1436+
1437+
To specify parameters required by the operation, we can use a **Link Parameters Object**. This object contains parameter names along with static or dynamic valus:
1438+
1439+
```yaml
1440+
paths:
1441+
/user/{username}: # ...
1442+
/user/{username}/commits:
1443+
get:
1444+
operationId: userCommitHistory
1445+
parameters:
1446+
- name: username
1447+
in: path
1448+
type: string
1449+
required: true
1450+
- name: page
1451+
type: integer
1452+
format: int32
1453+
required: true
1454+
responses: { ... }
1455+
components:
1456+
links:
1457+
UserCommitHistory:
1458+
operationId: userCommitHistory
1459+
parameters:
1460+
username: $response.user.username
1461+
page: 0
1462+
```
1463+
1464+
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`.
1465+
11261466
#### <a name="headerObject"></a>Header Object
11271467

11281468
Field Name | Type | Description

0 commit comments

Comments
 (0)