Go http2 和 h2c

Go http2 和 h2c1 http 1 1 的服务器我们经常会在代码中启动一个 http 服务器 最简单的 http 1 1 服务器如下所示 1http Handle foo fooHandler 2http HandleFunc bar func whttp ResponseWrit r http Request 3fmt Fpr

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”。



版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/205449.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午6:00
下一篇 2026年3月19日 下午6:00


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号