大家好,我是 Yubin
我們在開發網頁後端的時候,常常會需要定義一些 API。本篇講一下透過 Fastify 的 Route 來定義 API Endpoint。
API,Application Programming Interface,應用程式介面。
這裡指的 API 可以想像成是你的系統,對外開出去的介面,對外開出去給別人使用的服務。
別人只能透過那些介面來跟你互動。
就像你去銀行想領錢,銀行是一個很大的系統,而且不是你管理的系統。
銀行提供了一些介面可以讓你領錢,例如櫃台人員、提款機。你只能透過櫃台人員或提款機,透過特定的動作
、提交特定的資訊
,才能完成領錢這個工作。
以銀行的角度來說,櫃台人員跟提款機就是銀行提供出去的介面。經過這些介面來提供提款服務給使用者,而不是讓使用者自己到金庫中拿取自己的財產。
以網頁系統來說,基於安全還有其他一堆有的沒的問題,我們也不會把自己的資料庫分享給別人(或外部系統)做使用,而是定義一些 Web API,讓使用者透過你開出去的介面,來拿取相應的資源。
想像你要開發一個會員資料庫系統,會員資料都存在資料庫中,如果把資料庫的連線帳號密碼給別人會非常的危險 (即使有做相應的資料庫使用者權限控管,仍然很危險)。
這個時候你就可以定義一些相應的 API 來讓外部服務進行存取。
我們可以利用 Fastify 的 route
方法,定義 endpoints。
import fastify, { FastifyInstance, RouteOptions } from 'fastify'
const server: FastifyInstance = fastify()
const helloRouteOptions: RouteOptions = {
method: 'GET',
url: '/',
handler: (request, reply) => {
return reply.status(200).send({ message: 'Hello World' })
}
}
server.route(helloRouteOptions)
.route()
方法吃一個 RouteOptions
的參數,我們可以把想要的 API 的資訊設定上去。以上述程式片段為例,method
是 GET
,url
是 /
。
就是在定義 GET /
這樣的 API,如果有一個 request 進來到這個 Endpoint,會呼叫 handler
所定義的函式。
handler
要給定的型態是一個 function,這個 function 的第一個參數是 FastifyRequest
、第二個參數是 FastifyReply
,然後 return 一個 FastifyReply
。
我們透過給定 RouteOptions
的值,來定義每個 API Endpoint 的樣子。
method
描述 HTTP Method,用大寫字串定義。例如 GET
, POST
, PUT
, PATCH
, DELETE
, 等。url
,描述路徑,這個 route 代表的路徑。handler
,這個 route 收到 request 後的處理函式。errorHandler
,自行定義 error 的處理函式。schema
,可以定義 request 跟 response 的格式,用於做資料的驗證及序列化。logLevel
,定義這個 route 使用的 log 等級。除了上述還有很多 fastify hook 可以設定在這個 route 上。
詳細 RouteOptions 的說明可以參考 Fastify RouteOptions
上述介紹的方式,先定義 RouteOptions
,再透過 .route()
的方式,其實有點麻煩,也不易閱讀。
Fastify 提供另一種比較簡潔的寫法,稱為 Shorthand declaration。
對應於不同的 HTTP Method,提供以下幾個方法
fastify.get(path, [options], handler)
fastify.head(path, [options], handler)
fastify.post(path, [options], handler)
fastify.put(path, [options], handler)
fastify.delete(path, [options], handler)
fastify.options(path, [options], handler)
fastify.patch(path, [options], handler)
試著把把上述定義 GET /
會回傳 Hello World 字串的 route,以 Shorthand 的方式改寫。
const server: FastifyInstance = fastify()
server.get('/', (request, reply) => {
return reply.status(200).send({ message: 'Hello World' })
})
有沒有覺得簡單直覺許多。
.get
表示註冊的是 GET
方法,第一個參數是 url,如果有需要 RouteOptions
可以放在第二個參數,然後接一個 handler function。
因為看起來比較乾淨清楚(不用看一堆 key-value 來判斷這是什麼樣的 API),所以自己在開發比較常用這種寫法。
handler
的使用,該 function 可以是一般的 function 也可以是 async function。
如果處理 request 的需要做一些非同步的工作,如查詢資料庫,用 async function 搭配 await 的寫法非常方便。
server.get('/', async (request, reply) => {
try {
const users = await queryUsersFromDb() // async task
return reply.status(200).send({ users })
} catch(error) {
return reply.status(500).send({ error })
}
})
以上是 fastify route 的基本介紹。