diff --git a/gin.go b/gin.go index 57f8c2a3..a099fe5f 100644 --- a/gin.go +++ b/gin.go @@ -582,6 +582,23 @@ func (engine *Engine) RunQUIC(addr, certFile, keyFile string) (err error) { return } +// RunHttp3 attaches the router to a http.Server and starts listening +// and serving both TLS/TCP and QUIC requests in parallel. +// It is a shortcut for http3.ListenAndServe(addr, certFile, keyFile, router) +// Note: this method will block the calling goroutine indefinitely unless an error happens. +func (engine *Engine) RunHttp3(addr, certFile, keyFile string) (err error) { + debugPrint("Listening and serving both HTTPS and QUIC on %s\n", addr) + defer func() { debugPrintError(err) }() + + if engine.isUnsafeTrustedProxies() { + debugPrint("[WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.\n" + + "Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.") + } + + err = http3.ListenAndServe(addr, certFile, keyFile, engine.Handler()) + return +} + // RunListener attaches the router to a http.Server and starts listening and serving HTTP requests // through the specified net.Listener func (engine *Engine) RunListener(listener net.Listener) (err error) { diff --git a/gin_integration_test.go b/gin_integration_test.go index 2125df92..a5798c65 100644 --- a/gin_integration_test.go +++ b/gin_integration_test.go @@ -290,6 +290,22 @@ func TestRunQUIC(t *testing.T) { testRequest(t, "https://localhost:8443/example") } +func TestRunHttp3(t *testing.T) { + router := New() + go func() { + router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") }) + + assert.NoError(t, router.RunHttp3(":2396", "./testdata/certificate/cert.pem", "./testdata/certificate/key.pem")) + }() + + // have to wait for the goroutine to start and run the server + // otherwise the main thread will complete + time.Sleep(5 * time.Millisecond) + + assert.Error(t, router.RunHttp3(":2396", "./testdata/certificate/cert.pem", "./testdata/certificate/key.pem")) + testRequest(t, "https://localhost:2396/example") +} + func TestFileDescriptor(t *testing.T) { router := New()