在 Go Echo 框架中操作 HTTP 請求 (2)

這是關於在 Echo 框架中處理 HTTP 請求的第二篇文章,我們將繼續開發上一篇文章所完成的例子。

這次我們將建立一個簡單的 HTML 表格並將其實現為一個 POST 請求。

建立 POST 請求端點

取得此 git 項目並新增 api/post_full_name.go 來處理 POST 請求。這個新文件幾乎與* api/post_full_name.go* 相同,唯一分別在於返回客戶端的 JSON 被格式化。

api/post_full_name.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package api

import (
  "bytes"
  "encoding/json"
  "fmt"
  "net/http"

  "github.com/labstack/echo"

  "gitlab.com/ykyuen/handling-http-request-in-go-echo-example-1/model"
)

func PostFullName(c echo.Context) error {
  // Bind the input data to ExampleRequest
  exampleRequest := new(model.ExampleRequest)
  if err := c.Bind(exampleRequest); err != nil {
    return err
  }

  // Manipulate the input data
  greeting := exampleRequest.FirstName + " " + exampleRequest.LastName

  // Pretty print the json []byte
  var resp bytes.Buffer
  var b = []byte(
    fmt.Sprintf(`{
      "first_name": %q,
      "last_name": %q,
      "msg": "Hello %s"
    }`, exampleRequest.FirstName, exampleRequest.LastName, greeting),
  )
  err := json.Indent(&resp, b, "", "  ")
  if err != nil {
    return err
  }

  // Return the json to the client
  return c.JSONBlob(
    http.StatusOK,
    []byte(
      fmt.Sprintf("%s", resp.Bytes()),
    ),
  )
}

main.go 中添加新路由。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
func main() {
  // Echo instance
  e := echo.New()

  // Instantiate a template registry with an array of template set
  // Ref: https://gist.github.com/rand99/808e6e9702c00ce64803d94abff65678
  templates := make(map[string]*template.Template)
  templates["home.html"] = template.Must(template.ParseFiles("view/home.html", "view/base.html"))
  templates["about.html"] = template.Must(template.ParseFiles("view/about.html", "view/base.html"))
  e.Renderer = &TemplateRegistry{
    templates: templates,
  }

  // Route => handler
  e.GET("/", handler.HomeHandler)
  e.GET("/about", handler.AboutHandler)

  // Route => api
  e.GET("/api/get-full-name", api.GetFullName)
  e.POST("/api/post-full-name", api.PostFullName)

  // Start the Echo server
  e.Logger.Fatal(e.Start(":1323"))
}

使用 curl 指令來測試新端點

運行 Echo 服務器並使用 curl 指令發送 POST 請求。

1
curl http://localhost:1323/api/post-full-name -H "Content-Type: application/json" -d '{ "first_name": "Kit", "last_name": "Yuen"  }'

結果如下。

根據 POST 請求所返回的 JSON 回應。

根據 POST 請求所返回的 JSON 回應。

建立一張 HTML 表格

現在 POST 請求端點已準備就緒,我們可以在 about 頁面中添加一張表單並完成整個設置。

view/about.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{{define "title"}}
  Boatswain Blog | {{index . "name"}}
{{end}}

{{define "body"}}
  <h1>{{index . "msg"}}</h1>
  <h2>This is the about page.</h2>

  <!-- HTML form -->
  <form id="post-full-name-form">
    <input type="text" id="first-name" placeholder="First Name">
    <input type="text" id="last-name" placeholder="Last Name">
    <button type="button" id="submit-btn">Submit</button>
  </form>

  <!-- Print the response after the jQuery ajax request -->
  <pre id="form-result"></pre>

  <script type="text/javascript">
    // Send a ajax request when the submit button is clicked
    $("#submit-btn").on("click", function(){
      var firstName = $("#first-name").val();
      var lastName = $("#last-name").val();

      $.ajax({
        type: "POST",
        url: "/api/post-full-name",
        data: JSON.stringify({
          first_name: firstName,
          last_name: lastName
        }),
        processData: false,
        contentType: "application/json",
        dataType: "json"
      }).done(
        function(data){
          $("#form-result").text(JSON.stringify(data, null, 2));
        }
      ).fail(
        function(data){
          $("#form-result").text("POST request failed!");
        }
      )
    });
  </script>
{{end}}

由於提交表格需要使用 jQuery,所以要在修改 view/base.html 來加入它。

view/base.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{{define "base.html"}}
  <!DOCTYPE html>
  <html>
    <head>
      <title>{{template "title" .}}</title>
      <!-- jQuery -->
      <script
        src="https://code.jquery.com/jquery-3.3.1.min.js"
        integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
        crossorigin="anonymous"></script>
    </head>
    <body>
      {{template "body" .}}
    </body>
  </html>
{{end}}

在 about 頁面中測試 HTML 表格

啟動 Echo 服務器並瀏覽 about 頁面,填寫名字和姓氏然後點擊提交按鈕之後就應該可以看到 API 回應的 JSON。

點擊提交按鈕便可得到 API 的回應。

點擊提交按鈕便可得到 API 的回應。

項目結構

這是新的項目結構,作了更改或新增的文件被加亮。(項目重命名為 handling-http-request-in-go-echo-example-2,如果要更改項目名稱,請確保正確設置 Golang 代碼中的 import 語句。)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
handling-http-request-in-go-echo-example-2/
  ├── api/                     # folder of api endpoints
  │   ├── get_full_name.go     # api for get full name
  │   ├── post_full_name.go    # api for post full name
  ├── handler/                 # folder of request handlers
  │   ├── home_handler.go      # handler for home page
  │   └── about_handler.go     # handler for about page
  ├── model/                   # folder of custom struct types
  │   ├── example_request.go   # struct type of get_full_name request
  │   └── example_response.go  # hstruct type of get_full_name response
  ├── vendor/                  # dependencies managed by dep
  │   ├── github.com/*
  │   └── golang.org/*
  ├── view/                    # folder of html templates
  │   ├── base.html            # base layout template
  │   ├── home.html            # home page template
  │   └── about.html           # about page template
  ├── Gopkg.lock               # dep config file
  ├── Gopkg.toml               # dep config file
  └── main.go                  # programme entrypoint

總結

本文是在 Go Echo 框架中操作 HTTP 請求 (1)的後續,我們作了以下修改:

  • Echo 框架中建立 POST 請求端點。
  • 格式化/美化 JSON 回應。
  • 添加一個 HTML 表格並使用 jQuery/javascript 以 AJAX 將其實現一個 POST 請求。

完整的例子可以在此 gitlab.com 代碼庫上找到。