リンク
リンクは、OpenAPI 3.0の新機能の一つです。リンクを使用すると、ある操作によって返されたさまざまな値が、他の操作の入力としてどのように使用できるかを記述できます。これにより、リンクは操作間の既知の関係とトラバースメカニズムを提供します。リンクの概念はハイパーメディアと多少似ていますが、OpenAPIリンクは実際のレスポンスにリンク情報が存在することを要求しません。
いつリンクを使用しますか?
「ユーザー作成」操作を考慮します
1POST /users HTTP/1.12Host: example.com3Content-Type: application/json4
5{6 "name": "Alex",7 "age": 278}9
10which returns the ID of the created user:11
12HTTP/1.1 201 Created13Content-Type: application/json14
15{16 "id": 30517}
このユーザーIDは、ユーザーの読み取り、更新、削除に使用できます。GET /users/305
、PATCH /users/305
、DELETE /users/305
です。リンクを使用すると、「ユーザー作成」によって返されたid
値が、「ユーザー取得」、「ユーザー更新」、「ユーザー削除」のパラメータとして使用できることを指定できます。別の例として、カーソルによるページネーションがあり、レスポンスには次のデータセットを取得するためのカーソルが含まれます。
1GET /items?limit=1002
3 ⇩4
5{6 "metadata": {7 "previous": null,8 "next": "Q1MjAwNz",9 "count": 1010 },11 ...12}13
14 ⇩15
16GET /items?cursor=Q1MjAwNz&limit=100
ただし、リンク関係は必ずしも同じリソース内、あるいは同じAPI仕様内である必要はありません。
リンクの定義
リンクは、各レスポンスのlinks
セクションで定義されます。
1responses:2 "200":3 description: Created4 content: ...5 links: # <----6 ...7 "400":8 description: Bad request9 content: ...10 links: # <----11 ...
これをよりよく理解するために、完全な例を見てみましょう。このAPIは「ユーザー作成」と「ユーザー取得」操作を定義しており、「ユーザー作成」の結果は「ユーザー取得」への入力として使用されます。
1openapi: 3.0.42info:3 version: 0.0.04 title: Links example5
6paths:7 /users:8 post:9 summary: Creates a user and returns the user ID10 operationId: createUser11 requestBody:12 required: true13 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: Created21 content:22 application/json:23 schema:24 type: object25 properties:26 id:27 type: integer28 format: int6429 description: ID of the created user.30 # -----------------------------------------------------31 # Links32 # -----------------------------------------------------33 links:34 GetUserByUserId: # <---- arbitrary name for the link35 operationId: getUser36 # or37 # 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 as43 the `userId` parameter in `GET /users/{userId}`.44 # -----------------------------------------------------45
46 /users/{userId}:47 get:48 summary: Gets a user by ID49 operationId: getUser50 parameters:51 - in: path52 name: userId53 required: true54 schema:55 type: integer56 format: int6457 responses:58 "200":59 description: A User object60 content:61 application/json:62 schema:63 $ref: "#/components/schemas/User"64
65components:66 schemas:67 User:68 type: object69 properties:70 id:71 type: integer72 format: int6473 readOnly: true74 name:75 type: string
links
セクションには、名前付きリンク定義が含まれています。この例では、「GetUserByUserId」という名前のリンクが1つだけです。リンク名には次の文字のみを含めることができます。
1A..Z a..z 0..9 . _ -
各リンクには以下の情報が含まれます。
- ターゲット操作を指定する
operationId
またはoperationRef
。これは、現在のまたは外部のAPI仕様内の同じ操作または異なる操作である場合があります。operationId
はローカルリンクのみに使用され、operationRef
はローカルおよび外部操作の両方にリンクできます。 - ターゲット操作に渡す値を指定する
parameters
および/またはrequestBody
セクション。ランタイム式構文は、これらの値を親操作から抽出するために使用されます。 - (オプション) ターゲット操作がデフォルトのサーバーと異なる場合、ターゲット操作が使用すべき
server
。 - (オプション) このリンクの
description
。CommonMark構文はリッチテキスト表現に使用できます。
このページの残りの部分では、これらのキーワードについてさらに詳しく説明します。
operationId
ターゲット操作にoperationId
が指定されている場合、上記の画像のように、リンクはこのIDを指すことができます。このアプローチはローカルリンクのみに使用できます。operationId
の値は現在のAPI仕様のスコープ内で解決されるためです。
operationRef
operationId
が利用できない場合、operationRef
を使用できます。operationRef
は、JSON参照構文を使用してターゲット操作への参照です。$ref
キーワードで使用されるものと同じです。参照はローカル(現在のAPI仕様内)にできます。
1operationRef: "#/paths/~1users~1{userId}/get"
または外部
1operationRef: 'https://anotherapi.com/openapi.yaml#/paths/~1users~1{userId}/get'2operationRef: './operations/getUser.yaml'
ここで、文字列#/paths/~1users~1{userId}/get
は実際には#/paths//users/{userId}/get
を意味しますが、パス名内の内部スラッシュ/は特殊文字であるため、~1
としてエスケープする必要があります。
1#/paths/~1users~1{userId}/get2 │ │ │3 │ │ │4paths: │ │5 /users/{userId}: │6 get: ─────────────────┘7 ...
この構文は読みにくいため、外部リンクのみに使用することをお勧めします。ローカルリンクの場合、すべての操作にoperationId
を割り当て、これらのIDにリンクする方が簡単です。
parametersとrequestBody
リンクの最も重要な部分は、元の操作からの値に基づいてターゲット操作の入力を計算することです。これがparameters
およびrequestBody
キーワードの目的です。
1links:2 # GET /users/{userId}3 GetUserByUserId:4 operationId: getUser5 parameters:6 userId: "$response.body#/id"7
8 # POST /users/{userId}/manager with the manager ID in the request body9 SetManagerId:10 operationId: setUserManager11 requestBody: "$response.body#/id"
構文は_parameter_name: value_
または _requestBody: value
_ です。パラメーター名とリクエストボディはターゲット操作のものです。すべてのパラメーターをリストする必要はなく、リンクをたどるのに必要なものだけです。同様に、requestBody
は、ターゲット操作にbodyがあり、かつリンクの目的がボディの内容を定義する場合にのみ使用されます。2つ以上のパラメーターが同じ名前を持つ場合、パス、クエリ、ヘッダー、またはクッキーなど、パラメーターの位置で名前を接頭辞として付けます。
1parameters:2 path.id: ...3 query.id: ...
パラメータとrequestBody
の値は、次の方法で定義できます。
- 元の操作のリクエストまたはレスポンス内の値を参照する、
$response.body#/id
などのランタイム式、 ID_{$response.body#/id}
のように、埋め込みランタイム式を含む文字列、mystring
やtrue
などのハードコードされた値(文字列、数値、配列など)。
通常、ターゲット操作に対して評価されたパラメーターとハードコードされたパラメーターの特定の組み合わせを渡す必要がある場合は、定数値を使用します。
1paths:2 /date_ranges:3 get:4 summary: Get relative date ranges for the report.5 responses:6 '200':7 description: OK8 content:9 application/json:10 example: [Today, Yesterday, LastWeek, ThisMonth]11 links:12 ReportRelDate:13 operationId: getReport14 # 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: getReport25 ...
ランタイム式構文
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
式を文字列に埋め込むには、{}
中括弧で囲みます。
備考
- 特に指定がない限り、評価された式は参照される値と同じ型を持ちます。
- ランタイム式が評価できない場合、ターゲット操作にパラメータ値は渡されません。
例
次のリクエストとレスポンスを考慮してください。
1GET /users?limit=2&total=true2Host: api.example.com3Accept: application/json
1HTTP/1.1 200 OK2Content-Type: application/json3X-Total-Count: 374
5{6 "prev_offset": 0,7 "next_offset": 2,8 "users": [9 {"id": 1, "name": "Alice"},10 {"id": 2, "name": "Bob"}11 ]12}
以下にランタイム式の例と、それらが評価される値を示します。
式 | 結果 | コメント |
---|---|---|
$url | http://api.example.com/users?limit=2&total=true | |
$method | GET | |
$request.query.total | 本当 | total はクエリパラメータとして定義されている必要があります。 |
$statusCode | 200 | |
$response.header.x-total-count | 37 | X-Total-Count がレスポンスヘッダーとして定義されていると仮定します。ヘッダー名は大文字と小文字を区別しません。 |
$response.body#/next_offset | 2 | |
$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
はグローバルサーバーと同じフィールドを持ちますが、単一のサーバーであり配列ではありません。
1servers:2 - url: https://api.example.com3---4links:5 GetUserByUserId:6 operationId: getUser7 parameters:8 userId: "$response.body#/id"9 server:10 url: https://new-api.example.com/v2
リンクの再利用
リンクはインラインで定義することも(前述の例のように)、グローバルなcomponents/links
セクションに配置し、$ref
を使用して操作のlinks
セクションから参照することもできます。これは、複数の操作が同じ方法で別の操作にリンクする場合に役立ちます。参照はコードの重複を減らすのに役立ちます。次の例では、「ユーザー作成」操作と「ユーザー更新」操作の両方が応答ボディにユーザーIDを返し、このIDは「ユーザー取得」操作で使用されます。ソース操作はcomponents/links
から同じリンク定義を再利用します。
1paths:2 /users:3 post:4 summary: Create a user5 operationId: createUser6 ...7 responses:8 '201':9 description: Created10 content:11 application/json:12 schema:13 type: object14 properties:15 id:16 type: integer17 format: int6418 description: ID of the created user.19 links:20 GetUserByUserId:21 $ref: '#/components/links/GetUserByUserId' # <-------22
23 /user/{userId}:24 patch:25 summary: Update user26 operationId: updateUser27 ...28 responses:29 '200':30 description: The updated user object31 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 ID41 operationId: getUser42 ...43
44components:45 links:46 GetUserByUserId: # <----- The $ref's above point here47 description: >48 The `id` value returned in the response can be used as49 the `userId` parameter in `GET /users/{userId}`.50 operationId: getUser51 parameters:52 userId: '$response.body#/id'
参照
お探しのものが見つかりませんでしたか? コミュニティに質問する
間違いを見つけましたか? お知らせください