Add HTTP3 support (experimental)
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
This commit is contained in:
parent
0509b6fdb9
commit
e5a01c7cc8
13 changed files with 298 additions and 20 deletions
87
pkg/server/server_entrypoint_tcp_http3.go
Normal file
87
pkg/server/server_entrypoint_tcp_http3.go
Normal file
|
@ -0,0 +1,87 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/http3"
|
||||
"github.com/traefik/traefik/v2/pkg/config/static"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
"github.com/traefik/traefik/v2/pkg/tcp"
|
||||
)
|
||||
|
||||
type http3server struct {
|
||||
*http3.Server
|
||||
|
||||
http3conn net.PacketConn
|
||||
|
||||
lock sync.RWMutex
|
||||
getter func(info *tls.ClientHelloInfo) (*tls.Config, error)
|
||||
}
|
||||
|
||||
func newHTTP3Server(ctx context.Context, configuration *static.EntryPoint, httpsServer *httpServer) (*http3server, error) {
|
||||
if !configuration.EnableHTTP3 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
conn, err := net.ListenPacket("udp", configuration.GetAddress())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while starting http3 listener: %w", err)
|
||||
}
|
||||
|
||||
h3 := &http3server{
|
||||
http3conn: conn,
|
||||
getter: func(info *tls.ClientHelloInfo) (*tls.Config, error) {
|
||||
return nil, errors.New("no tls config")
|
||||
},
|
||||
}
|
||||
|
||||
h3.Server = &http3.Server{
|
||||
Server: &http.Server{
|
||||
Addr: configuration.GetAddress(),
|
||||
Handler: httpsServer.Server.(*http.Server).Handler,
|
||||
ErrorLog: httpServerLogger,
|
||||
ReadTimeout: time.Duration(configuration.Transport.RespondingTimeouts.ReadTimeout),
|
||||
WriteTimeout: time.Duration(configuration.Transport.RespondingTimeouts.WriteTimeout),
|
||||
IdleTimeout: time.Duration(configuration.Transport.RespondingTimeouts.IdleTimeout),
|
||||
TLSConfig: &tls.Config{GetConfigForClient: h3.getGetConfigForClient},
|
||||
},
|
||||
}
|
||||
|
||||
previousHandler := httpsServer.Server.(*http.Server).Handler
|
||||
|
||||
httpsServer.Server.(*http.Server).Handler = http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
err := h3.Server.SetQuicHeaders(rw.Header())
|
||||
if err != nil {
|
||||
log.FromContext(ctx).Errorf("failed to set HTTP3 headers: %v", err)
|
||||
}
|
||||
|
||||
previousHandler.ServeHTTP(rw, req)
|
||||
})
|
||||
|
||||
return h3, nil
|
||||
}
|
||||
|
||||
func (e *http3server) Start() error {
|
||||
return e.Serve(e.http3conn)
|
||||
}
|
||||
|
||||
func (e *http3server) Switch(rt *tcp.Router) {
|
||||
e.lock.Lock()
|
||||
defer e.lock.Unlock()
|
||||
|
||||
e.getter = rt.GetTLSGetClientInfo()
|
||||
}
|
||||
|
||||
func (e *http3server) getGetConfigForClient(info *tls.ClientHelloInfo) (*tls.Config, error) {
|
||||
e.lock.RLock()
|
||||
defer e.lock.RUnlock()
|
||||
|
||||
return e.getter(info)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue