前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >GO-处理请求

GO-处理请求

作者头像
cwl_java
发布2020-04-08 15:21:02
6660
发布2020-04-08 15:21:02
举报
文章被收录于专栏:cwl_Java

第 5 章:处理请求

Go 语言的 net/http 包提供了一系列用于表示 HTTP 报文的结构,我们可以使用它处理请求和发送相应,其中 Request 结构代表了客户端发送的请求报文,下面让我们看一下 Request 结构体

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.1 获取请求 URL

Request 结构中的 URL 字段用于表示请求行中包含的 URL,改字段是一个指向url.URL 结构的指针,让我们来看一下 URL 结构

在这里插入图片描述
在这里插入图片描述
  1. Path 字段、
  • 获取请求的 URL
  • 例如:http://localhost:8080/hello?username=admin&password=123456
    • 通过 r.URL.Path 只能得到 /hello
  1. RawQuery 字段
  • 获取请求的 URL 后面?后面的查询字符串\
  • 例如:http://localhost:8080/hello?username=admin&password=123456
    • 通过 r.URL.RawQuery 得到的是 username=admin&password=123456

5.2 获取请求头中的信息

通过 Request 结果中的 Header 字段用来获取请求头中的所有信息,Header 字段的类型是 Header 类型,而 Header 类型是一个 map[string][]string,string 类型的 key,string 切片类型的值。下面是 Header 类型及它的方法:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  1. 获取请求头中的所有信息
  • r.Header
  • 得到的结果如下:
代码语言:javascript
复制
map[User-Agent:[Mozilla/5.0 (Windows NT 10.0; Win64; x64) 
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36] 
Accept:[text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,ima
ge/apng,*/*;q=0.8] Accept-Encoding:[gzip, deflate, br] Accept-Language:[zhCN,zh;q=0.9,en-US;q=0.8,en;q=0.7] Connection:[keep-alive] Upgrade-InsecureRequests:[1]]
  1. 获取请求头中的某个具体属性的值,如获取 Accept-Encoding 的值
  • 方式一:r.Header[“Accept-Encoding”]
    • 得到的是一个字符串切片
    • 结果:[gzip, deflate, br]
  • 方式二:r.Header.Get(“Accept-Encoding”)
    • 得到的是字符串形式的值,多个值使用逗号分隔
    • 结果:gzip, deflate, br

5.3 获取请求体中的信息

请求和响应的主体都是有 Request 结构中的 Body 字段表示,这个字段的类型是io.ReadCloser 接口,该接口包含了 Reader 接口和 Closer 接口,Reader 接口拥有 Read方法,Closer 接口拥有 Close 方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  1. 由于 GET 请求没有请求体,所以我们需要在 HTML 页面中创建一个 form 表单,通过指定 method=”post”来发送一个 POST 请求 a) 表单
代码语言:javascript
复制
<form action="http://localhost:8080/getBody" method="POST">
	用户名:
	<input type="text" name="username" value="hanzong">
	<br/>
	密 码 :
	<input type="password" name="password" value="666666">
	<br/>
	<input type="submit">
</form>

b) 服务器处理请求的代码

代码语言:javascript
复制
package main
import (
	"fmt"
	"net/http"
)
func handler(w http.ResponseWriter, r * http.Request) {
	//获取内容的长度
	length: = r.ContentLength
	//创建一个字节切片
	body: = make([] byte, length)
	//读取请求体
	r.Body.Read(body)
	fmt.Fprintln(w, "请求体中的内容是:", string(body))
}
func main() {
	http.HandleFunc("/getBody", handler)
	http.ListenAndServe(":8080", nil)
}

c) 在浏览器上显示的结果

代码语言:javascript
复制
请求体中的内容是: username=hanzong&password=666666

5.4 获取请求参数

下面我们就通过 net/http 库中的 Request 结构的字段以及方法获取请求 URL 后面的请求参数以及 form 表单中提交的请求参数

5.4.1 Form 字段

  1. 类型是 url.Values 类型,Form 是解析好的表单数据,包括 URL 字段的 query参数和 POST 或 PUT 的表单数据。
在这里插入图片描述
在这里插入图片描述
  1. Form 字段只有在调用 Request 的 ParseForm 方法后才有效。在客户端,会忽略请求中的本字段而使用 Body 替代
在这里插入图片描述
在这里插入图片描述
  1. 获取 5.3 中的表单中提交的请求参数(username 和 password)
  • 代码
代码语言:javascript
复制
func handler(w http.ResponseWriter, r * http.Request) {
	//解析表单
	r.ParseForm()
	//获取请求参数
	fmt.Fprintln(w, "请求参数为:", r.Form)
}

注意:在执行 r.Form 之前一定要调用 ParseForm 方法

  • 结果
代码语言:javascript
复制
请求参数为: map[password:[666666] username:[hanzong]]

d) 如果对 form 表单做一些修改,在 action 属性的 URL 后面也添加相同的请求参数,如下:

代码语言:javascript
复制
<form action="http://localhost:8080/getBody?username=admin&pwd=123456"
method="POST">
	用 户 名 :
	<input type="text" name="username" value="hanzong">
	<br/>
	密码:
	<input type="password" name="password" value="666666">
	<br/>
	<input type="submit">
</form>
  • 则执行结果如下:
代码语言:javascript
复制
请求参数为:map[username:[hanzong admin] password:[666666] pwd:[123456]]
  • 我们发现:表单中的请求参数 username 和 URL 中的请求参数username 都获取到了,而且表单中的请求参数的值排在 URL 请求参数值的前面
  • 如果此时我们只想获取表单中的请求参数该怎么办呢?那就需要使用 Request 结构中的 PostForm 字段

5.4.2 PostForm 字段

  1. 类型也是 url.Values 类型,用来获取表单中的请求参数
  • 将 r.Form 改为 r.PostForm 之后的代码
代码语言:javascript
复制
func handler(w http.ResponseWriter, r * http.Request) {
	//解析表单
	r.ParseForm()
	//获取请求参数
	fmt.Fprintln(w, "请求参数为:", r.PostForm)
}
  • 结果
代码语言:javascript
复制
请求参数为: map[username:[hanzong] password:[666666]]
  1. 但是 PostForm 字段只支持 application/x-www-form-urlencoded 编码,如果form 表单的 enctype 属性值为 multipart/form-data,那么使用 PostForm 字段无法获取表单中的数据,此时需要使用 MultipartForm 字段
  • 说明:form 表单的 enctype 属性的默认值是 application/x-www-formurlencoded 编 码 , 实 现 上 传 文 件 时 需 要 讲 该 属 性 的 值 设 置 为multipart/form-data 编码格式
  1. FormValue 方法 a) 可以通过 FormValue 方法快速地获取某一个请求参数,该方法调用之前会自动调用 ParseMultipartForm 和 ParseForm 方法对表单进行解析
在这里插入图片描述
在这里插入图片描述
  • 代码
代码语言:javascript
复制
func handler(w http.ResponseWriter, r * http.Request) {
	//获取请求参数
	fmt.Fprintln(w, "请求参数username的值为:", r.FormValue("username"))
}
  • 结果
代码语言:javascript
复制
请求参数 username 的值为: hanzong
  1. PostFormValue 方法 a) 可以通过 PostFormValue 方法快速地获取表单中的某一个请求参数,该方法调用之前会自动调用 ParseMultipartForm 和 ParseForm 方法对表单进行解析
在这里插入图片描述
在这里插入图片描述
  • 代码
代码语言:javascript
复制
func handler(w http.ResponseWriter, r * http.Request) {
	//获取请求参数
	fmt.Fprintln(w, "请求参数 username 的值为:", r.PostFormValue("username"))
}
  • 结果:
代码语言:javascript
复制
请求参数 username 的值为: hanzong

5.4.4 MultipartForm 字段

为了取得 multipart/form-data 编码的表单数据,我们需要用到 Request 结构的ParseMultipartForm 方法和 MultipartForm 字段,我们通常上传文件时会将 form 表单的enctype 属性值设置为 multipart/form-data

在这里插入图片描述
在这里插入图片描述
  1. 表单
代码语言:javascript
复制
<form action="http://localhost:8080/upload" method="POST" enctype="multipart/form-data">
	用 户 名 :
	<input type="text" name="username" value="hanzong">
	<br/>
	文件:
	<input type="file" name="photo" />
	<br/>
	<input type="submit">
</form>
  1. 后台处理请求代码
代码语言:javascript
复制
package main
import (
	"fmt"
	"net/http"
)
func handler(w http.ResponseWriter, r * http.Request) {
	//解析表单
	r.ParseMultipartForm(1024)
	//打印表单数据
	fmt.Fprintln(w, r.MultipartForm)
}
func main() {
	http.HandleFunc("/upload", handler)
	http.ListenAndServe(":8080", nil)
}
  1. 浏览器显示结果
代码语言:javascript
复制
&{map[username:[hanzong]] map[photo:[0xc042126000]]}
  • 结果中有两个映射,第一个映射映射的是用户名;第二个映射的值是一个地址
  • MuiltipartForm 字段的类型为 *multipart.Form,multipart 包下 Form 结构的指针类型
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  • 打开上传的文件
代码语言:javascript
复制
func handler(w http.ResponseWriter, r * http.Request) {
	//解析表单
	r.ParseMultipartForm(1024)
	fileHeader: = r.MultipartForm.File["photo"][0]
	file, err: = fileHeader.Open()
	if err == nil {
		data,
		err: = ioutil.ReadAll(file)
		if err == nil {
			fmt.Fprintln(w, string(data))
		}
	}
}
  1. FormFile 方法
  • net/http 提供的 FormFile 方法可以快速的获取被上传的文件,但是只能处理上传一个文件的情况。
在这里插入图片描述
在这里插入图片描述
  • 代码
代码语言:javascript
复制
func handler(w http.ResponseWriter, r * http.Request) {
	file,
	_,
	err: = r.FormFile("photo")
	if err == nil {
		data,
		err: = ioutil.ReadAll(file) if err == nil {
			fmt.Fprintln(w, string(data))
		}
	}
}

5.5 给客户端响应

前面我们一直说的是如何使用处理器中的 *http.Request 处理用户的请求,下面我们来说一下如何使用 http.ResponseWriter 来给用户响应

在这里插入图片描述
在这里插入图片描述
  1. 给客户端响应一个字符串
  • 处理器中的代码
代码语言:javascript
复制
func handler(w http.ResponseWriter, r * http.Request) {
	w.Write([] byte("你的请求我已经收到"))
}
  • 浏览器中的结果
代码语言:javascript
复制
你的请求我已经收到
  • 响应报文中的内容
代码语言:javascript
复制
HTTP/1.1 200 OK
代码语言:javascript
复制
Date: Fri, 10 Aug 2018 01:09:27 GMT
Content-Length: 27
Content-Type: text/plain; charset=utf-8
  1. 给客户端响应一个 HTML 页面
  2. 处理器中的代码
代码语言:javascript
复制
func handler(w http.ResponseWriter, r * http.Request) {
	html: = `<html>
 <head>
 <title>测试响应内容为网页</title>
 <meta charset="utf-8"/>
 </head>
 <body>
 我是以网页的形式响应过来的!
 </body>
</html>`
	w.Write([] byte(html))
}
  1. 浏览器中的结果
代码语言:javascript
复制
我是以网页的形式响应过来的!
  • 通过在浏览器中右键→查看网页代码发现确实是一个 html 页面
  1. 响应报文中的内容
代码语言:javascript
复制
HTTP/1.1 200 OK
Date: Fri, 10 Aug 2018 01:26:58 GMT
Content-Length: 194
Content-Type: text/html; charset=utf-8
  1. 给客户端响应 JSON 格式的数据
  2. 处理器端代码
代码语言:javascript
复制
func handler(w http.ResponseWriter, r * http.Request) {
	//设置响应头中内容的类型
	w.Header().Set("Content-Type", "application/json")
	user: = User {
		ID: 1,
		Username: "admin",
		Password: "123456",
	}
	//将 user 转换为 json 格式
	json, _: = json.Marshal(user)
	w.Write(json)
}
  1. 浏览器中的结果
代码语言:javascript
复制
{"ID":1,"Username":"admin","Password":"123456"}
  1. 响应报文中的内容
代码语言:javascript
复制
HTTP/1.1 200 OK
Content-Type: application/json
Date: Fri, 10 Aug 2018 01:58:02 GMT
Content-Length: 47
  1. 让客户端重定向
  2. 处理器端代码
代码语言:javascript
复制
func handler(w http.ResponseWriter, r * http.Request) {
	//以下操作必须要在 WriteHeader 之前进行
	w.Header().Set("Location", "https:www.baidu.com")
	w.WriteHeader(302)
}
  1. 响应报文中的内容
代码语言:javascript
复制
HTTP/1.1 302 Found
Location: https:www.baidu.com
Date: Fri, 10 Aug 2018 01:45:04 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/04/06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第 5 章:处理请求
    • 5.1 获取请求 URL
      • 5.2 获取请求头中的信息
        • 5.3 获取请求体中的信息
          • 5.4 获取请求参数
            • 5.4.1 Form 字段
            • 5.4.2 PostForm 字段
            • 5.4.4 MultipartForm 字段
          • 5.5 给客户端响应
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档