使用自签名证书,在端口4433和4431用两种方式启动了http3服务,在8443启动了HTTP2服务
用go写的客户端能正常访问http3服务,用浏览器firefo和chrome打开https://localhost:4431/都是显示无法连接是怎么回事?打开http2 https://localhost:8443/浏览器都会提示证书不信任,点忽略后正常。
为什么http3不行?
代码如下:
server.go:
package main
import (
"crypto/tls"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"time"
"github.com/quic-go/quic-go"
"github.com/quic-go/quic-go/http3"
)
func streamHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/x-ndjson")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Alt-Svc", `h3=":4433"; ma=86400`)
flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "Streaming unsupported", http.StatusInternalServerError)
return
}
for i := 0; i < 5; i++ {
msg := map[string]interface{}{
"token": fmt.Sprintf("h3-word%d", i),
"proto": r.Proto, // 应为 "HTTP/3.0"
"index": i,
}
json.NewEncoder(w).Encode(msg)
flusher.Flush()
time.Sleep(600 * time.Millisecond)
}
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Alt-Svc", `h3=":4433"; ma=86400`)
w.Write([]byte("ok\n"))
w.Write([]byte(r.Proto))
})
mux.HandleFunc("/stream", streamHandler)
certPath := "cert.pem"
keyPath := "key.pem"
// 使用 quic-go 提供的 HTTP/3 服务器
server := &http3.Server{
Handler: mux,
Addr: ":4433",
TLSConfig: http3.ConfigureTLSConfig(&tls.Config{}),
QUICConfig: &quic.Config{},
}
go func() {
log.Println("HTTP/3 server running on https://localhost:4433")
log.Fatal(server.ListenAndServeTLS(certPath, keyPath))
}()
go func() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, fmt.Sprintf("ok, http proto=%s", r.Proto))
})
// If mux is nil, the http.DefaultServeMux is used.
log.Println("HTTP/3 server running on https://localhost:4431")
log.Fatal(http3.ListenAndServeQUIC("0.0.0.0:4431", certPath, keyPath, mux))
}()
// 同时启动 HTTP/2 (TCP)
log.Println("HTTP/2 on TCP :8443")
log.Fatal(http.ListenAndServeTLS(":8443", certPath, keyPath, mux))
}client.go:
package main
import (
"crypto/tls"
"io"
"log"
"net/http"
"github.com/quic-go/quic-go"
"github.com/quic-go/quic-go/http3"
)
func main() {
tr := &http3.Transport{
// set a TLS client config, if desired
TLSClientConfig: &tls.Config{
NextProtos: []string{http3.NextProtoH3}, // set the ALPN for HTTP/3
InsecureSkipVerify: true,
},
QUICConfig: &quic.Config{}, // QUIC connection options
}
defer tr.Close()
client := &http.Client{
Transport: tr,
}
urls := []string{
"https://127.0.0.1:4433",
"https://127.0.0.1:4433/stream",
"https://127.0.0.1:4431",
}
for _, url := range urls {
rsp, err := client.Get(url)
if err != nil {
log.Printf("req error: %s", err)
return
}
defer rsp.Body.Close()
rb, err := io.ReadAll(rsp.Body)
if err != nil {
log.Println("read body err: ", err)
return
}
log.Println("req:", url, "-- response:", string(rb))
}
}2025-11-22更新:
折腾一番搞定了:https://360us.net/article/109.html 里面拉到最底部。
为了方面这里使用了一个工具:mkcert - https://github.com/FiloSottile/mkcert
使用方法:
用上面生成的证书文件来启动http3本地服务器。
浏览器直接访问还没用,不管是firefox还是chrome都不会用http3来连接,会提示连接不了。
然后得让浏览器强制使用http3协议来连接。
win系统下面的命令:
"C:\Program Files\Google\Chrome\Application\chrome.exe" --origin-to-force-quic-on=127.0.0.1:443 https://127.0.0.1:443强制chrome使用http3连接才行,edge浏览器参数一样。firefox没找到相关启动参数,就没法了。
在142版的chrome和edge测试通过。