iT邦幫忙

2024 iThome 鐵人賽

DAY 10
0
IT 管理

我要成為文件工程師── Web API 文件撰寫系列 第 10

[Day 10] TypeSpec:撰寫 OpenAPI 的領域特定語言 (四)

  • 分享至 

  • xImage
  •  

今天將介紹 TypeSpec 的基礎型別,接著說明如何將其使用在操作的參數和回傳中。

型別

數值

和 OpenAPI 一樣,TypeSpec 支援許多不同的數值型別,讓開發者可視需求選用。首先是最基本的幾種:

型別 說明
numeric 所有的數值型別
integer 所有的整數
float 二進位制浮點數
decimal 十進位制小數

若想更精細的表示數值型別,則有以下型別可使用:

型別 說明
int64 64-bit 整數
int32 32-bit 整數
float32 32-bit 浮點數
float64 64-bit 浮點數

完整清單可見官方文件

其他基礎型別

TypeSpec 也提供其他基礎型別如下:

型別 說明
boolean 布林
string 字串
null 無值
void 無回傳

常用型別

TypeSpec 也支援 API 常使用的型別,如時間等如下:

型別 說明
utcDateTime UTC 標準日期時間
offsetDateTime 指定時區的日期時間
url 網址格式的字串

另有 Array<Element>Record<Element> 兩種型別可使用,Array<Element> 為陣列,角括號中可指定陣列中的項目型別;Record<Element> 為 Key-Value 型別,類似其他語言中的 Map<Key, Value> 或 Dictionary<Key, Value>,在 TypeSpec 中,Key 必定為 string 型別。

TypeSpec 完整的型別請見官方文件

操作

參數

操作的參數對應到 API 的 Request Parameter,和 OpenAPI 規格中一樣須有名字和型別,並可透過 TypeSpec.Http 提供的 @header@query@path@body 裝飾器標示參數的擺放位置。延續昨日的範例專案,以取得單一會員 API 為範例,請求參數為 memberId,其型別為 int64,範例程式碼如下:

// member/member.tsp
import "@typespec/http";

using TypeSpec.Http;

namespace MemberService.Member;

@get()
@route("members/{memberId}")
op get(@path memberId: int64): {};

回傳

當沒有指定回傳狀態碼的時候,TypeSpec 會自動視型別是否為 void 判斷為 200 OK204 No Content。以昨日的 healthCheck API 為例,op healthCheck(): {}; 時編譯出的 openapi.yaml 回傳為 200,但若改為 op healthCheck(): void; 時編譯出的回傳則為 204 如下:

import "@typespec/http";
import "@typespec/rest";
import "@typespec/openapi3";

using TypeSpec.Http;

@service({
    title: "會員服務",
    version: "1.0.0"
})
@server("https://api.example.com/v1", "正式環境")
@server("https://api.staging.example.com/v1", "測試環境")
namespace MemberService;

@get()
@route("_hc")
@summary("確認服務健康狀態")
@doc("""
    這個 API 用來確認服務是否正常運作。
    這個 API 不需要任何參數,只要回應 204 即表示服務正常。
""")
op healthCheck(): void;
openapi: 3.0.0
info:
  title: 會員服務
  version: 1.0.0
tags: []
paths:
  /_hc:
    get:
      operationId: healthCheck
      summary: 確認服務健康狀態
      description: |2-
            這個 API 用來確認服務是否正常運作。
            這個 API 不需要任何參數,只要回應 204 即表示服務正常。
      parameters: []
      responses:
        '204':
          description: 'There is no content to send for this request, but the headers may be useful. '
components: {}
servers:
  - url: https://api.staging.example.com/v1
    description: 測試環境
    variables: {}
  - url: https://api.example.com/v1
    description: 正式環境
    variables: {}

我們可在回傳中指定不具名欄位並透過裝飾器 @statusCode 來指定回傳的狀態碼,範例程式碼如下:

op healthCheck(): { @statusCode _: 204 };

大括號中可列出回傳的其他內容,一樣可透過 @header@query@path@body 裝飾器標示擺放位置。以上面取得單一會員 API 為例,在大括號中宣告回傳的狀態碼、header 中的請求 ID 及 body 中的會員資料結構欄位,程式碼如下:

import "@typespec/http";

using TypeSpec.Http;

namespace MemberService.Member;

@summary("取得單一會員")
@doc("""
    這個 API 用來取得單一會員的資料。
    這個 API 需要提供會員 ID,並回應該會員的基本資料。
""")
@get()
@route("members/{memberId}")
op get(@path memberId: int64): {
    @statusCode _: 200;
    @header `x-request-id`: string;
    id: int64;
    name: string;
    email: string;
    phone: string;
    birthday?: utcDateTime;
};

其中 header 的名稱由於含有 - 所以使用反引號 `名稱`夾起,而 birthday 欄位為非必填所以使用 ? 表示。


到這邊完整 TypeSpec 專案程式碼如下:

// main.tsp
import "@typespec/http";
import "@typespec/rest";
import "@typespec/openapi3";
import "./member/member.tsp";

using TypeSpec.Http;

@service({
    title: "會員服務",
    version: "1.0.0"
})
@server("https://api.example.com/v1", "正式環境")
@server("https://api.staging.example.com/v1", "測試環境")
namespace MemberService;

@get()
@route("_hc")
@summary("確認服務健康狀態")
@doc("""
    這個 API 用來確認服務是否正常運作。
    這個 API 不需要任何參數,只要回應 204 即表示服務正常。
""")
op healthCheck(): { @statusCode _: 204 };
// member/member.tsp
import "@typespec/http";

using TypeSpec.Http;

namespace MemberService.Member;

@summary("取得單一會員")
@doc("""
    這個 API 用來取得單一會員的資料。
    這個 API 需要提供會員 ID,並回應該會員的基本資料。
""")
@get()
@route("members/{memberId}")
op get(@path memberId: int64): {
    @statusCode _: 200;
    @header `x-request-id`: string;
    id: int64;
    name: string;
    email: string;
    phone: string;
    birthday?: utcDateTime;
};

編譯後可得 openapi.yaml 如下:

openapi: 3.0.0
info:
  title: 會員服務
  version: 1.0.0
tags: []
paths:
  /_hc:
    get:
      operationId: healthCheck
      summary: 確認服務健康狀態
      description: |2-
            這個 API 用來確認服務是否正常運作。
            這個 API 不需要任何參數,只要回應 204 即表示服務正常。
      parameters: []
      responses:
        '204':
          description: 'There is no content to send for this request, but the headers may be useful. '
  /members/{memberId}:
    get:
      operationId: Member_get
      summary: 取得單一會員
      description: |2-
            這個 API 用來取得單一會員的資料。
            這個 API 需要提供會員 ID,並回應該會員的基本資料。
      parameters:
        - name: memberId
          in: path
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: The request has succeeded.
          headers:
            x-request-id:
              required: true
              schema:
                type: string
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                    format: int64
                  name:
                    type: string
                  email:
                    type: string
                  phone:
                    type: string
                  birthday:
                    type: string
                    format: date-time
                required:
                  - id
                  - name
                  - email
                  - phone
components: {}
servers:
  - url: https://api.staging.example.com/v1
    description: 測試環境
    variables: {}
  - url: https://api.example.com/v1
    description: 正式環境
    variables: {}

Redoc 預覽畫面如下:

https://ithelp.ithome.com.tw/upload/images/20240923/201511377rEcyijp2I.png

https://ithelp.ithome.com.tw/upload/images/20240923/201511378s6n810PLM.png

https://ithelp.ithome.com.tw/upload/images/20240923/20151137seaWjkSRM7.png

明天將介紹如何在 TypeSpec 中建立可重複使用的模型。


上一篇
[Day 09] TypeSpec:撰寫 OpenAPI 的領域特定語言 (三)
下一篇
[Day 11] TypeSpec:撰寫 OpenAPI 的領域特定語言 (五)
系列文
我要成為文件工程師── Web API 文件撰寫12
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言