Go语言打造HTTP/2服务:一步步指南

发表时间: 2024-05-20 17:51

整个golang实现http2服务的步骤

HTTP/2强制使用TLS。为了实现这一点, 我们首先需要一个私钥和一个证书。

1 生成公钥私钥文件

openssl req -newkey rsa:2048 -nodes -keyout private.pem -x509 -days 365 -out certificate.pem

private.pem:服务端私钥

certificate.pem:证书文件

2 实现server端代码如下:

package mainimport (    "fmt"    "log"    "net/http"    "os"    "path"    "time"    "golang.org/x/net/http2"    "golang.org/x/net/http2/h2c")func main() {      currentPath, _ := os.Getwd()      handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {          fmt.Fprint(w, "Hello world")          fmt.Fprintf(w, "Protocol: %s\n", r.Proto)      })      h2s := &http2.Server{          IdleTimeout: 60 * time.Second,      }      h1s := &http.Server{          Addr: ":8080",          Handler: h2c.NewHandler(handler, h2s),      }      // path.Join() 方法能够兼容不同的操作系统      log.Fatal(h1s.ListenAndServeTLS(path.Join(currentPath, "certificate.pem"), path.Join(currentPath, "private.pem")))}

3 实现客户端代码如下:

package mainimport (    "crypto/tls"    "crypto/x509"    "fmt"    "io/ioutil"    "log"    "net/http"    "os"    "path"    "time"    "golang.org/x/net/http2")var url = "https://localhost:8080"func main() {		requestByHttp2()}// 几种请求方式// HTTP2请求方式func requestByHttp2() {    currentPath, _ := os.Getwd()    client := &http.Client{        Timeout: 100 * time.Millisecond,    }    //读取证书文件,正式环境无读取证书文件,因为本地测试是无法认证证书    caCert, err := ioutil.ReadFile(path.Join(currentPath, "certificate.pem"))    if err != nil {        log.Fatalf("Reading server certificate: %s", err)        return    }    caCertPool := x509.NewCertPool()    caCertPool.AppendCertsFromPEM(caCert)    //tls协议配置,InsecureSkipVerify认证证书是否跳过    tlsConfig := &tls.Config{        RootCAs: caCertPool,        //设置安全跳跃认证        InsecureSkipVerify: true,    }    client.Transport = &http2.Transport{        TLSClientConfig: tlsConfig,    }    resp, err := client.Get(url)    if err != nil {        fmt.Printf("Failed get: err:%s \n", err)        return    }    defer resp.Body.Close()    body, err := ioutil.ReadAll(resp.Body)    if err != nil {        fmt.Printf("Failed reading response body: %s\n", err)        return    }    fmt.Printf("Get requestByHttp2 response %d: %s %s\n", resp.StatusCode, resp.Proto, string(body))}//普通的HTTP请求func requestByHTTP() {    //http1    _, err := http.Get(url)    fmt.Println(err)}// HTTP + SSL 证书请求func requestByHTTPSSL() {    currentPath, _ := os.Getwd()    client := &http.Client{}    //证书文件    caCert, err := ioutil.ReadFile(path.Join(currentPath, "certificate.pem"))    if err != nil {        log.Fatalf("Reading server certificate: %s", err)        return    }    caCertPool := x509.NewCertPool()    caCertPool.AppendCertsFromPEM(caCert)    // Create TLS configuration with the certificate of the server    tlsConfig := &tls.Config{        RootCAs: caCertPool,        //设置安全跳跃认证        InsecureSkipVerify: true,    }    client.Transport = &http.Transport{        TLSClientConfig: tlsConfig,    }    resp, err := client.Get(url)    if err != nil {        log.Fatalf("Failed get: %s", err)        return    }    defer resp.Body.Close()    body, err := ioutil.ReadAll(resp.Body)    if err != nil {        log.Fatalf("Failed reading response body: %s", err)        return    }		fmt.Printf("Get response %d: %s %s\n", resp.StatusCode, resp.Proto, string(body))}
> # go run server.go> # go run client.goGet requestByHttp2 response 200: HTTP/2.0 Hello worldProtocol: HTTP/2.0

问题总结:

报错: x509: certificate is not valid for any names, but wanted to match localhost

原因: 是http2请求安全认证不过, 通过设置如下参数来实现:

//设置安全跳跃认证

InsecureSkipVerify: true,