コンテンツにスキップ

リンク

リンクは、OpenAPI 3.0の新機能の一つです。リンクを使用すると、ある操作によって返されたさまざまな値が、他の操作の入力としてどのように使用できるかを記述できます。これにより、リンクは操作間の既知の関係とトラバースメカニズムを提供します。リンクの概念はハイパーメディアと多少似ていますが、OpenAPIリンクは実際のレスポンスにリンク情報が存在することを要求しません。

「ユーザー作成」操作を考慮します

1
POST /users HTTP/1.1
2
Host: example.com
3
Content-Type: application/json
4
5
{
6
"name": "Alex",
7
"age": 27
8
}
9
10
which returns the ID of the created user:
11
12
HTTP/1.1 201 Created
13
Content-Type: application/json
14
15
{
16
"id": 305
17
}

このユーザーIDは、ユーザーの読み取り、更新、削除に使用できます。GET /users/305PATCH /users/305DELETE /users/305です。リンクを使用すると、「ユーザー作成」によって返されたid値が、「ユーザー取得」、「ユーザー更新」、「ユーザー削除」のパラメータとして使用できることを指定できます。別の例として、カーソルによるページネーションがあり、レスポンスには次のデータセットを取得するためのカーソルが含まれます。

1
GET /items?limit=100
2
3
4
5
{
6
"metadata": {
7
"previous": null,
8
"next": "Q1MjAwNz",
9
"count": 10
10
},
11
...
12
}
13
14
15
16
GET /items?cursor=Q1MjAwNz&limit=100

ただし、リンク関係は必ずしも同じリソース内、あるいは同じAPI仕様内である必要はありません。

リンクは、各レスポンスのlinksセクションで定義されます。

1
responses:
2
"200":
3
description: Created
4
content: ...
5
links: # <----
6
...
7
"400":
8
description: Bad request
9
content: ...
10
links: # <----
11
...

これをよりよく理解するために、完全な例を見てみましょう。このAPIは「ユーザー作成」と「ユーザー取得」操作を定義しており、「ユーザー作成」の結果は「ユーザー取得」への入力として使用されます。

1
openapi: 3.0.4
2
info:
3
version: 0.0.0
4
title: Links example
5
6
paths:
7
/users:
8
post:
9
summary: Creates a user and returns the user ID
10
operationId: createUser
11
requestBody:
12
required: true
13
description: A JSON object that contains the user name and age.
14
content:
15
application/json:
16
schema:
17
$ref: "#/components/schemas/User"
18
responses:
19
"201":
20
description: Created
21
content:
22
application/json:
23
schema:
24
type: object
25
properties:
26
id:
27
type: integer
28
format: int64
29
description: ID of the created user.
30
# -----------------------------------------------------
31
# Links
32
# -----------------------------------------------------
33
links:
34
GetUserByUserId: # <---- arbitrary name for the link
35
operationId: getUser
36
# or
37
# operationRef: '#/paths/~1users~1{userId}/get'
38
parameters:
39
userId: "$response.body#/id"
40
41
description: >
42
The `id` value returned in the response can be used as
43
the `userId` parameter in `GET /users/{userId}`.
44
# -----------------------------------------------------
45
46
/users/{userId}:
47
get:
48
summary: Gets a user by ID
49
operationId: getUser
50
parameters:
51
- in: path
52
name: userId
53
required: true
54
schema:
55
type: integer
56
format: int64
57
responses:
58
"200":
59
description: A User object
60
content:
61
application/json:
62
schema:
63
$ref: "#/components/schemas/User"
64
65
components:
66
schemas:
67
User:
68
type: object
69
properties:
70
id:
71
type: integer
72
format: int64
73
readOnly: true
74
name:
75
type: string

linksセクションには、名前付きリンク定義が含まれています。この例では、「GetUserByUserId」という名前のリンクが1つだけです。リンク名には次の文字のみを含めることができます。

1
A..Z a..z 0..9 . _ -

各リンクには以下の情報が含まれます。

  • ターゲット操作を指定するoperationIdまたはoperationRef。これは、現在のまたは外部のAPI仕様内の同じ操作または異なる操作である場合があります。operationIdはローカルリンクのみに使用され、operationRefはローカルおよび外部操作の両方にリンクできます。
  • ターゲット操作に渡す値を指定するparametersおよび/またはrequestBodyセクション。ランタイム式構文は、これらの値を親操作から抽出するために使用されます。
  • (オプション) ターゲット操作がデフォルトのサーバーと異なる場合、ターゲット操作が使用すべきserver
  • (オプション) このリンクのdescriptionCommonMark構文はリッチテキスト表現に使用できます。

このページの残りの部分では、これらのキーワードについてさらに詳しく説明します。

OpenAPI 3.0 links

operationId

ターゲット操作にoperationIdが指定されている場合、上記の画像のように、リンクはこのIDを指すことができます。このアプローチはローカルリンクのみに使用できます。operationIdの値は現在のAPI仕様のスコープ内で解決されるためです。

operationRef

operationIdが利用できない場合、operationRefを使用できます。operationRefは、JSON参照構文を使用してターゲット操作への参照です。$refキーワードで使用されるものと同じです。参照はローカル(現在のAPI仕様内)にできます。

1
operationRef: "#/paths/~1users~1{userId}/get"

または外部

1
operationRef: 'https://anotherapi.com/openapi.yaml#/paths/~1users~1{userId}/get'
2
operationRef: './operations/getUser.yaml'

ここで、文字列#/paths/~1users~1{userId}/getは実際には#/paths//users/{userId}/getを意味しますが、パス名内の内部スラッシュ/は特殊文字であるため、~1としてエスケープする必要があります。

1
#/paths/~1users~1{userId}/get
2
│ │ │
3
│ │ │
4
paths: │ │
5
/users/{userId}:
6
get: ─────────────────┘
7
...

この構文は読みにくいため、外部リンクのみに使用することをお勧めします。ローカルリンクの場合、すべての操作にoperationIdを割り当て、これらのIDにリンクする方が簡単です。

parametersとrequestBody

リンクの最も重要な部分は、元の操作からの値に基づいてターゲット操作の入力を計算することです。これがparametersおよびrequestBodyキーワードの目的です。

1
links:
2
# GET /users/{userId}
3
GetUserByUserId:
4
operationId: getUser
5
parameters:
6
userId: "$response.body#/id"
7
8
# POST /users/{userId}/manager with the manager ID in the request body
9
SetManagerId:
10
operationId: setUserManager
11
requestBody: "$response.body#/id"

構文は_parameter_name: value_または _requestBody: value_ です。パラメーター名とリクエストボディはターゲット操作のものです。すべてのパラメーターをリストする必要はなく、リンクをたどるのに必要なものだけです。同様に、requestBodyは、ターゲット操作にbodyがあり、かつリンクの目的がボディの内容を定義する場合にのみ使用されます。2つ以上のパラメーターが同じ名前を持つ場合、パス、クエリ、ヘッダー、またはクッキーなど、パラメーターの位置で名前を接頭辞として付けます。

1
parameters:
2
path.id: ...
3
query.id: ...

パラメータとrequestBodyの値は、次の方法で定義できます。

  • 元の操作のリクエストまたはレスポンス内の値を参照する、$response.body#/idなどのランタイム式
  • ID_{$response.body#/id}のように、埋め込みランタイム式を含む文字列、
  • mystringtrueなどのハードコードされた値(文字列、数値、配列など)。

通常、ターゲット操作に対して評価されたパラメーターとハードコードされたパラメーターの特定の組み合わせを渡す必要がある場合は、定数値を使用します。

1
paths:
2
/date_ranges:
3
get:
4
summary: Get relative date ranges for the report.
5
responses:
6
'200':
7
description: OK
8
content:
9
application/json:
10
example: [Today, Yesterday, LastWeek, ThisMonth]
11
links:
12
ReportRelDate:
13
operationId: getReport
14
# Call "getReport" with the `rdate` parameter and with empty `start_date` and `end_date`
15
parameters:
16
rdate: '$response.body#/1'
17
start_date: ''
18
end_date: ''
19
20
# GET /report?rdate=...
21
# GET /report?start_date=...&end_date=...
22
/report:
23
get:
24
operationId: getReport
25
...

ランタイム式構文

OpenAPIランタイム式は、操作のリクエストとレスポンスからさまざまな値を抽出するための構文です。リンクはランタイム式を使用して、リンクされた操作に渡すパラメーター値を指定します。これらの式は「ランタイム」と呼ばれます。なぜなら、値はAPI呼び出しの実際のリクエストとレスポンスから抽出され、API仕様で提供される例の値などからではないからです。次の表に、ランタイム式構文を説明します。すべての式は、linksが定義されている*現在の操作*を参照します。

説明

$url

クエリ文字列を含む完全なリクエストURL。

$method

GETやPOSTなどのリクエストHTTPメソッド。

$request.query._param_name_

指定されたクエリパラメータの値。パラメータは操作のparametersセクションで定義されている必要があります。そうでない場合、評価できません。パラメータ名は大文字と小文字を区別します。

$request.path._param_name_

指定されたパスパラメータの値。パラメータは操作のparametersセクションで定義されている必要があります。そうでない場合、評価できません。パラメータ名は大文字と小文字を区別します。

$request.header._header_name_

指定されたリクエストヘッダーの値。このヘッダーは操作のparametersセクションで定義されている必要があります。そうでない場合、評価できません。ヘッダー名は大文字と小文字を区別しません。

$request.body

リクエストボディ全体。

$request.body_#/foo/bar_

JSONポインタで指定されたリクエストボディの一部。

$statusCode

レスポンスのHTTPステータスコード。例えば、200または404。

$response.header._header_name_

指定された応答ヘッダーの完全な値(文字列として)。ヘッダー名は大文字と小文字を区別しません。ヘッダーは応答のheadersセクションで定義されている必要はありません。

$response.body

レスポンスボディ全体。

$response.body_#/foo/bar_

JSONポインタで指定されたリクエストボディの一部。

foo{$request.path.id}bar

式を文字列に埋め込むには、{}中括弧で囲みます。

備考

  • 特に指定がない限り、評価された式は参照される値と同じ型を持ちます。
  • ランタイム式が評価できない場合、ターゲット操作にパラメータ値は渡されません。

次のリクエストとレスポンスを考慮してください。

1
GET /users?limit=2&total=true
2
Host: api.example.com
3
Accept: application/json
1
HTTP/1.1 200 OK
2
Content-Type: application/json
3
X-Total-Count: 37
4
5
{
6
"prev_offset": 0,
7
"next_offset": 2,
8
"users": [
9
{"id": 1, "name": "Alice"},
10
{"id": 2, "name": "Bob"}
11
]
12
}

以下にランタイム式の例と、それらが評価される値を示します。

結果コメント
$urlhttp://api.example.com/users?limit=2&total=true
$methodGET
$request.query.total本当total はクエリパラメータとして定義されている必要があります。
$statusCode200
$response.header.x-total-count37X-Total-Countがレスポンスヘッダーとして定義されていると仮定します。ヘッダー名は大文字と小文字を区別しません。
$response.body#/next_offset2
$response.body#/users/0{"id": 1, "name": "Alice"}JSONポインタ(#/...の部分)は、配列要素にアクセスするために0ベースのインデックスを使用します。ただし、ワイルドカード構文はないため、$response.body#/users/*/idは無効です。
$response.body#/users/1{"id": 2, "name": "Bob"}
$response.body#/users/1/nameボブ
ID_{$response.body#/users/1/id}ID_2

サーバー

デフォルトでは、ターゲット操作は、グローバルなserversまたは操作固有のserversのいずれかのデフォルトのサーバーに対して呼び出されます。ただし、serverキーワードを使用してリンクによってサーバーをオーバーライドできます。serverはグローバルサーバーと同じフィールドを持ちますが、単一のサーバーであり配列ではありません。

1
servers:
2
- url: https://api.example.com
3
---
4
links:
5
GetUserByUserId:
6
operationId: getUser
7
parameters:
8
userId: "$response.body#/id"
9
server:
10
url: https://new-api.example.com/v2

リンクはインラインで定義することも(前述の例のように)、グローバルなcomponents/linksセクションに配置し、$refを使用して操作のlinksセクションから参照することもできます。これは、複数の操作が同じ方法で別の操作にリンクする場合に役立ちます。参照はコードの重複を減らすのに役立ちます。次の例では、「ユーザー作成」操作と「ユーザー更新」操作の両方が応答ボディにユーザーIDを返し、このIDは「ユーザー取得」操作で使用されます。ソース操作はcomponents/linksから同じリンク定義を再利用します。

1
paths:
2
/users:
3
post:
4
summary: Create a user
5
operationId: createUser
6
...
7
responses:
8
'201':
9
description: Created
10
content:
11
application/json:
12
schema:
13
type: object
14
properties:
15
id:
16
type: integer
17
format: int64
18
description: ID of the created user.
19
links:
20
GetUserByUserId:
21
$ref: '#/components/links/GetUserByUserId' # <-------
22
23
/user/{userId}:
24
patch:
25
summary: Update user
26
operationId: updateUser
27
...
28
responses:
29
'200':
30
description: The updated user object
31
content:
32
application/json:
33
schema:
34
$ref: '#/components/schemas/User'
35
links:
36
GetUserByUserId:
37
$ref: '#/components/links/GetUserByUserId' # <-------
38
39
get:
40
summary: Get a user by ID
41
operationId: getUser
42
...
43
44
components:
45
links:
46
GetUserByUserId: # <----- The $ref's above point here
47
description: >
48
The `id` value returned in the response can be used as
49
the `userId` parameter in `GET /users/{userId}`.
50
operationId: getUser
51
parameters:
52
userId: '$response.body#/id'

参照

リンクオブジェクト

お探しのものが見つかりませんでしたか? コミュニティに質問する
間違いを見つけましたか? お知らせください