in golang ~ read.

以 Go 語言快速實作 HTTP GET/POST API

(同步發表於 Cepave)

維基百科中提到:

目前在三種主流的Web服務實現方案中,因為REST模式與複雜的SOAP和XML-RPC相比更加簡潔,越來越多的web服務開始採用REST風格設計和實現。

符合 REST 設計風格的 Web API 稱為 RESTful API。它從以下三個方面資源進行定義:直觀簡短的資源地址、傳輸的資源、對資源的操作。

那麼我們要如何使用 Go 語言原生的函式庫建立簡單的 Web Server 提供 GET/POST 接口呢?讓我們透過 Hello World 的範例來說明。

建立 HTTP Server 接收請求

  1. 透過
    http.HandleFunc("/", callback)
    ,我們可以定義 callback 函式所要負責的 URI。
  2. 呼叫
    http.Request.ParseForm()
    取出參數。同時適用於 GET/POST,所以為了減少行數我將範例中 GET/POST 一併處理。
  3. 透過
    http.Request.FormValue("key")
    取出姓氏與名字。
  4. 最後,將字串以
    http.ResponseWriter.Write("Hello World")
    輸出,client 端即可在網頁上看到對應的訊息囉!
// server.go package main import (     "fmt"     "net/http" ) func main() {     http.HandleFunc("/cepave", func(w http.ResponseWriter, req *http.Request) {         req.ParseForm()         if req.Method "GET" || req.Method "POST" {             fmt.Println(req.ContentLength)             firstname := req.FormValue("firstname")             lastname := req.FormValue("lastname")             w.Write([]byte(fmt.Sprintf("[%s] Hello, %s %s!", req.Method, firstname, lastname)))         } else {             http.Error(w, "The method is not allowed.", http.StatusMethodNotAllowed)         }     })     err := http.ListenAndServe(":9000", nil)     if err != nil {         fmt.Println("ListenAndServe failed: ", err)     } }

實際發送請求來試試!

完成了 Server 端程式之後,我們可以透過

go run server.go
開始運行。 HTTP GET 可以直接以瀏覽器輸入 URL 即可測試,但既然都寫了 server.go 不如也把 client.go 實現吧! GET/POST 發送請由分別是透過
http.Get(...)
以及
http.PostForm(...)
來達成。在 client.go 裡面之所以多 import 兩個函式庫的原因是為了要儲存 HTTP POST 的參數,並且處理送出請求後返回的 HTTP response。
// client.go package main import (     "fmt"     "io/ioutil"     "net/http"     "net/url" ) func main() {     // POST     resp, err := http.PostForm("http://localhost:9000/cepave",         url.Values{"firstname": {"Kordan"}, "lastname": {"Ou"}})     if err != nil {         fmt.Println(err)     } else {         body, _ := ioutil.ReadAll(resp.Body)         fmt.Println("POST OK: ", string(body), resp)     }     // GET     resp, err = http.Get("http://localhost:9000/cepave?firstname=Kordan&lastname=Ou")     if err != nil {         fmt.Println(err)     } else {         body, _ := ioutil.ReadAll(resp.Body)         fmt.Println("GET OK: ", string(body), resp)     } }

如果只是想測試 API,我們也可以打開終端機直接輸入以下命令:

$ curl "localhost:9000/cepave?firstname=Kordan&lastname=Ou" [GET] Hello, Kordan Ou! $curl -X POST -d "firstname=Kordan&&lastname=Ou" localhost:9000/cepave [POST] Hello, Kordan Ou!

如果是有巢狀結構的 JSON,我們可以這樣發 HTTP POST:

package main import (     "bytes"     "fmt"     "io/ioutil"     "net/http" ) func main() {     var jsonStr = []byte(`{     "endpoint_counters": [         {             "endpoint": "host1",             "counter": "load.1min"         },         {             "endpoint": "host2",             "counter": "cpu.idle"         }     ],     "start": 1437375109,     "end": 1437377109,     "cf": "AVERAGE"     }`)     url := "http://example.com/graph/history"     fmt.Println("URL:>", url)     req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))     req.Header.Set("X-Custom-Header", "myvalue")     req.Header.Set("Content-Type", "application/json")     client := &http.Client{}     resp, err := client.Do(req)     if err != nil {         panic(err)     }     defer resp.Body.Close()     fmt.Println("response Status:", resp.Status)     fmt.Println("response Headers:", resp.Header)     body, _ := ioutil.ReadAll(resp.Body)     fmt.Println("response Body:", string(body)) }

透過以上幾個範例,應該可以感受到 Go 語言的簡潔以及內建函式庫的強大吧?!

其他參考資料

  1. http://www.restapitutorial.com/lessons/httpmethods.html
  2. http://www.evanlin.com/golangheroku-rest-api-web-application/
  3. http://dougblack.io/words/a-restful-micro-framework-in-go.html
comments powered by Disqus