請求和響應
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結構獲取表單數據的一般步驟是:
- 調用ParseForm或者ParseMultipartForm方法進行語法分析
- 訪問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()
}
cookie
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))
}
}