Go Web編程 第四章--處理請求

請求和響應

Request結構

  • URL字段
  • Header字段
  • Body字段
  • Form, PostForm, MultipartForm字段

在處理器函數中,我們可以通過Request獲取各個字段的詳細信息

func get_request_value(w *http.ResponseWriter, r *http.Request) {
    h := r.Header
    brower := r.Header.Get("User-Agent")
    fme.Fprintln(w, h)

    body := make([]byte, r.ContentLength)
    r.Body.Read(body)
    fmt.Fprintln(w, string(body))
}

Go與HTML表單

用戶在表單中輸入的數據會以鍵值對的形式記錄在請求的主體中,其中表單中的enctype屬性決定了以何種形式發送鍵值對。默認屬性值爲application/x-www-form-urlencoded,這個屬性會把表單中的數據編碼一個連續的長查詢字符串,另一種編碼方式爲multipart/form-data,表單中的數據會被轉換爲一條MIME報文,每個鍵值對都構成了這個報文的一部分。簡單來說,當表單只需要傳送簡單數據時,默認編碼更加簡單,高效;而當表單需要傳輸大量數據(如文件)時,使用後一種編碼方式會更好。有些時候,用戶可以通過Base64編碼,以文本方式傳送二進制數據。

使用Request結構獲取表單數據的一般步驟是:

  1. 調用ParseForm或者ParseMultipartForm方法進行語法分析
  2. 訪問Form, PostForm, MultipartForm等字段獲取數據
func get_form_data1(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()
    fmt.Fprintln(w, r.Form)
    // PostForm字段只支持默認編碼,並且只返回表單值,不返回URL查詢值
    fmt.Fprintln(w, r.PostForm)
}

當使用multipart/form-data編碼時,表單數據會被存儲到MultipartForm字段中

func get_form_data2(w http.ResponseWriter, r *http.Request) {
    r.ParseMultipartForm(1024)
    fmt.Fprintln(w, r.MultipartForm)
}

我們也可以使用FormValue或者PostFormValue快速獲取表單值,也兩個方法會自動調用ParseForm或者ParseMultipartForm方法,其中PostFormValue只會返回表單鍵值對而不會返回URL鍵值對

使用FormFile方法可以快速的獲取被上傳的文件

func process(w http.ResponseWriter, r *http.Request) {
    file, _, err := r.FormFile("upload")
    if err == nil {
        data, err := ioutil.ReadAll(file)
        if err == nil {
            fmt.Fprintln(w, string(data))
        }
    }
}

ResponseWriter

  • Write 接收一個字節數組,並寫入到HTTP響應主體中
  • WriteHeader 改變HTTP響應狀態碼
  • Header 修改HTTP響應首部
package main

import (
    json2 "encoding/json"
    "fmt"
    "net/http"
)

type Post struct {
    User string
    Threads []string
}

func writeExample(w http.ResponseWriter, r *http.Request) {
    str := `<html>
            <head><title>Go</title></head>
            <body><h1>Hello world</h1></body>
            </html>`
    w.Write([]byte(str))
}

func writeHeaderExample(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(501)
    fmt.Fprintln(w, "No such service, try next door")
}

func headerExample(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Location", "http://baidu.com")
    w.WriteHeader(302)
}

func jsonExample(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    post := &Post{
        User: "authetic",
        Threads: []string{"first", "second"},
    }
    json, _ := json2.Marshal(post)
    w.Write(json)
}

func main() {
    server := http.Server{
        Addr: "127.0.0.1:8080",
    }
    http.HandleFunc("/write", writeExample)
    http.HandleFunc("/writeheader", writeHeaderExample)
    http.HandleFunc("/redirect", headerExample)
    http.HandleFunc("/json", jsonExample)
    server.ListenAndServe()
}

Go與cookie

沒有設置Expires字段的通常被成爲會話cookie,瀏覽器關閉或刷新cookie就會消失,設置了Expires字段的通常被稱爲持久cookie,在過期時間之前會一直存在。

func set_cookie(w http.ResponseWriter, r *http.Request) {
    c1 := http.Cookie{
        Name: "first_cookie",
        Value: "Go Web",
        HttpOnly: true,
    }
    c2 := http.Cookie{
        Name: "second_cookie",
        Value: "Go Web",
        HttpOnly: true,
    }
    
    http.SetCookie(w, &c1)
    http.SetCookie(w, &c2)
}

func get_cookie(w http.ResponseWriter, r *http.Request) {
    // h := r.Header["Cookie"]
    cl, err := r.Cookie("first_cookie")
    if err != nil {
        fmt.Fprintln(w, "Something wrong")
    }
    cs := r.Cookies()
    fmt.Fprintln(w, cl)
    fmt.Fprintln(w, cs)
}

cookie實現閃現消息

func setMessage(w http.ResponseWriter, r *http.Request) {
    msg := []byte("Hello Go")
    c := http.Cookie{
        Name: "flash",
        Value: base64.URLEncoding.EncodeToString(msg),
    }
    http.SetCookie(w, &c)
}

func showMessage(w http.ResponseWriter, r *http.Request) {
    c, err := r.Cookie("flash")
    if err != nil {
        if err == http.ErrNoCookie {
            fmt.Fprintln(w, "No message found")
        }
    } else {
        rc := http.Cookie{
            Name: "flash",
            MaxAge: -1,
            Expires: time.Unix(1, 0),
        }
        http.SetCookie(w, &rc)
        val, _ := base64.URLEncoding.DecodeString(c.Value)
        fmt.Fprintln(w, string(val))
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章