「GO标准库」net/http 包的全面解析 :初识

前篇

net/http 包,作为 golang 最核心的一个标准库,核心知识点较多,所以咱们大致拆分为三部分:

  1. 原理篇
  2. Client 服务端篇
  3. Server 客户端篇

回顾:什么是 HTTP ?

超文本传输协议(Hypertext Transfer Protocol、HTTP 协议)是今天使用最广泛的应用层协议,1989 年由 Tim Berners-Lee 在 CERN 起草的协议已经成为了互联网的数据传输的核心。

在过去几年的时间里,HTTP/2 和 HTTP/3 也对现有的协议进行了更新,提供更加安全和快速的传输功能。

多数的编程语言都会在标准库中实现 HTTP/1.1 和 HTTP/2.0 已满足工程师的日常开发需求,今天要介绍的 Go 语言的网络库也实现了这两个大版本的 HTTP 协议。

HTTP 设计原理

HTTP 协议是应用层协议,在通常情况下我们都会使用 TCP 作为底层的传输层协议传输数据包,但是 HTTP/3 在 UDP 协议上实现了新的传输层协议 QUIC 并使用 QUIC 传输数据,这也意味着 HTTP 既可以跑在 TCP 上,也可以跑在 UDP 上。

HTTP 与传输层协议

Go 语言标准库通过 net/http 包提供 HTTP 的客户端和服务端实现,在分析内部的实现原理之前,我们先来了解一下 HTTP 协议相关的一些设计以及标准库内部的层级结构和模块之间的关系。

HTTP 协议中最常见的概念是 HTTP 请求与响应,我们可以将它们理解成客户端和服务端之间传递的消息,客户端向服务端发送 HTTP 请求,服务端收到 HTTP 请求后会做出计算后以 HTTP 响应的形式发送给客户端。

HTTP 实现的接口

  • http.RoundTripper 用来表示执行单个 HTTP 请求的接口,调用方将请求作为参数可以获取请求对应的响应
go 复制代码
// RoundTripper是一个接口,表示执行单个HTTP事务的能力,从而获得给定请求的响应。
// 
// RoundTripper对于多个goroutine的并发使用必须是安全的。
    
type RoundTripper interface {
    // RoundTrip 执行单个HTTP事务,返回对所提供请求的响应.
    // 
    // RoundTrip 不应试图解释响应。
    // 特别是,如果RoundTrip 获得响应,则无论响应的 HTTP 状态代码如何,都必须返回 err == nil。
    // 应为未能获得响应保留非零错误。
    // 同样,RoundTrip 不应试图处理更高级别的协议细节,如重定向、身份验证或 cookie 。
    // 
    // RoundTrip 不应修改请求,除非消耗和关闭请求的正文。
    // RoundTrip 可以在单独的 goroutine 中读取请求的字段。
    // 在关闭响应的正文之前,调用者不应更改或重复使用请求。

    // RoundTrip 必须始终关闭主体,
    // 包括出现错误时,但根据实现情况,即使在 RoundTrip 返回后,也可以在单独的 goroutine 中关闭主体。
    // 这意味着,想要在后续请求中重用正文的调用者必须安排等待 Close 调用,然后才能这样做。
    //
    // 必须初始化请求的URL和标题字段。
    
    RoundTrip(*Request) (*Response, error)
}
go 复制代码
// 处理程序响应HTTP请求。
//
// ServeHTTP 应该将回复头和数据写入 ResponseWriter,然后返回请求已完成的信号。
// 在完成 ServeHTTP 调用之后或同时使用 ResponseWriter 或从 Request.Body 读取是无效的。
//
// 根据 HTTP 客户端软件、HTTP 协议版本以及客户端和 Go 服务器之间的任何中介
// 在写入 ResponseWriter 后可能无法读取 Request.Body。
// 谨慎的处理程序应该先阅读 Request.Body,然后再回复。
//
// 除了读取正文之外,处理程序不应修改所提供的 Request。
//
// 如果 ServeHTTP 死机,服务器( ServeHTTP 的调用方)会认为死机的影响与活动请求无关。
// 它恢复死机,将堆栈跟踪记录到服务器错误日志中,并根据HTTP协议关闭网络连接或发送 HTTP/2 RST_STREAM。
// 要中止处理程序,以便客户端看到中断的响应,但服务器没有记录错误,请使用值 ErrArtrtHandler 进行死机。

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}
go 复制代码
// A ResponseWriter interface is used by an HTTP handler to
// construct an HTTP response.
//
// A ResponseWriter may not be used after the Handler.ServeHTTP method
// has returned.
type ResponseWriter interface {
    // Header returns the header map that will be sent by
    // WriteHeader. The Header map also is the mechanism with which
    // Handlers can set HTTP trailers.
    //
    // Changing the header map after a call to WriteHeader (or
    // Write) has no effect unless the HTTP status code was of the
    // 1xx class or the modified headers are trailers.
    //
    // There are two ways to set Trailers. The preferred way is to
    // predeclare in the headers which trailers you will later
    // send by setting the "Trailer" header to the names of the
    // trailer keys which will come later. In this case, those
    // keys of the Header map are treated as if they were
    // trailers. See the example. The second way, for trailer
    // keys not known to the Handler until after the first Write,
    // is to prefix the Header map keys with the TrailerPrefix
    // constant value. See TrailerPrefix.
    //
    // To suppress automatic response headers (such as "Date"), set
    // their value to nil.
    Header() Header

    // Write writes the data to the connection as part of an HTTP reply.
    //
    // If WriteHeader has not yet been called, Write calls
    // WriteHeader(http.StatusOK) before writing the data. If the Header
    // does not contain a Content-Type line, Write adds a Content-Type set
    // to the result of passing the initial 512 bytes of written data to
    // DetectContentType. Additionally, if the total size of all written
    // data is under a few KB and there are no Flush calls, the
    // Content-Length header is added automatically.
    //
    // Depending on the HTTP protocol version and the client, calling
    // Write or WriteHeader may prevent future reads on the
    // Request.Body. For HTTP/1.x requests, handlers should read any
    // needed request body data before writing the response. Once the
    // headers have been flushed (due to either an explicit Flusher.Flush
    // call or writing enough data to trigger a flush), the request body
    // may be unavailable. For HTTP/2 requests, the Go HTTP server permits
    // handlers to continue to read the request body while concurrently
    // writing the response. However, such behavior may not be supported
    // by all HTTP/2 clients. Handlers should read before writing if
    // possible to maximize compatibility.
    Write([]byte) (int, error)

    // WriteHeader sends an HTTP response header with the provided
    // status code.
    //
    // If WriteHeader is not called explicitly, the first call to Write
    // will trigger an implicit WriteHeader(http.StatusOK).
    // Thus explicit calls to WriteHeader are mainly used to
    // send error codes or 1xx informational responses.
    //
    // The provided code must be a valid HTTP 1xx-5xx status code.
    // Any number of 1xx headers may be written, followed by at most
    // one 2xx-5xx header. 1xx headers are sent immediately, but 2xx-5xx
    // headers may be buffered. Use the Flusher interface to send
    // buffered data. The header map is cleared when 2xx-5xx headers are
    // sent, but not with 1xx headers.
    //
    // The server will automatically send a 100 (Continue) header
    // on the first read from the request body if the request has
    // an "Expect: 100-continue" header.
    WriteHeader(statusCode int)
}

它提供的三个接口 HeaderWriteWriteHeader 分别会获取 HTTP 响应、将数据写入负载以及写入响应头

结束语

主要讲解了 HTTP 的定义,传输协议,设计原理,net/http 两大核心接口。

相关推荐
uzong10 分钟前
软件架构指南 Software Architecture Guide
后端
又是忙碌的一天10 分钟前
SpringBoot 创建及登录、拦截器
java·spring boot·后端
勇哥java实战分享1 小时前
短信平台 Pro 版本 ,比开源版本更强大
后端
学历真的很重要1 小时前
LangChain V1.0 Context Engineering(上下文工程)详细指南
人工智能·后端·学习·语言模型·面试·职场和发展·langchain
计算机毕设VX:Fegn08951 小时前
计算机毕业设计|基于springboot + vue二手家电管理系统(源码+数据库+文档)
vue.js·spring boot·后端·课程设计
上进小菜猪2 小时前
基于 YOLOv8 的智能杂草检测识别实战 [目标检测完整源码]
后端
韩师傅2 小时前
前端开发消亡史:AI也无法掩盖没有设计创造力的真相
前端·人工智能·后端
ps酷教程3 小时前
HttpPostRequestDecoder源码浅析
java·http·netty
栈与堆3 小时前
LeetCode-1-两数之和
java·数据结构·后端·python·算法·leetcode·rust
superman超哥3 小时前
双端迭代器(DoubleEndedIterator):Rust双向遍历的优雅实现
开发语言·后端·rust·双端迭代器·rust双向遍历