前言
填坑…
Go 有一点比较要注意的就是大小写了。
先填一下 Go 语法的坑吧
把简单的手册读完,就这样吧,我读的是菜鸟教程 2333。
请求
请求 URL
request.URL 是个指向 url.URL 结构体的指针,而这个结构体中存放了请求 URL 相关的数据,比如 request.URL.Path。
请求头
请求头存放在 request.Header 中,遍历输出一下:
1 2 3
| for key, value := range request.Header { fmt.Fprintln(writer, key, ": ", value) }
|
大致就是这样:
1 2 3 4 5 6 7
| Accept : [text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8] Accept-Language : [zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3] Accept-Encoding : [gzip, deflate] Cookie : [csrftoken=J8qkz9Ebk6VDXsf4T1rkTmJ39T3uiOe0zD4j4tm9xOe5K8ATfcioJPu7sQKBGTPO] Connection : [keep-alive] Upgrade-Insecure-Requests : [1] User-Agent : [Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0]
|
可以使用 [] 或者 Get() 来取值。
请求 body
body 存放在 request.Body 中,是一个 io.ReadCloser 接口,同时包含了 reader 和 closer 接口,我们要获取 body 的内容就需要调用 Read 方法,从 Body 中读取固定长度的字节放进 make 方法创建的语言切片中:
1 2 3 4 5
| len := request.ContentLength body := make([]byte, len) request.Body.Read(body) request.Body.Close() fmt.Fprintf(writer, string(body))
|
可以得到未经过处理的 body,想要获取 POST 提交的表单还有内置的方法,不需要我们自己去解析。
1 2 3
| request.ParseForm() fmt.Fprintln(writer, request.Form["a"][0], request.Form["a"][1]) fmt.Fprintln(writer, request.Form)
|
这种方式不分 GET 和 POST,比如我们 GET 提交 a=456&a=0,POST 提交 a=123&b=abc&a=789,结果就是:
1 2
| 123 789 map[a:[123 789 456 0] b:[abc]]
|
它会将相同键值的合并到一起。
PostForm
如果只想要 POST 的数据,就使用 PostForm 方法:
1 2
| request.ParseForm() fmt.Fprintln(writer, request.PostForm)
|
结果就只剩下:
这种类型要自己写太麻烦了,所以整个简单的表单:
1 2 3 4 5
| <form action="http://***/register?myname=Twings" method="POST" enctype="multipart/form-data"> <input type="text" name="myname"> <input type="file" name="myfile"> <input type="submit"> </form>
|
然后:
1 2
| request.ParseMultipartForm(1024) fmt.Fprintln(writer, request.MultipartForm)
|
效果如下:
MultipartForm 只会接受 POST 的数据,而且文本数据和文件会分开放在两个 map 里面。
FormValue、Form、PostFormValue、PostForm
比较方便的取值方法,会自动解析 multipart/form-data 或者 application/x-www-form-urlencoded 编码方式的表单(1.12 版本的 go 中好像可以自动解析了)使用方式类似这样:
1
| fmt.Fprintln(writer, request.FormValue("myname"))
|
Form 会返回整个表单,而 FormValue 只会按顺序返回一个我们需要的键的值。
Form 会从 GET 和 POST 中取值。
感觉上来说,GET 的数据用多路复用器来获取比较好,POST 的可以用 PostFormValue。
文件上传
要引入 io/io.util 包,比较麻烦的方法,不过可以上传多个文件:
1 2 3 4 5 6 7 8 9
| request.ParseMultipartForm(1024) fileHeader := request.MultipartForm.File["myfile"][0] file, err := fileHeader.Open() if err == nil { data, err := ioutil.ReadAll(file) if err == nil { fmt.Fprintln(writer, string(data)) } }
|
比较简单的方法,类似 FormValue:
1 2 3 4 5 6 7
| file, _, err := request.FormFile("myfile") if err == nil { data, err := ioutil.ReadAll(file) if err == nil { fmt.Fprintln(writer, string(data)) } }
|
获取完文件还有别的操作,比如大小校验、文件类型校验、写入文件等等,这里留坑。
JSON
留个坑。
响应
ResponseWriter 接口有三种用来处理响应的方法:
- Write 用于处理响应主体
- WriteHeader 用于处理响应码
- Header 用于处理响应头
如下:
1 2 3 4 5 6 7 8 9 10 11
| html := `<html> <head> <title>Hello World!</title> </head> <body> <h1>Hello World!</h1> </body> </html>` writer.Header().Set("FLAG", "flag{0123456789}") writer.WriteHeader(233) writer.Write([]byte(html))
|
响应主体还是使用模板比较好一点啊。
Cookie
Go 的 Cookie 是一个结构体,要设置 Cookie 可以先设置一个 http.Cookie 结构体,然后用 Header 将 Cookie Set 到客户端:
1 2 3 4 5 6 7 8 9 10 11 12
| cookie1 := http.Cookie{ Name: "HINT1", Value: "FLAG is not here", HttpOnly: true, } cookie2 := http.Cookie{ Name: "HINT2", Value: "FLAG in db", HttpOnly: true, } writer.Header().Set("Set-Cookie", cookie1.String()) writer.Header().Add("Set-Cookie", cookie2.String())
|
用 Add 可以继续第二个 Cookie,或者使用 http.SetCookie:
1 2
| http.SetCookie(writer, &cookie1) http.SetCookie(writer, &cookie2)
|
Go 想要获取 Cookie 也有两种方法,一种是简单粗暴的 Header[“Cookie”] / Header.Get(“Cookie”),另一种比较简单,是内置的 request.Cookie 方法,Cookies 方法获得的则是全部 Cookie,得到的是一个指向 Cookie 结构体的指针:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| cookie1, err := request.Cookie("HINT1") if err != nil { if err == http.ErrNoCookie { fmt.Fprintln(writer, "No Cookie1") } } else { cookie2, err := request.Cookie("HINT2") if err != nil { if err == http.ErrNoCookie { fmt.Fprintln(writer, "No Cookie2") } } else { html := cookie1.Value + cookie2.Value writer.Write([]byte(html)) } }
|
Go 的 base64 编码,引入 encoding/base64 包,然后:
1
| base64.URLEncoding.EncodeToString()
|
Orz