更多Go内容请见: https://blog.csdn.net/weixin_39777626/article/details/85066750
请求和响应
Request结构
表示一个由客户端发送的HTTP请求报文,组成部分:
- URL字段
- Header字段
- Body字段
- Form字段、PostForm字段和MultipartForm字段
用户还可以对报文中的cookie、引用URL以及用户代理进行访问
请求URL
请求来源:
- 浏览器
- HTTP客户端库
- Angular客户端框架
请求首部
基本方法:
- 添加
- 删除
- 获取
- 设置
设置&添加
操作 | 构造 |
---|---|
设置 | 给定键的值先被设置成一个空白的字符串切片,然后切片中的第一个元素会被设置成给定的首部值 |
添加 | 给定的首部值会被添加到字符串切片已有元素的后面 |
package main
import (
"fmt"
"net/http"
)
func headers(w http.ResponseWriter, r *http.Request) {
h := r.Header
fmt.Fprintln(w, h)
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/headers", headers)
server.ListenAndServe()
}
请求主体
请求和响应的主体都由Request结构的Body字段表示,这个字段是一个io.Read Closer接口
- Reader接口(Read方法):接受一个字节切片为输入,返回被读取内容的字节数以及一个可选的错误作为结果
- Closer接口(Close方法):不接受任何参数,但会在出错时返回一个错误
package main
import (
"fmt"
"net/http"
)
func body(w http.ResponseWriter, r *http.Request) {
len := r.ContentLength
body := make([]byte, len)
r.Body.Read(body)
fmt.Fprintln(w, string(body))
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/body", body)
server.ListenAndServe()
}
终端发送Post请求
curl -id "first_name=sausheong&last_name=chang" 127.0.0.1:8080/body
Go与HTML表单
- <form>标签包含文本行、文本框、单选按钮、复选框、文件上传等HTML表单元素
- 编码格式化
- POST请求的形式发送至服务器
常见编码方式
- application/x-www-form-urlencoded(默认——简单的文本数据):不同键值对使用&;键值对中的键与值使用=
- multipart/form-data(大量数据——上传文件):表单中的数据将被转换成一条MIME报文
- text/plain
- Base64(以文本方式传递二进制数据)
使用Request结构的方法获取表单数据:
- 对请求进行语法分析:ParseForm方法、ParseMultipartForm方法
- 访问相应的字段:Form字段、PostForm字段、MultipartForm字段
package main
import (
"fmt"
"net/http"
)
func process(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
fmt.Fprintln(w, r.Form)
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/process", process)
server.ListenAndServe()
}
HTML表单——客户端
- 通过POST方法将表单发送至http://localhost:8080/process?hello=world&thread=123
- 通过enctype属性将表单的内容类型设置为application/x-www-form-urlencoded
- 将表单键值 hello=sau sheong 和 post=456 发送至服务器
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Go Web Programming</title>
</head>
<body>
<form action=http://127.0.0.1:8080/process?hello=world&thread=123 method="post" enctype="application/x-www-form-urlencoded">
<input type="text" name="hello" value="sua sheong"/>
<input type="text" name="post" value="456"/>
<input type="submit"/>
</form>
</body>
</html>
字段 | 需调用或返回的方法、字段 | 键值对来源 | 内容类型 |
---|---|---|---|
Form | ParseForm方法 | 表单值+URL值 | URL编码 |
PostForm | Form字段 | 表单值 | URL编码 |
MultipartForm | ParseMultipartForm方法 | 表单值 | Multipart编码 |
FormValue | 表单值+URL值 | URL编码 | |
PostFormValue | 表单值 | URL编码 |
文件
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Go Web Programming</title>
</head>
<body>
<form action="http://localhost:8080/process?hello=world&thread=123" method="post" enctype="multipart/form-data">
<input type="text" name="hello" value="sau sheong" />
<input type="text" name="post" value="456" />
<input type="file" name="uploaded">
<input type="submit">
</form>
</body>
</html>
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func process(w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(1024)
fileHeader := r.MultipartForm.File["uploaded"][0]
file, err := fileHeader.Open()
if err == nil {
data, err := ioutil.ReadAll(file)
if err == nil {
fmt.Fprintln(w, string(data))
}
}
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/process", process)
server.ListenAndServe()
}
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func process(w http.ResponseWriter, r *http.Request) {
file, _, err := r.FormFile("uploaded")
if err == nil {
data, err := ioutil.ReadAll(file)
if err == nil {
fmt.Fprintln(w, string(data))
}
}
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/process", process)
server.ListenAndServe()
}
处理带有JSON主体的POST请求
ResponseWriter——接口
方法:
- Writer
- WriterHeader
- Header
对ResponseWriter进行写入
使用Write方法向客户端发送响应
package main
import (
"net/http"
)
func writeExample(w http.ResponseWriter, r *http.Request) {
str := `<html>
<head><title>Go Web Programming</title></head>
<body><h1>Hello World</h1></body>
</html>`
w.Write([]byte(str))
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/write", writeExample)
server.ListenAndServe()
}
curl -i 127.0.0.1:8080/write
通过WriteHeader方法将状态码写入响应当中
package main
import (
"fmt"
"net/http"
)
func writeExample(w http.ResponseWriter, r *http.Request) {
str := `<html>
<head><title>Go Web Programming</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 main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/write", writeExample)
http.HandleFunc("/writeheader", writeHeaderExample)
server.ListenAndServe()
}
curl -i 127.0.0.1:8080/writeheader
通过编写首部实现客户端重定向
package main
import (
"fmt"
"net/http"
)
func writeExample(w http.ResponseWriter, r *http.Request) {
str := `<html>
<head><title>Go Web Programming</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://google.com")
w.WriteHeader(302)
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/write", writeExample)
http.HandleFunc("/writeheader", writeHeaderExample)
http.HandleFunc("/redirect", headerExample)
server.ListenAndServe()
}
curl -i 127.0.0.1:8080/redirect
编写JSON输出
package main
import (
"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 Web Programming</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://google.com")
w.WriteHeader(302)
}
func jsonExample(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
post := &Post{
User: "Sau Sheong",
Threads: []string{"first", "second", "third"},
}
json, _ := json.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()
}
curl -i 127.0.0.1:8080/json
cookie
- 存储在客户端的、体积较小的信息
- 由服务器通过HTTP响应报文发送
Cookie结构
type Cookie struct{
Name string
Value string
Path string
Domain string
Expires time.Time
RawExpires string
MaxAge int
Secure bool
HttpOnly bool
Raw string
Unparsed []string
}
Go与cookie
将cookie发送至浏览器
String方法:返回一个经过序列化处理的cookie,Set-Cookie响应的首部的值就是由这些序列化之后的cookie组成的。
向浏览器发送cookie
package main
import (
"net/http"
)
func setCookie(w http.ResponseWriter, r *http.Request) {
c1 := http.Cookie{
Name: "first_cookie",
Value: "Go Web Programming",
HttpOnly: true,
}
c2 := http.Cookie{
Name: "second_cookie",
Value: "Manning Publications Co",
HttpOnly: true,
}
w.Header().Set("Set-Cookie", c1.String())
w.Header().Add("Set-Cookie", c2.String())
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/set_cookie", setCookie)
server.ListenAndServe()
}
代码运行成功后,
- 打开浏览器访问 http://127.0.0.1:8080/set_cookie
- 按 F12 键
- 按 F5 键
- 点击 Network>>set_cookie>>Cookies ,就能看到如下cookie
使用SetCookie方法设置cookie
package main
import (
"net/http"
)
func setCookie(w http.ResponseWriter, r *http.Request) {
c1 := http.Cookie{
Name: "first_cookie",
Value: "Go Web Programming",
HttpOnly: true,
}
c2 := http.Cookie{
Name: "second_cookie",
Value: "Manning Publications Co",
HttpOnly: true,
}
http.SetCookie(w, &c1)
http.SetCookie(w, &c2)
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/set_cookie", setCookie)
server.ListenAndServe()
}
从浏览器里面提取cookie
从请求的首部获取cookie
package main
import (
"fmt"
"net/http"
)
func setCookie(w http.ResponseWriter, r *http.Request) {
c1 := http.Cookie{
Name: "first_cookie",
Value: "Go Web Programming",
HttpOnly: true,
}
c2 := http.Cookie{
Name: "second_cookie",
Value: "Manning Publications Co",
HttpOnly: true,
}
http.SetCookie(w, &c1)
http.SetCookie(w, &c2)
}
func getCookie(w http.ResponseWriter, r *http.Request) {
h := r.Header["Cookie"]
fmt.Fprintln(w, h)
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/set_cookie", setCookie)
http.HandleFunc("/get_cookie", getCookie)
server.ListenAndServe()
}
使用Cookie方法获取cookie
package main
import (
"fmt"
"net/http"
)
func setCookie(w http.ResponseWriter, r *http.Request) {
c1 := http.Cookie{
Name: "first_cookie",
Value: "Go Web Programming",
HttpOnly: true,
}
c2 := http.Cookie{
Name: "second_cookie",
Value: "Manning Publications Co",
HttpOnly: true,
}
http.SetCookie(w, &c1)
http.SetCookie(w, &c2)
}
func getCookie(w http.ResponseWriter, r *http.Request) {
c1, err := r.Cookie("first_cookie")
if err != nil {
fmt.Fprintln(w, "Cannot get the first cookie")
}
cs := r.Cookies()
fmt.Fprintln(w, c1)
fmt.Fprintln(w, cs)
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/set_cookie", setCookie)
http.HandleFunc("/get_cookie", getCookie)
server.ListenAndServe()
}
使用cookie实现闪现消息
闪现消息:在某个条件被满足时,在页面上临时出现的消息
实现原理:把消息存储在页面刷新时就会被移除的会话cookie里
package main
import (
"encoding/base64"
"fmt"
"net/http"
"time"
)
func setMessage(w http.ResponseWriter, r *http.Request) {
msg := []byte("Hello World!")
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))
}
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
}
http.HandleFunc("/set_message", setMessage)
http.HandleFunc("/show_message", showMessage)
server.ListenAndServe()
}
更多Go内容请见: https://blog.csdn.net/weixin_39777626/article/details/85066750