处理请求

更多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表单

  1. <form>标签包含文本行、文本框、单选按钮、复选框、文件上传等HTML表单元素
  2. 编码格式化
  3. POST请求的形式发送至服务器

常见编码方式

  • application/x-www-form-urlencoded(默认——简单的文本数据):不同键值对使用&;键值对中的键与值使用=
  • multipart/form-data(大量数据——上传文件):表单中的数据将被转换成一条MIME报文
  • text/plain
  • Base64(以文本方式传递二进制数据)

使用Request结构的方法获取表单数据:

  1. 对请求进行语法分析:ParseForm方法、ParseMultipartForm方法
  2. 访问相应的字段: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>
字段需调用或返回的方法、字段键值对来源内容类型
FormParseForm方法表单值+URL值URL编码
PostFormForm字段表单值URL编码
MultipartFormParseMultipartForm方法表单值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()
}

代码运行成功后,

  1. 打开浏览器访问 http://127.0.0.1:8080/set_cookie
  2. 按 F12 键
  3. 按 F5 键
  4. 点击 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值