什么是request
http消息分为request(请求) 和 response(响应)
request:在go中是一个struct,代表了客户段发送的http请求,已可以通过request 的方法访问请求中的cookie、URL、User Agent,查询字符串等信息。
Request Header
请求和响应的headers是通过Header来描述的,它是一个map,用来表示Http Header里的Key-Value.
获取Header
request.Header:获取整个haeder的map信息
request.Header["{key}"] :获取header中的指定key的value的切片
request.Header.Get("{key}") :返回获取header中的指定key的value字符传,多个值以逗号分隔
import (
"fmt"
"net/http"
)
func main() {
server := http.Server{
Addr: "localhost:8080",
}
http.HandleFunc("/test", func(writer http.ResponseWriter, request *http.Request) {
fmt.Println(request.Header)
fmt.Println(request.Header["Accept-Encoding"])
fmt.Println(request.Header.Get("Accept-Encoding"))
})
server.ListenAndServe()
}
处理请求参数
get请求处理
request.URL.RawQuery:获取参数字符串。 request.URL.Query():获取请求参数字符串对应的map[String][]String,值为切片的原因是key有可能重复。 request.URL.Query("{key}"):获取对应请求参数的第一个值。
package main
import (
"fmt"
"net/http"
)
func main() {
server := http.Server{
Addr: "localhost:8080",
}
http.HandleFunc("/test", func(writer http.ResponseWriter, request *http.Request) {
//request.URL.RawQuery:获取参数字符串
query := request.URL.RawQuery
fmt.Println(query)
//request.URL.Query():获取请求参数字符串对应的map[String][]String,值为切片的原因是key有可能重复
values := request.URL.Query()
fmt.Println(values)
//request.URL.Query("{key}"):获取对应请求参数的第一个值
get := request.URL.Query().Get("name")
fmt.Println(get)
writer.Write([]byte("请求成功"))
})
server.ListenAndServe()
}
form表单请求处理
请求包含的内容
html表单中的数据会以name-value对的形式,如果通过get请求,数据通过url的name-value来发送,如果post请求发送,数据内容放在post请求的body中,name-value数据格式可以通过表单的Content Type指定,也就是enctype
enctype的值如下:
- application/x-www-form-urlencoded:默认值,表单数据编码到请求字符串里面,适用于文本请求
- multipart/form-data:每一对name-value都会转换为MIME消息部分,每一部分都有自己的Content Type 和Content Disposition,适用大量数据,例如上传文件
- text/plain:html5浏览器需要支持的内容
不同请求对应的处理
Request允许我们从URL或/和Body中提取请求数据,先调用ParseForm 或者 parseMultipartForm 解析Request,然后在访问相应的Form、PostForm、MultipartForm获取数据
<html>
<title>测试表单请求</title>
<body>
<form action="http://localhost:8080/test?first_name=urlData" method="post" enctype="application/x-www-form-urlencoded">
<input type="text" name="first_name" />
<br />
<input type="text" name="last_name" />
<br />
<input type="submit" value="提交"/>
</form>
</body>
</html>
package main
import (
"fmt"
"net/http"
)
func main() {
server := http.Server{
Addr: "localhost:8080",
}
http.HandleFunc("/test", func(writer http.ResponseWriter, request *http.Request) {
//先调用 request.ParseForm 解析request,再获取from数据-request.Form/request.PostForm
request.ParseForm()
fmt.Fprintln(writer, request.Form)
fmt.Fprintln(writer, request.PostForm)
})
server.ListenAndServe()
}
第二行比第一行返回中少了url中first_name的值
Form:request.Form,返回map格式的参数信息,如果url中有和表单中相同的key,表单数据在前,url中数据在后
PostForm: request.PostForm,只获取表单中的数据
MultipartForm:对应from表单中的enctype = multipart/form-data需要先调用parseMultipartForm解析请求,会返回一个struct,struct有两个map,第一个map是from表单中的数据,第二个map是上传的文件。
<html>
<title>测试表单请求</title>
<body>
<form action="http://localhost:8080/test?first_name=urlData" method="post" enctype="multipart/form-data">
<input type="text" name="first_name" />
<br />
<input type="text" name="last_name" />
<br />
<input type="file" name="myFile"/>
<br />
<input type="submit" value="提交"/>
</form>
</body>
</html>
package main
import (
"fmt"
"net/http"
)
func main() {
server := http.Server{
Addr: "localhost:8080",
}
http.HandleFunc("/test", func(writer http.ResponseWriter, request *http.Request) {
request.ParseMultipartForm(1024)
fmt.Fprintln(writer, request.MultipartForm)
})
server.ListenAndServe()
}
FormValue:获取form字段中指定的key对应的第一个。 valuePostFormValue:获取form字段中指定的key对应的第一个value,只能获取到form表单中的值 FormValue 和 PostFormValue无需在调用parseForm/ ParseMultipartForm
package main
import (
"fmt"
"net/http"
)
func main() {
server := http.Server{
Addr: "localhost:8080",
}
http.HandleFunc("/test", func(writer http.ResponseWriter, request *http.Request) {
v1 := request.FormValue("first_name")
v2 := request.FormValue("last_name")
v3 := request.PostFormValue("first_name")
v4 := request.PostFormValue("last_name")
fmt.Println(v1)
fmt.Println(v2)
fmt.Println(v3)
fmt.Println(v4)
})
server.ListenAndServe()
}
上传文件
1.请求的enctype应为"multipart/form-data"
2.解析request请求:request.ParseMultipartForm(1024)
3.获取文件:request.MultipartForm.File["myFile"][0]:myFile对应请求的file的key,[0]获取第一个文件
<html>
<title>测试表单请求</title>
<body>
<form action="http://localhost:8080/test?first_name=urlData" method="post" enctype="multipart/form-data">
<input type="text" name="first_name" />
<br />
<input type="text" name="last_name" />
<br />
<input type="file" name ="myFile"/>
<br />
<input type="submit" value="提交"/>
</form>
</body>
</html>
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
server := http.Server{
Addr: "localhost:8080",
}
http.HandleFunc("/test", func(writer http.ResponseWriter, request *http.Request) {
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.Println(string(data))
}
}
})
server.ListenAndServe()
}
Json请求
读取json
1.使用解码器:dec := json.NewDecoder(request.Body)
2.在解码器上进行解码:err := dec.Decode(&struct的实例)
写入json
使用编码器 enc := json.NewEncoder(writer)
编码:err = enc.Encode(struct的实例)
package main
import (
"encoding/json"
"fmt"
"net/http"
)
func main() {
server := http.Server{
Addr: "localhost:8080",
}
http.HandleFunc("/test", func(writer http.ResponseWriter, request *http.Request) {
// 读取json
// 1.解码
dec := json.NewDecoder(request.Body)
// 1.转换为结构体
company := Company{}
err := dec.Decode(&company)
//3.打印数据
if err == nil {
fmt.Println(company)
}
// 返回json
//1.获取编码器
enc := json.NewEncoder(writer)
//2.对struct编码
err = enc.Encode(company)
if err == nil {
//3.向请求输出json
writer.WriteHeader(http.StatusInternalServerError)
return
}
})
server.ListenAndServe()
}
/*
创建和json结构一致的 struct
{"id":1,"name":"xiaoqiang","country":"China"}
*/
type Company struct {
ID int `json:"id"`
Name string `json:"name"`
Country string `json:"country"`
}