对请求的处理

Go 语言的 net/http 包提供了一系列用于表示 HTTP 报文的结构,我们可以使用它

处理请求和发送相应,其中 Request 结构代表了客户端发送的请求报文,下面让我们看

一下 Request 结构体

获取请求 URL

Request 结构中的 URL 字段用于表示请求行中包含的 URL,改字段是一个指向

url.URL 结构的指针

Path 字段

注: 通过 r.URL.Path 只能得到 /hello

RawQuery 字段

注: 通过 r.URL.RawQuery 得到的是 username=admin&password=123456

获取请求头中的信息

通过 Request 结果中的 Header 字段用来获取请求头中的所有信息,Header 字段

的类型是 Header 类型,而 Header 类型是一个 map[string][]string,string 类型的 key,

string 切片类型的值。

获取请求头中的所有信息

  • r.Header

  • 得到的结果如下:

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:[zh-
CN,zh;q=0.9,en-US;q=0.8,en;q=0.7] Connection:[keep-alive] Upgrade-Insecure-
Requests:[1]]

获取请求头中的某个具体属性的值,如获取 Accept-Encoding 的值

  • 方式一:r.Header[“Accept-Encoding”]

    • 得到的是一个字符串切片
    • 结果[gzip, deflate, br]
  • 方式二:r.Header.Get(“Accept-Encoding”)

    • 得到的是字符串形式的值,多个值使用逗号分隔
    • 结果 gzip, deflate, br

获取请求体中的信息

请求和响应的主体都是有 Request 结构中的 Body 字段表示,这个字段的类型是

io.ReadCloser 接口,该接口包含了 Reader 接口和 Closer 接口,Reader 接口拥有 Read

方法,Closer 接口拥有 Close 方法

通过指定 method=”post”来发送一个 POST 请求

由于 GET 请求没有请求体,所以我们需要在 HTML 页面中创建一个 form 表单,通

过指定 method=”post”来发送一个 POST 请求

  • 表单
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<form
action="http://localhost:8080/getBody"
method="POST"
enctype="multipart/form-data"
>
用户名:<input type="text" name="username" /><br />
密码:<input type="password" name="password" /><br />
<input type="submit" />
</form>
</body>
</html>
  • 服务器处理请求的代码
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)
}
  • 在浏览器上显示的结果

    • 请求体中的内容是: username=hanzong&password=666666

获取请求参数

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

的请求参数以及 form 表单中提交的请求参数

Form 字段

  1. 类型是 url.Values 类型,Form 是解析好的表单数据,包括 URL 字段的 query

    参数和 POST 或 PUT 的表单数据。
  2. Form 字段只有在调用 Request 的 ParseForm 方法后才有效。在客户端,会忽

    略请求中的本字段而使用 Body 替代
  3. 获取表单中提交的请求参数(username 和 password)
  • 代码
func handler(w http.ResponseWriter, r *http.Request) {
//解析表单
r.ParseForm()
//获取请求参数
fmt.Fprintln(w, "请求参数为:", r.Form)
}
//注意:在执行 r.Form 之前一定要调用 ParseForm 方法
//结果
//请求参数为: map[password:[666666] username:[hanzong]]
  • d) 如果对 form 表单做一些修改,在 action 属性的 URL 后面也添加相同的请求参

    数,如下:
<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>

则执行结果如下:

请求参数为:map[username:[hanzong admin] password:[666666] pwd:[123456]]

  • 我们发现:表单中的请求参数 username 和 URL 中的请求参数

    username 都获取到了,而且表单中的请求参数的值排在 URL 请求参

    数值的前面
  • 如果此时我们只想获取表单中的请求参数该怎么办呢?那就需要使

    用 Request 结构中的 PostForm 字段

PostForm 字段

  1. 类型也是 url.Values 类型,用来获取表单中的请求参数
  • 将 r.Form 改为 r.PostForm 之后的代码
func handler(w http.ResponseWriter, r *http.Request) {
//解析表单
r.ParseForm()
//获取请求参数
fmt.Fprintln(w, "请求参数为:", r.PostForm)
}
  • 结果

请求参数为:map[username:[hanzong] password:[666666]]

  1. 但是 PostForm 字段只支持 application/x-www-form-urlencoded 编码,如果

    form 表单的 enctype 属性值为 multipart/form-data,那么使用 PostForm 字段

    无法获取表单中的数据,此时需要使用 MultipartForm 字段
  • 说明:form 表单的 enctype 属性的默认值是 application/x-www-form-

    urlencoded 编 码 , 实 现 上 传 文 件 时 需 要 讲 该 属 性 的 值 设 置 为

    multipart/form-data 编码格式

FormValue 方法和 e PostFormValue 方法

FormValue 方法

a) 可以通过 FormValue 方法快速地获取某一个请求参数,该方法调用之前

会自动调用 ParseMultipartForm 和 ParseForm 方法对表单进行解析

  • 代码
func handler(w http.ResponseWriter, r *http.Request) {
//获取请求参数
fmt.Fprintln(w, "请求参数username的值为:", r.FormValue("username"))
}
  • 结果

请求参数 username 的值为: hanzong

PostFormValue 方法

a) 可以通过 PostFormValue 方法快速地获取表单中的某一个请求参数,该

方法调用之前会自动调用 ParseMultipartForm 和 ParseForm 方法对表单

进行解析

  • 代码
func handler(w http.ResponseWriter, r *http.Request) {
//获取请求参数
fmt.Fprintln(w, "请求参数 username 的值为:", r.PostFormValue("username"))
}
  • 结果

请求参数 username 的值为: hanzong

MultipartForm 字段

为了取得 multipart/form-data 编码的表单数据,我们需要用到 Request 结构的

ParseMultipartForm 方法和 MultipartForm 字段,我们通常上传文件时会将 form 表单的

enctype 属性值设置为 multipart/form-data

  1. 表单
<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. 后台处理请求代码
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. 浏览器显示结果

&{map[username:[hanzong]] map[photo:[0xc042126000]]}

  • 结果中有两个映射,第一个映射映射的是用户名;第二个映射的值是一个地址

  • MuiltipartForm 字段的类型为 *multipart.Form,multipart 包下 Form 结构的指

    针类型

  • 打开上传的文件

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))
}
}
}

FormFile 方法

  • net/http 提供的 FormFile 方法可以快速的获取被上传的文件,但是只能处理上

    传一个文件的情况。

  • 代码

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))
}
}
}

给客户端响应

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

们来说一下如何使用 http.ResponseWriter 来给用户响应

给客户端响应一个字符串

  • 处理器中的代码
func handler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("你的请求我已经收到"))
}
  • 浏览器中的结果

    你的请求我已经收到
  • 响应报文中的内容
 HTTP/1.1 200 OK
Date: Fri, 10 Aug 2019 01:09:27 GMT
Content-Length: 27
Content-Type: text/plain; charset=utf-8
  1. 给客户端响应一个 HTML 页面
  2. 处理器中的代码
   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. 浏览器中的结果

    我是以网页的形式响应过来的!
  • 通过在浏览器中右键 → 查看网页代码发现确实是一个 html 页面
  1. 响应报文中的内容
   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. 处理器端代码

   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. 浏览器中的结果

    {"ID":1,"Username":"admin","Password":"123456"}
  2. 响应报文中的内容
   HTTP/1.1 200 OK
Content-Type: application/json
Date: Fri, 10 Aug 2018 01:58:02 GMT
Content-Length: 47
  1. 让客户端重定向

  2. 处理器端代码

   func handler(w http.ResponseWriter, r \*http.Request) {
//以下操作必须要在 WriteHeader 之前进行
w.Header().Set("Location", "https:www.baidu.com")
w.WriteHeader(302)
}
  1. 响应报文中的内容
    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

goweb- 对请求的处理的更多相关文章

  1. Kubernetes学习笔记(四):服务

    服务介绍 服务是一种为一组相同功能的pod提供单一不变接入点的资源.当服务存在时,他的IP和端口不会改变.客户端通过IP和端口建立连接,这些连接会被路由到任何一个pod上.如此,客户端不需要知道每个单 ...

  2. GoWeb开发_Iris框架讲解(二):Get、Post、Put等请求及数据返回格式

    数据请求方式的分类 所有的项目中使用的请求都遵循HTTP协议标准,HTTP协议经过了1.0和1.1两个版本的发展. HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法. HTTP ...

  3. go-web 获取get/post请求中的请求头和表单数据

    package main import ( "fmt" "net/http" ) func handler(w http.ResponseWriter, r * ...

  4. Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求

    上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...

  5. Android请求网络共通类——Hi_博客 Android App 开发笔记

    今天 ,来分享一下 ,一个博客App的开发过程,以前也没开发过这种类型App 的经验,求大神们轻点喷. 首先我们要创建一个Andriod 项目 因为要从网络请求数据所以我们先来一个请求网络的共通类. ...

  6. 重温Http协议--请求报文和响应报文

    http协议是位于应用层的协议,我们在日常浏览网页比如在导航网站请求百度首页的时候,会先通过http协议把请求做一个类似于编码的工作,发送给百度的服务器,然后在百度服务器响应请求时把相应的内容再通过h ...

  7. Taurus.MVC 2.2 开源发布:WebAPI 功能增强(请求跨域及Json转换)

    背景: 1:有用户反馈了关于跨域请求的问题. 2:有用户反馈了参数获取的问题. 3:JsonHelper的增强. 在综合上面的条件下,有了2.2版本的更新,也因此写了此文. 开源地址: https:/ ...

  8. nodejs之get/post请求的几种方式

    最近一段时间在学习前端向服务器发送数据和请求数据,下面总结了一下向服务器发送请求用get和post的几种不同请求方式: 1.用form表单的方法:(1)get方法 前端代码: <form act ...

  9. ajax异步请求

    做前端开发的朋友对于ajax异步更新一定印象深刻,作为刚入坑的小白,今天就和大家一起聊聊关于ajax异步请求的那点事.既然是ajax就少不了jQuery的知识,推荐大家访问www.w3school.c ...

  10. C# MVC 5 - 生命周期(应用程序生命周期&请求生命周期)

    本文是根据网上的文章总结的. 1.介绍 本文讨论ASP.Net MVC框架MVC的请求生命周期. MVC有两个生命周期,一为应用程序生命周期,二为请求生命周期. 2.应用程序生命周期 应用程序生命周期 ...

随机推荐

  1. C# 中的栈和堆

    程序运行时,它的数据必须存储在内存中.一个数据项需要多大的内存.存储在内存中的什么位置.以及如何存储都依赖于该数据项的类型. 运行中的程序使用两个内存区域来存储数据:栈和堆. 栈 栈是一个内存数组,是 ...

  2. 分布式事务之解决方案(XA和2PC)

    3. 分布式事务解决方案之2PC(两阶段提交) 针对不同的分布式场景业界常见的解决方案有2PC.TCC.可靠消息最终一致性.最大努力通知这几种. 3.1. 什么是2PC 2PC即两阶段提交协议,是将整 ...

  3. Linux CPU占用率监控工具

    关键词:top.perf.sar.ksar.mpstat.uptime.vmstat.pidstat.time.cpustat.munin.htop.glances.atop.nmon.pcp-gui ...

  4. Nginx+Tomcat8+Memcached实现负载均衡及session共享

    1> 基础环境 简易拓扑图: 2> 部署Tomcat [root@node01 ~]# ll -h ~ |egrep 'jdk|tomcat'-rw-r--r-- 1 root root ...

  5. 14集超详细视频教程,手把手教你用数据神器Hawk!

    沙漠君在闭关4个月后,终于把开源数据神器Hawk(详细介绍在这里)的文档和教学视频基本录制完毕, 并同步更新在有爱无广告二次元的B站! 教程总时间超过3个小时,覆盖了网页采集器,数据清洗,文件读写等方 ...

  6. css3 中的渐变

    虽说css3 都已经使用多年了,但是关于css3的渐变用的很少.今天遇见了,就学习了一下. 首先我们打开ps,新建一个画布,选择渐变工具,这个时候我们能够看到顶栏上面的渐变类型如下 第一个我们选中的是 ...

  7. ESP8266的RTOS版本ota在线升级基本流程及备忘

    ESP8266的ota升级由于涉及到不同的flash空间大小,以及新旧版本的不同,所以流程相对比较复杂.笔者这个倒腾的时间还是有一些的,不过,总归把事情解决了.下面记录一下基本的流程和遇到的问题. 还 ...

  8. 修改Android源码实现原生应用双开,应用多开

    1. 准备 把某系统双开的两个app的信息进行对比 1.1 目录的对比 1.1.1 data目录对比 原应用: /data/user/0/com.luoyesiqiu.crackme/files 被复 ...

  9. .net core百万设备连接服务和硬件需求测试

    随着物联网的普及,服务应用将面对大量物联设备处理:早期.NET在通讯上的处理能力一直给人的印像并不怎样,但net core经历过大量的优化后在各个模块的处理性能都有着比较出色的提升,针对网络方向的处理 ...

  10. .Net Core 项目发布到Linux - CentOS 7(二)用Supervisor守护netcore进程

    简介 supervisor可以保证程序崩溃后,可以重新把程序启动起来等相关功能. 安装 yum install -y supervisor 安装好后在/etc/会生成一个supervisord.con ...