API得全名叫做Application Programming Interface,也就是一個應用程式的街口,讓第三方可以進行開發、應用在其他用途上的溝通管道。
但首先需要先介紹一下HTTP,HTTP全名Hypertext Transfer Protocol,在該Protocol有Client、Server兩種人,舉例來說,Client指的就是我、Server指的就是Google,我在點擊Google首頁時,我就是像Google的Server傳送了這個請求,然後Google在回應所需資源給我。但為了要讓Request與Response有統一個規範,才誕生出HTTP。
舉例來說,我們搜尋了某個在Google下的網址會有以下步驟:
Response會依照該Request的合法性給出相對應的狀態碼,狀態碼也能夠大致分為以下種類:
此外,在HTTP中會有許多種不同method的請求行為,最常見的就是GET / POST / PUT /DELETE,
這些method也剛好會對應到資料庫的基本操作CRUD行為(Create, Read, Update, Delete)
REST全名為Representational State Transfer( 表現層狀態轉移),他是一種設計風格,而RESTful則形容以此規範設計的API,稱為RESTfuk API。
RESTful API主要由三種不同元件組成:
一般的API,可能呈現方式會是這樣:
新增資料POST /createData
獲得資料GET /getData/1
刪除資料DELETEe /deleteData/1
不同公司,不一樣的工程師,設計的名稱都會不一樣,也沒有統一的命名方式,造成在引用各家 API 時,都需要詳讀 API 文件,理解所有設計命名規則後,才可使用。
若是以RESTful API的風格開發的話:
新增資料POST /data ,Method: POST
獲得資料GET /data ,Method: GET
刪除資料DELETE /data/1 ,Method: DELETE
就是用一個唯一的URL定位資源,將動作藏在HTTP的method裡面。
所以使用RESTful風格設計的API,就會有以下幾種優點以及限制:
RESTful的狀態即是HTTP的請求狀態,在一般Web服務中,Server Side與Client Side交互的資訊會存在Server Side的Session(像是登入狀態等),在Client Side再次發起請求時,Server Side會透過保存的Session去執行Request。而無狀態的意思就是Client Side會自行保存狀態,在對Server Side發出請求時,一併將其附給Server Side,Server Side並不會保存Client Side的狀態。
舉例來說,在用戶登錄系統時,Server 產生 token 紀錄 user 已登錄系統,然後把 token 還給 Client,在 Client 再次發送請求的時候,把 token 一起發給 Server,這樣 Server 就知道這一個 Client 是已經處於登錄的狀態。
Using GET, POST, PUT, PATCH, DELETE and OPTIONS @ API Example
gin.Default()
:使用 gin router 預設的 middleware,包含 logger 和 recover (crash-free) 的 middlewarerouter.Run()
:預設是 :8080
,可以用字串修改,例如 router.Run(":3000")
router.GET()
: 前面的GET, POST表示方法,後面參數則是表示路徑以及接收Request執行的行為簡單舉例如下
func main() {
// Creates a gin router with default middleware:
// logger and recovery (crash-free) middleware
router := gin.Default()
router.GET("/someGet", getting)
router.POST("/somePost", posting)
router.PUT("/somePut", putting)
router.DELETE("/someDelete", deleting)
router.PATCH("/somePatch", patching)
router.HEAD("/someHead", head)
router.OPTIONS("/someOptions", options)
// By default it serves on :8080 unless a PORT environment variable was defined.
router.Run()
// router.Run(":3000") for a hard coded port
}
取得網址中的 params:
:<filed>
可以定義動態路由(只能匹配到 /
以前)<filed>
可以定義動態路由(可以匹配到 /
以後)c.Param("<field>")
可以取得網址中的參數c.Fullpath()
可以取得定義的路由參數func main() {
router := gin.Default()
router.GET("/user", func(c *gin.Context) {
c.String(200, "/user")
})
router.GET("/user/:name", func(c *gin.Context) {
fmt.Println(c.FullPath()) // /user/:name/
name := c.Param("name")
c.String(http.StatusOK, "Hello %s", name)
})
router.GET("/user/:name/*action", func(c *gin.Context) {
fmt.Println(c.FullPath()) // /user/:name/*action
name := c.Param("name")
action := c.Param("action")
message := name + " is " + action
c.String(http.StatusOK, message)
})
router.Run(":3000")
}
這章節主要介紹RESTful API以及簡單Gin Router的使用,在下個章節則會示範Gin的項目結構一般來說會長怎麼樣,如何配合middleware來建立起簡單乾淨的routing structure。