为了学习golang的client源码执行流程,所以笔者通过golang实现http2的服务端和客户端,然后通过单步调试学习源码。下面我们看下整个golang实现http2的服务步骤。
1 生成公钥私钥文件
openssl req -newkey rsa:2048 -nodes -keyout private.pem -x509 -days 365 -out certificate.pem
private.pem:服务端私钥
certificate.pem:证书文件
2 实现server端代码如下
package main
import (
"fmt"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
"log"
"net/http"
"os"
)
func main() {
path, _ := 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{
// ...
}
h1s := &http.Server{
Addr: ":8080",
Handler: h2c.NewHandler(handler, h2s),
}
log.Fatal(h1s.ListenAndServeTLS(path+"\\certificate.pem", path+"\\private.pem"))
}
3 实现客户端代码如下
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"golang.org/x/net/http2"
"io/ioutil"
"log"
"net/http"
"os"
"time"
)
var url = "https://localhost:8080"
func main() {
request2()
}
func request2() {
path, _ := os.Getwd()
client := &http.Client{
Timeout: 100 * time.Millisecond,
}
//读取证书文件,正式环境无读取证书文件,因为本地测试是无法认证证书
caCert, err := ioutil.ReadFile(path + "\\http_connect\\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 request2 response %d: %s %s\n", resp.StatusCode, resp.Proto, string(body))
}
//http1请求
func request1() {
//http1
_, err := http.Get(url)
fmt.Println(err)
}
//http11请求
func request11() {
path, _ := os.Getwd()
client := &http.Client{}
//证书文件
caCert, err := ioutil.ReadFile(path + "\\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("Got response %d: %s %s\n", resp.StatusCode, resp.Proto, string(body))
}
问题总结:
报错:
x509: certificate is not valid for any names, but wanted to match localhost
是http2请求安全认证不过,通过设置如下参数来实现:
//设置安全跳跃认证
InsecureSkipVerify: true,