實作簡單的REST API


Posted by Nacho on 2020-03-29

實作目標

寫一個簡單的Web Server,處裡不同HTTP動作的請求,並輸出字串回應。

開始

在Go的工作目錄底下,建立一個新資料夾叫 SimpleRESTAPI,並建立一個主程式的執行檔 main.go。基本的檔案內容如下,這裡需要引入net套件中的http函式庫,後續才能用Go產生一個 http server。

package main

import(
    "fmt"
    "net/http"
)

func main() {
}

階段一: 建立一個 web server

撰寫一個notFound的處裡器,讓 server 啟動後可以顯示一點東西。在這個notFound函式會傳入兩個參數。先從第二個參數說起 ,r 代表Request負責接收client端發出的請求,並交由第一個參數 w 負責為請求做出回應與寫入訊息。針對寫入的訊息,在函式內可以設定了http的表頭、狀態及內容。

func notFound(w http.ResponseWriter, r *http.Request){
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusNotFound)  
    w.Write([]byte(`{"message": "not found"}`)) // 傳輸 []byte 格式的資料
}

func main() {
    http.HandleFunc("/", notFound) // 指定任何路徑下的都去呼叫 notFound 函式
    http.ListenAndServe(":8000", nil) // 指定server監聽 port 8000 
}

這裡加上例外處裡顯示像是port號已被其它程式占用或其他的錯誤訊息。

func main() {
    http.HandleFunc("/", notFound) 
    err := http.ListenAndServe(":8000", nil)
    if err != nil {
        panic(err) // 如果有錯誤就終止程式
    }
    fmt.Println("The port 8000 is successfully connected")
}

階段二: 建立路由功能

雖然使用 net/http 可以實現路由功能,但日後若有更多功能要開發,這樣的設計方式會衍伸路由管理的麻煩,因此這個階段導入了一個路由設計的套件叫gorilla/mux。可以用這行指令$ go get -u github.com/gorilla/mux取得這個套件。

import(
    "net/http"
    "github.com/gorilla/mux"
)
func get(w http.ResponseWriter, r *http.Request){
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK) 
    w.Write([]byte(`{"message": "get called"}`))
}

func main() {
    router := mux.NewRouter()
    router.HandleFunc("/", get).Methods(http.MethodGet)
    err := http.ListenAndServe(":8000", router)
    if err != nil {
        panic(err) // 如果有錯誤就終止程式
    }
    fmt.Println("The port 8000 is successfully connected")
}

引入"github.com/gorilla/mux" ,這裡我註冊了一條新url路徑並指給 get 處裡,註冊新 url的方式與 http.HandleFunc()一樣,若有符合路徑的請求就到對應的處裡器並傳入參數(http.ResponseWriter, *http.Request)。參考文件 另外,這裡在HandleFunc()之後綁定 HTTP的動作,所以同一個路徑會針對有不同HTTP動作執行相對應的處裡器。現在可以打開終端機,先輸入go run main.go啟動go主程式,接著輸入curl -X GET localhost:8000/就會看到 {message: get called} 的訊息了。

階段三: 設計 Web API

func main() {
    router := mux.NewRouter()
    api := router.PathPrefix("/api/v1").Subrouter()
    api.HandleFunc("/", get).Methods(http.MethodGet)
    err := http.ListenAndServe(":8000", router)
    if err != nil {
        panic(err) // 如果有錯誤就終止程式
    }
    fmt.Println("The port 8000 is successfully connected")
}

假如在我的server上有很多支API路徑,我希望透過不同的namespace來做管理。透過 mux 利用 PathPrefix("/api/v1").Subrouter(),篩選符合路徑的請求並做路徑分流。現在要輸入curl -X GET localhost:8000/api/v1/才會看到 {message: get called} 的訊息。參考文件

之後可以加入其它像是POST、PUT、DELETE的動作來做不同的路由處裡。
完整範例參考

筆記參考

Mux官方文件


#Go http #Gorilla Mux #REST API #Go Router







Related Posts

陳述式 與 表達式

陳述式 與 表達式

使用 VScode + Code Runner 開發 Python 輸出為中文亂碼問題

使用 VScode + Code Runner 開發 Python 輸出為中文亂碼問題

DP

DP


Comments