A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 小蜀哥哥 黑马粉丝团   /  2019-12-12 13:11  /  1260 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

Request结构

Request结构主要由以下部分组成
URL字段
Header字段
Body字段
Form字段、PostForm字段和MultipartForm字段
[HTML] 纯文本查看 复制代码
type Request struct {

	Method string

	URL *url.URL

	Proto      string // "HTTP/1.0"

	ProtoMajor int    // 1

	ProtoMinor int    // 0

	Header Header

	Body io.ReadCloser

	GetBody func() (io.ReadCloser, error)

	ContentLength int64

	TransferEncoding []string

	Close bool

	Host string

	Form url.Values

	PostForm url.Values

	MultipartForm *multipart.Form

	Trailer Header

	RemoteAddr string

	RequestURI string

	TLS *tls.ConnectionState

	Cancel <-chan struct{}

	Response *Response

	ctx context.Context

}

请求URL

Request结构中的URL字段用于表示请求行中包含的URL

[JavaScript] 纯文本查看 复制代码
type URL struct {

	Scheme     string

	Opaque     string    // encoded opaque data

	User       *Userinfo // username and password information

	Host       string    // host or host:port

	Path       string    // path (relative paths may omit leading slash)

	RawPath    string    // encoded path hint (see EscapedPath method)

	ForceQuery bool      // append a query ('?') even if RawQuery is empty

	RawQuery   string    // encoded query values, without '?'

	Fragment   string    // fragment for references, without '#'

}

URL的一般格式:[scheme:][//[userinfo@]host][/]path[?query][#fragment]



客户端通过URL的查询参数向服务器传递信息,而URL结构的RawQuery字段记录的就是客户端向服务器传递的查询参数字符串。如:http://www.example.com/post?id=1234&name=chen ,则RawQuery字段的值存储的就是id=1234&name=chen ,要想获取键值对格式的查询参数,要对RawQuery值进行语法分析,但是使用Request结构的Form字段,系统提供了解析RawQuery的方法,将解析的键值对信息会存储在Form字段中。下面会主要会对Request结构的Form字段、PostForm字段和MultipartForm字段进行讲解。

请求首部

http.Header类型拥有4中基本方法,这些方法根据给定的键执行添加、删除、获取和设置等操作。
[JavaScript] 纯文本查看 复制代码
import (

	"net/http"

	"fmt"

)

 

func headers(w http.ResponseWriter,r *http.Request)  {

	r.ParseForm()

	h := r.Header

	fmt.Println(r.Header.Get("Accept-Encoding"))  //gzip, deflate

	fmt.Println(r.Header["Accept-Encoding"])   //[gzip, deflate]

	fmt.Fprintln(w,h) 

}

 

func main() {

	http.HandleFunc("/headers",headers)

	http.ListenAndServe(":8080",nil)

}

r.Header.Get("Accept-Encoding")是通过Header类型的Get方法获取的头信息,其返回的就是字符串形式的首部值,而r.Header["Accept-Encoding"]是以切片的形式返回的。

请求主体

请求和响应的主体都是由Request结构的Body字段表示,该字段是一个io.ReadCloser接口。
[JavaScript] 纯文本查看 复制代码
import (

	"net/http"

	"fmt"

)

 

func body(w http.ResponseWriter,r *http.Request)  {

	bys := make([]byte,r.ContentLength)

	r.Body.Read(bys)

	w.Write(bys)

}

 

func main() {

	http.HandleFunc("/body",body)

	http.ListenAndServe(":8080",nil)

}



通过ContentLength表示的是主体数据的字节长度,根据该长度创建字节切片,在通过Read方法将主体数据读取到字节切片中。因为GET请求不包含报文主体,所以使用的是POST表单请求。
Go语言提供了诸如FormValue和FormFile这种的方法来提取通过POST方法提交的表单,所以用户一般不需要自行读取主体中未经处理的表单,以下讲解FormValue和FormFile等方法。

Go与HTML表单

HTML表单的内容类型(Content-Type)决定了POST请求在发送键值对时将使用何种格式,其中,表单的enctype(也就是Content-Type)属性指定的值可以是application/x-www-form-urlencoded和multipart/form-data等。如果enctype属性的值设置为application/x-www-form-urlencoded,那么表单中的数据编码为一个连续的“长查询字符串”,这种编码和URL编码是一样的,如:id=1234&name=chen。如enctype属性的值设置为multipart/form-data,那么表单中的数据将被转换为一条MIME报文,表单中的每个键值对都构成了这条报文的一部分,并且每个键值对都带有它们各自的内容类型以及内容配置。以下是使用multipart/form-data编码对表单数据进行格式化的例子:

----------------------------780741602912379251409253
Content-Disposition: form-data; name="id"

123
----------------------------780741602912379251409253
Content-Disposition: form-data; name="name"

chen
----------------------------780741602912379251409253--


那么application/x-www-form-urlencoded和multipart/form-data两种编码应该如何选择呢,如果表单传送的简单的文本数据,那么使用URL编码格式更好,因为这种编码更为简单、高效,并且它所需的计算量要比另一种编码少,如果表单需要传送大量数据(如上传文件),那么使用multipart/form-data编码格式会更好一些。

Form字段

前面提到了如果直接获取请求体数据,需要自行进行语法分析,解析出键值对数据,而net/http库已经提供了一套用途相当广泛的函数,这些函数一般都能够满足用户对数据提取方面的需求,所以我们很少需要自行对表单数据进行语法分析。
通过调用Request结构提供的方法,用户可以将URL、主体又或者以上两者记录的数据提取到该结构的Form、PostForm和MultipartForm等字段当中。跟我们平常通过POST请求获取到的数据一样,存储在这些字段里面的数据也是以键值对形式表示的。使用Request结构的方法获取表单数据的一般步骤是:
(1)调用ParseForm()方法或者ParseMultipartForm()方法,对请求进行语法分析。
(2)根据步骤1调用的方法,访问相应的Form字段、PostForm字段或MultipartForm字段。
使用ParseForm()方法对表单进行语法分析的例子:

[JavaScript] 纯文本查看 复制代码
import (

	"net/http"

	"fmt"

)

 

func process(w http.ResponseWriter,r *http.Request)  {

	fmt.Println(r.Form)  //map[]

	r.ParseForm()

	fmt.Println(r.Form)  //map[id:[123] name:[chen hello world] hello:[world]]

	fmt.Fprint(w,r.Form)

}

 

func main() {

	http.HandleFunc("/process",process)

	http.ListenAndServe(":8080",nil)

}


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马