Go http2 和 h2c

简介:

1、http/1.1 的服务器

我们经常会在代码中启动一个http服务器,最简单的http/1.1服务器如下所示:


1http.Handle("/foo", fooHandler)
2http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
3 fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
4})
5log.Fatal(http.ListenAndServe(":8080", nil))

使用Go开发web服务非常的简单,快速。

2、http/1.1 的服务器 with TLS

如果想让http/1.1服务器支持TLS, 可以使用如下的代码:


1http.Handle("/foo", fooHandler)
2http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
3 fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
4})
5log.Fatal(http.http.ListenAndServeTLS(":443", "server.crt", "server.key",nil))

至于server.crtserver.key,你可以使用你从CA购买的证书,你也可以使用下面的测试证书。

为了测试,你可以创建CA证书和你的服务器使用的证书。

1、 创建CA证书


1$ openssl genrsa -out rootCA.key 2048
2$ openssl req -x509 -new -nodes -key rootCA.key -days 1024 -out rootCA.pem

然后把rootCA.pem加到你的浏览器的证书中

2、 创建证书


1$ openssl genrsa -out server.key 2048
2$ openssl req -new -key server.key -out server.csr
3$ openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 500
3、免费证书

如果你不想从CA花钱购买证书, 也不想配置测试证书,那么你可以使用let's encrypt的免费证书, 而且let's encrypt目前支持通配符证书,使用也是很方便的。

Go的扩展包中提供了let's encrypt的支持。


1package main
2import (
3 "crypto/tls"
4 "log"
5 "net/http"
6 "golang.org/x/crypto/acme/autocert"
7)
8func main() {
9 certManager := autocert.Manager{
10 Prompt: autocert.AcceptTOS,
11 HostPolicy: autocert.HostWhitelist("example.com"),
12 Cache: autocert.DirCache("certs"),
13 }
14 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
15 w.Write([]byte("Hello world"))
16 })
17 server := &http.Server{
18 Addr: ":443",
19 TLSConfig: &tls.Config{
20 GetCertificate: certManager.GetCertificate,
21 },
22 }
23 go http.ListenAndServe(":80", certManager.HTTPHandler(nil))
24 log.Fatal(server.ListenAndServeTLS("", "")) //Key and cert are coming from Let's Encrypt
25}

或者更简单的:

1log.Fatal(http.Serve(autocert.NewListener("example.com"), handler))

看上面的例子, 把example.com换成你的域名,证书暂存在certs文件夹。autocert会定期自动刷新,避免证书过期。它会自动申请证书,并进行验证。

不过比较遗憾的是, autocert目前不支持通配符域名。

HostWhitelist returns a policy where only the specified host names are allowed. Only exact matches are currently supported. Subdomains, regexp or wildcard will not match.

通配符(ACME v2)的支持也已经完成了,但是迟迟未通过review,所以你暂时还不能使用这个特性。 (issue#21081)

4、HTTP/2

Go 在 1.6的时候已经支持 HTTP/2 了, 1.8 开始支持PUSH功能,你什么时候开始采用HTTP/2的呢?

Go的http/2使用也非常简单,但是必须和TLS一起使用。


1package main
2import (
3 "log"
4 "net/http"
5 "time"
6 "golang.org/x/net/http2"
7)
8const idleTimeout = 5 * time.Minute
9const activeTimeout = 10 * time.Minute
10func main() {
11 var srv http.Server
12 //http2.VerboseLogs = true
13 srv.Addr = ":8972"
14 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
15 w.Write([]byte("hello http2"))
16 })
17 http2.ConfigureServer(&srv, &http2.Server{})
18 go func() {
19 log.Fatal(srv.ListenAndServeTLS("server.crt", "server.key"))
20 }()
21 select {}
22}

http2封装并隐藏了http/2的处理逻辑,对于用户来说,可以不必关心内部的具体实现,想http/1.1一样简单的使用即可。

这里的证书可以使用上面提到证书,或者你购买的1证书,或者免费let's encrypt证书。

5、h2c

上面我们说Go的http/2必须使用TLS是不严谨的,如果你想不使用TLS,你可以使用最近添加的h2c功能。


1package main
2import (
3 "fmt"
4 "log"
5 "net/http"
6 "golang.org/x/net/http2"
7 "golang.org/x/net/http2/h2c"
8)
9func main() {
10 mux := http.NewServeMux()
11 mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
12 fmt.Fprint(w, "Hello h2c")
13 })
14 s := &http.Server{
15 Addr: ":8972",
16 Handler: mux,
17 }
18 http2.ConfigureServer(s, &http2.Server{})
19 log.Fatal(s.ListenAndServe())
20}

使用起来也很简单,单数目前浏览器对http/2都是采用TLS的方式,所以用浏览器访问这个服务的话会退化为http/1.1的协议,测试的话你可以使用Go实现客户端的h2c访问。

客户端代码如下:


1package main
2import (
3 "crypto/tls"
4 "fmt"
5 "log"
6 "net"
7 "net/http"
8 "golang.org/x/net/http2"
9)
10func main() {
11 client := http.Client{
12 // Skip TLS dial
13 Transport: &http2.Transport{
14 AllowHTTP: true,
15 DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
16 return net.Dial(network, addr)
17 },
18 },
19 }
20 resp, err := client.Get("http://localhost:8972")
21 if err != nil {
22 log.Fatal(fmt.Errorf("error making request: %v", err))
23 }
24 fmt.Println(resp.StatusCode)
25 fmt.Println(resp.Proto)
26}

这个功能的讨论2016年就开始了(issue#14141),最终5月份的这个功能加上了,这样你就可以在没有TLS使用http/2高性能的特性了。


原文发布时间为:2018-09-14
本文来自云栖社区合作伙伴“ Go http2 和 h2c”,了解相关信息可以关注“ Go http2 和 h2c”。
相关文章
|
6月前
|
JSON 中间件 Go
Go 网络编程:HTTP服务与客户端开发
Go 语言的 `net/http` 包功能强大,可快速构建高并发 HTTP 服务。本文从创建简单 HTTP 服务入手,逐步讲解请求与响应对象、URL 参数处理、自定义路由、JSON 接口、静态文件服务、中间件编写及 HTTPS 配置等内容。通过示例代码展示如何使用 `http.HandleFunc`、`http.ServeMux`、`http.Client` 等工具实现常见功能,帮助开发者掌握构建高效 Web 应用的核心技能。
378 61
|
4月前
|
数据采集 JSON Go
Go语言实战案例:实现HTTP客户端请求并解析响应
本文是 Go 网络与并发实战系列的第 2 篇,详细介绍如何使用 Go 构建 HTTP 客户端,涵盖请求发送、响应解析、错误处理、Header 与 Body 提取等流程,并通过实战代码演示如何并发请求多个 URL,适合希望掌握 Go 网络编程基础的开发者。
|
5月前
|
JSON 前端开发 Go
Go语言实战:创建一个简单的 HTTP 服务器
本篇是《Go语言101实战》系列之一,讲解如何使用Go构建基础HTTP服务器。涵盖Go语言并发优势、HTTP服务搭建、路由处理、日志记录及测试方法,助你掌握高性能Web服务开发核心技能。
|
5月前
|
Go
如何在Go语言的HTTP请求中设置使用代理服务器
当使用特定的代理时,在某些情况下可能需要认证信息,认证信息可以在代理URL中提供,格式通常是:
403 0
|
6月前
|
JSON 编解码 API
Go语言网络编程:使用 net/http 构建 RESTful API
本章介绍如何使用 Go 语言的 `net/http` 标准库构建 RESTful API。内容涵盖 RESTful API 的基本概念及规范,包括 GET、POST、PUT 和 DELETE 方法的实现。通过定义用户数据结构和模拟数据库,逐步实现获取用户列表、创建用户、更新用户、删除用户的 HTTP 路由处理函数。同时提供辅助函数用于路径参数解析,并展示如何设置路由器启动服务。最后通过 curl 或 Postman 测试接口功能。章节总结了路由分发、JSON 编解码、方法区分、并发安全管理和路径参数解析等关键点,为更复杂需求推荐第三方框架如 Gin、Echo 和 Chi。
|
JSON 安全 前端开发
类型安全的 Go HTTP 请求
类型安全的 Go HTTP 请求
|
网络协议 安全 Go
Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
【10月更文挑战第28天】Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
258 13
|
数据采集 缓存 IDE
Go中遇到http code 206和302的获取数据的解决方案
文章提供了解决Go语言中处理HTTP状态码206(部分内容)和302(重定向)的方案,包括如何获取部分数据和真实请求地址的方法,以便程序员能快速完成工作,享受七夕时光。
1017 0
Go中遇到http code 206和302的获取数据的解决方案
|
程序员 Go 网络架构
不看就落后了,Go 1.22 中更好的http router
不看就落后了,Go 1.22 中更好的http router
|
网络协议 程序员 应用服务中间件
Swoole与Go系列教程之HTTP服务的应用
PHP 曾是Web开发领域佼佼者,随着业务壮大,异步和高并发方面不足显现。Swoole 曾经尝试填补空白,但局限性也比较的明显。Go 语言的崛起,简洁语法和并发优势吸引大厂使用,吸引了大多数程序员的转型。
1073 0
Swoole与Go系列教程之HTTP服务的应用