「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 两大核心接口。

相关推荐
火狮31 分钟前
鸿蒙Next API 12开发,使用@ohos/axios进行HTTP请求
http·华为·harmonyos
m0_748238271 小时前
WebClient HTTP 请求问题处理模板(泛型响应、忽略 SSL 证书等)
网络协议·http·ssl
我曾经是个程序员1 小时前
鸿蒙学习记录之http网络请求
服务器·学习·http
0zxm1 小时前
06 - Django 视图view
网络·后端·python·django
m0_748257181 小时前
Spring Boot FileUpLoad and Interceptor(文件上传和拦截器,Web入门知识)
前端·spring boot·后端
小_太_阳2 小时前
Scala_【1】概述
开发语言·后端·scala·intellij-idea
智慧老师2 小时前
Spring基础分析13-Spring Security框架
java·后端·spring
搬码后生仔4 小时前
asp.net core webapi项目中 在生产环境中 进不去swagger
chrome·后端·asp.net
凡人的AI工具箱4 小时前
每天40分玩转Django:Django国际化
数据库·人工智能·后端·python·django·sqlite
Lx3525 小时前
Pandas数据重命名:列名与索引为标题
后端·python·pandas