summaryrefslogtreecommitdiff
path: root/modules/caddyhttp/server.go
diff options
context:
space:
mode:
authorMatt Holt <mholt@users.noreply.github.com>2022-08-15 12:01:58 -0600
committerGitHub <noreply@github.com>2022-08-15 12:01:58 -0600
commitc79c08627d36e9871dedd3c7d8889d7d710134c2 (patch)
tree886449e2ce6a2cf39c60f58f2e4d420b5e3a8f1b /modules/caddyhttp/server.go
parente2a5e2293ab0b06e33445a1243f36cd5def1de42 (diff)
caddyhttp: Enable HTTP/3 by default (#4707)
Diffstat (limited to 'modules/caddyhttp/server.go')
-rw-r--r--modules/caddyhttp/server.go83
1 files changed, 70 insertions, 13 deletions
diff --git a/modules/caddyhttp/server.go b/modules/caddyhttp/server.go
index 62c0fd9..f8cd612 100644
--- a/modules/caddyhttp/server.go
+++ b/modules/caddyhttp/server.go
@@ -16,6 +16,7 @@ package caddyhttp
import (
"context"
+ "crypto/tls"
"encoding/json"
"errors"
"fmt"
@@ -25,6 +26,7 @@ import (
"runtime"
"strings"
"sync"
+ "sync/atomic"
"time"
"github.com/caddyserver/caddy/v2"
@@ -37,6 +39,8 @@ import (
// Server describes an HTTP server.
type Server struct {
+ activeRequests int64 // accessed atomically
+
// Socket addresses to which to bind listeners. Accepts
// [network addresses](/docs/conventions#network-addresses)
// that may include port ranges. Listener addresses must
@@ -112,21 +116,35 @@ type Server struct {
// to a non-null, empty struct.
Logs *ServerLogConfig `json:"logs,omitempty"`
- // Enable experimental HTTP/3 support. Note that HTTP/3 is not a
- // finished standard and has extremely limited client support.
- // This field is not subject to compatibility promises.
- ExperimentalHTTP3 bool `json:"experimental_http3,omitempty"`
-
- // Enables H2C ("Cleartext HTTP/2" or "H2 over TCP") support,
- // which will serve HTTP/2 over plaintext TCP connections if
- // the client supports it. Because this is not implemented by the
- // Go standard library, using H2C is incompatible with most
- // of the other options for this server. Do not enable this
+ // Protocols specifies which HTTP protocols to enable.
+ // Supported values are:
+ //
+ // - `h1` (HTTP/1.1)
+ // - `h2` (HTTP/2)
+ // - `h2c` (cleartext HTTP/2)
+ // - `h3` (HTTP/3)
+ //
+ // If enabling `h2` or `h2c`, `h1` must also be enabled;
+ // this is due to current limitations in the Go standard
+ // library.
+ //
+ // HTTP/2 operates only over TLS (HTTPS). HTTP/3 opens
+ // a UDP socket to serve QUIC connections.
+ //
+ // H2C operates over plain TCP if the client supports it;
+ // however, because this is not implemented by the Go
+ // standard library, other server options are not compatible
+ // and will not be applied to H2C requests. Do not enable this
// only to achieve maximum client compatibility. In practice,
// very few clients implement H2C, and even fewer require it.
- // This setting applies only to unencrypted HTTP listeners.
- // ⚠️ Experimental feature; subject to change or removal.
- AllowH2C bool `json:"allow_h2c,omitempty"`
+ // Enabling H2C can be useful for serving/proxying gRPC
+ // if encryption is not possible or desired.
+ //
+ // We recommend for most users to simply let Caddy use the
+ // default settings.
+ //
+ // Default: `[h1 h2 h3]`
+ Protocols []string `json:"protocols,omitempty"`
name string
@@ -152,7 +170,12 @@ type Server struct {
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Server", "Caddy")
+ // advertise HTTP/3, if enabled
if s.h3server != nil {
+ // keep track of active requests for QUIC transport purposes (See AcceptToken callback in quic.Config)
+ atomic.AddInt64(&s.activeRequests, 1)
+ defer atomic.AddInt64(&s.activeRequests, -1)
+
err := s.h3server.SetQuicHeaders(w.Header())
if err != nil {
s.logger.Error("setting HTTP/3 Alt-Svc header", zap.Error(err))
@@ -445,6 +468,30 @@ func (s *Server) findLastRouteWithHostMatcher() int {
return lastIndex
}
+// serveHTTP3 creates a QUIC listener, configures an HTTP/3 server if
+// not already done, and then uses that server to serve HTTP/3 over
+// the listener, with Server s as the handler.
+func (s *Server) serveHTTP3(hostport string, tlsCfg *tls.Config) error {
+ h3ln, err := caddy.ListenQUIC(hostport, tlsCfg, &s.activeRequests)
+ if err != nil {
+ return fmt.Errorf("starting HTTP/3 QUIC listener: %v", err)
+ }
+
+ // create HTTP/3 server if not done already
+ if s.h3server == nil {
+ s.h3server = &http3.Server{
+ Handler: s,
+ TLSConfig: tlsCfg,
+ MaxHeaderBytes: s.MaxHeaderBytes,
+ }
+ }
+
+ //nolint:errcheck
+ go s.h3server.ServeListener(h3ln)
+
+ return nil
+}
+
// HTTPErrorConfig determines how to handle errors
// from the HTTP handlers.
type HTTPErrorConfig struct {
@@ -509,6 +556,16 @@ func (s *Server) shouldLogRequest(r *http.Request) bool {
return true
}
+// protocol returns true if the protocol proto is configured/enabled.
+func (s *Server) protocol(proto string) bool {
+ for _, p := range s.Protocols {
+ if p == proto {
+ return true
+ }
+ }
+ return false
+}
+
// ServerLogConfig describes a server's logging configuration. If
// enabled without customization, all requests to this server are
// logged to the default logger; logger destinations may be