golang源码解读之http.response

本文探讨了HTTP响应的结构,包括状态行、消息报头和响应正文,并详细解析了Go语言中`http.Response`结构体,介绍如何读取响应、获取Cookie、Location及设置无缓存。此外,还讨论了在实际项目中如何处理和分析响应结果的结构体。
摘要由CSDN通过智能技术生成

关于response
在接收和解释请求消息后,服务器会返回一个 HTTP 响应消息,与 HTTP 请求类似,HTTP 响应也是由三个部分组成,分别是:状态行、消息报头和响应正文

代码解析
Response 结构体
Response表示来自HTTP请求的响应。 一旦收到响应头,客户机和传输将从服务器返回响应。 响应主体在读取主体字段时按需流式传输

type Response struct {
   
	Status     string // e.g. "200 OK"
	StatusCode int    // e.g. 200
	Proto      string // e.g. "HTTP/1.0"
	ProtoMajor int    // e.g. 1
	ProtoMinor int    // e.g. 0

	// Header将头键映射到值。
	//如果响应有多个具有相同密钥的头,则可以使用逗号限制将它们串联起来。
	//当此结构中的其他字段(如ContentLength、transferncode、Trailer)复制头值时,字段值是权威的。
	Header Header

	// Body代表响应体。
	//响应主体在读取主体字段时按需流式传输。
	//如果网络连接失败或服务器终止响应,Body.Read调用返回错误,http客户机和传输保证Body始终为非nil, 关闭响应体时调用者的责任
	// 如果响应体未读到完成并关闭,则默认HTTP客户端的传输可能不会重用HTTP/1.x“keep alive”TCP连接
	// 如果服务器用“chunked”传输编码答复,则响应体将自动取消dechunked
	Body io.ReadCloser

	// ContentLength记录关联内容的长度。值>=0表示可以从Body读取给定的字节数。
	ContentLength int64

	// 包含从最外层到最内层的传输编码。值为nil,表示使用“identity”编码。
	TransferEncoding []string

	//Close记录响应头是否指示在读取Body之后关闭连接(是为客户提供建议)
	Close bool

	// 报告响应是否已压缩发送,但已由http包解压缩
	// 如果为true,则从Body读取生成未压缩的内容,而不是从服务器实际设置的压缩内容,ContentLength设置为-1,并且从responseHeader中删除“content Length”和“content Encoding”字段
	// 一般是压缩方式,利用gzip压缩文档能够显著地减少HTML文档的下载时间。
	Uncompressed bool

	// 将Trailer 键映射到与标头相同格式的值,初始是nil,服务器的Trailer头值中,指定的每个键对应一个值
	Trailer Header

	// Request 请求是为获取此响应而发送的请求。请求的主体为零(已被消耗)这仅为客户端请求填充
	Request *Request

	// TLS包含有关接收响应的TLS连接的信息
	TLS *tls.ConnectionState
}

将响应对象 写入(入参)写入器

func (r *Response) Write(w io.Writer) error {
   
	// 状态行
	text := r.Status
	if text == "" {
   
		var ok bool
		text, ok = statusText[r.StatusCode]
		if !ok {
   
			text = "status code " + strconv.Itoa(r.StatusCode)
		}
	} else {
   
		// 为了减少stutter, 如果用户设置响应码为2000 ok, 状态码为200
		text = strings.TrimPrefix(text, strconv.Itoa(r.StatusCode)+" ")
	}

	if _, err := fmt.Fprintf(w, "HTTP/%d.%d %03d %s\r\n", r.ProtoMajor, r.ProtoMinor, r.StatusCode, text); err != nil {
   
		return err
	}

	// 克隆r,这样我们可以根据需要修改r1
	r1 := new(Response)
	*r1 = *r
	if r1.ContentLength == 0 && r1.Body != nil {
   
		// Is it actually 0 length? Or just unknown?
		var buf [1]byte
		n, err := r1.Body.Read(buf[:])
		if err != nil && err != io.EOF {
   
			return err
		}
		if n == 0 {
   
			// 将其重置为已知的零读取器,以防重复读取底层读取器
			r1.Body = NoBody
		}<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值