mirror of
https://github.com/caddyserver/caddy.git
synced 2025-04-23 13:14:08 +08:00
Merge branch 'master' into master
This commit is contained in:
commit
1e82efd4ca
@ -111,7 +111,7 @@ archives:
|
||||
- id: default
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
formats: zip
|
||||
name_template: >-
|
||||
{{ .ProjectName }}_
|
||||
{{- .Version }}_
|
||||
|
23
cmd/main.go
23
cmd/main.go
@ -24,6 +24,7 @@ import (
|
||||
"io"
|
||||
"io/fs"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -33,10 +34,12 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/KimMachineGun/automemlimit/memlimit"
|
||||
"github.com/caddyserver/certmagic"
|
||||
"github.com/spf13/pflag"
|
||||
"go.uber.org/automaxprocs/maxprocs"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/exp/zapslog"
|
||||
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
"github.com/caddyserver/caddy/v2/caddyconfig"
|
||||
@ -66,12 +69,30 @@ func Main() {
|
||||
os.Exit(caddy.ExitCodeFailedStartup)
|
||||
}
|
||||
|
||||
undo, err := maxprocs.Set()
|
||||
logger := caddy.Log()
|
||||
|
||||
// Configure the maximum number of CPUs to use to match the Linux container quota (if any)
|
||||
// See https://pkg.go.dev/runtime#GOMAXPROCS
|
||||
undo, err := maxprocs.Set(maxprocs.Logger(logger.Sugar().Infof))
|
||||
defer undo()
|
||||
if err != nil {
|
||||
caddy.Log().Warn("failed to set GOMAXPROCS", zap.Error(err))
|
||||
}
|
||||
|
||||
// Configure the maximum memory to use to match the Linux container quota (if any) or system memory
|
||||
// See https://pkg.go.dev/runtime/debug#SetMemoryLimit
|
||||
_, _ = memlimit.SetGoMemLimitWithOpts(
|
||||
memlimit.WithLogger(
|
||||
slog.New(zapslog.NewHandler(logger.Core())),
|
||||
),
|
||||
memlimit.WithProvider(
|
||||
memlimit.ApplyFallback(
|
||||
memlimit.FromCgroup,
|
||||
memlimit.FromSystem,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
if err := defaultFactory.Build().Execute(); err != nil {
|
||||
var exitError *exitError
|
||||
if errors.As(err, &exitError) {
|
||||
|
6
go.mod
6
go.mod
@ -19,7 +19,7 @@ require (
|
||||
github.com/klauspost/cpuid/v2 v2.2.9
|
||||
github.com/mholt/acmez/v3 v3.0.1
|
||||
github.com/prometheus/client_golang v1.19.1
|
||||
github.com/quic-go/quic-go v0.48.2
|
||||
github.com/quic-go/quic-go v0.49.0
|
||||
github.com/smallstep/certificates v0.26.1
|
||||
github.com/smallstep/nosql v0.6.1
|
||||
github.com/smallstep/truststore v0.13.0
|
||||
@ -49,6 +49,7 @@ require (
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/KimMachineGun/automemlimit v0.7.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
@ -63,6 +64,7 @@ require (
|
||||
github.com/google/pprof v0.0.0-20231212022811-ec68065c825e // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.13.2 // indirect
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
github.com/smallstep/go-attestation v0.4.4-0.20240109183208-413678f90935 // indirect
|
||||
@ -74,7 +76,7 @@ require (
|
||||
go.opentelemetry.io/contrib/propagators/b3 v1.17.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/jaeger v1.17.0 // indirect
|
||||
go.opentelemetry.io/contrib/propagators/ot v1.17.0 // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
go.uber.org/mock v0.5.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect
|
||||
|
12
go.sum
12
go.sum
@ -31,6 +31,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/KimMachineGun/automemlimit v0.7.0 h1:7G06p/dMSf7G8E6oq+f2uOPuVncFyIlDI/pBWK49u88=
|
||||
github.com/KimMachineGun/automemlimit v0.7.0/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
@ -366,6 +368,8 @@ github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe
|
||||
github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
|
||||
github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/peterbourgon/diskv/v3 v3.0.1 h1:x06SQA46+PKIUftmEujdwSEpIx8kR+M9eLYsUxeYveU=
|
||||
github.com/peterbourgon/diskv/v3 v3.0.1/go.mod h1:kJ5Ny7vLdARGU3WUuy6uzO6T0nb/2gWcT1JiBvRmb5o=
|
||||
@ -392,8 +396,8 @@ github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE=
|
||||
github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
|
||||
github.com/quic-go/quic-go v0.49.0 h1:w5iJHXwHxs1QxyBv1EHKuC50GX5to8mJAxvtnttJp94=
|
||||
github.com/quic-go/quic-go v0.49.0/go.mod h1:s2wDnmCdooUQBmQfpUSTCYBl1/D4FcqbULMMkASvR6s=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
@ -564,8 +568,8 @@ go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
||||
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||
|
@ -154,16 +154,16 @@ func (rr *responseRecorder) WriteHeader(statusCode int) {
|
||||
// connections by manually setting headers and writing status 101
|
||||
rr.statusCode = statusCode
|
||||
|
||||
// decide whether we should buffer the response
|
||||
if rr.shouldBuffer == nil {
|
||||
rr.stream = true
|
||||
} else {
|
||||
rr.stream = !rr.shouldBuffer(rr.statusCode, rr.ResponseWriterWrapper.Header())
|
||||
}
|
||||
|
||||
// 1xx responses aren't final; just informational
|
||||
if statusCode < 100 || statusCode > 199 {
|
||||
rr.wroteHeader = true
|
||||
|
||||
// decide whether we should buffer the response
|
||||
if rr.shouldBuffer == nil {
|
||||
rr.stream = true
|
||||
} else {
|
||||
rr.stream = !rr.shouldBuffer(rr.statusCode, rr.ResponseWriterWrapper.Header())
|
||||
}
|
||||
}
|
||||
|
||||
// if informational or not buffered, immediately write header
|
||||
|
@ -2,26 +2,26 @@ package reverseproxy
|
||||
|
||||
import (
|
||||
"runtime/debug"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
)
|
||||
|
||||
var reverseProxyMetrics = struct {
|
||||
init sync.Once
|
||||
upstreamsHealthy *prometheus.GaugeVec
|
||||
logger *zap.Logger
|
||||
}{}
|
||||
|
||||
func initReverseProxyMetrics(handler *Handler) {
|
||||
func initReverseProxyMetrics(handler *Handler, registry *prometheus.Registry) {
|
||||
const ns, sub = "caddy", "reverse_proxy"
|
||||
|
||||
upstreamsLabels := []string{"upstream"}
|
||||
reverseProxyMetrics.upstreamsHealthy = promauto.NewGaugeVec(prometheus.GaugeOpts{
|
||||
reverseProxyMetrics.upstreamsHealthy = promauto.With(registry).NewGaugeVec(prometheus.GaugeOpts{
|
||||
Namespace: ns,
|
||||
Subsystem: sub,
|
||||
Name: "upstreams_healthy",
|
||||
@ -35,17 +35,19 @@ type metricsUpstreamsHealthyUpdater struct {
|
||||
handler *Handler
|
||||
}
|
||||
|
||||
func newMetricsUpstreamsHealthyUpdater(handler *Handler) *metricsUpstreamsHealthyUpdater {
|
||||
reverseProxyMetrics.init.Do(func() {
|
||||
initReverseProxyMetrics(handler)
|
||||
})
|
||||
const upstreamsHealthyMetrics caddy.CtxKey = "reverse_proxy_upstreams_healthy"
|
||||
|
||||
func newMetricsUpstreamsHealthyUpdater(handler *Handler, ctx caddy.Context) *metricsUpstreamsHealthyUpdater {
|
||||
if set := ctx.Value(upstreamsHealthyMetrics); set == nil {
|
||||
initReverseProxyMetrics(handler, ctx.GetMetricsRegistry())
|
||||
ctx = ctx.WithValue(upstreamsHealthyMetrics, true)
|
||||
}
|
||||
reverseProxyMetrics.upstreamsHealthy.Reset()
|
||||
|
||||
return &metricsUpstreamsHealthyUpdater{handler}
|
||||
}
|
||||
|
||||
func (m *metricsUpstreamsHealthyUpdater) Init() {
|
||||
func (m *metricsUpstreamsHealthyUpdater) init() {
|
||||
go func() {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
|
@ -382,8 +382,8 @@ func (h *Handler) Provision(ctx caddy.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
upstreamHealthyUpdater := newMetricsUpstreamsHealthyUpdater(h)
|
||||
upstreamHealthyUpdater.Init()
|
||||
upstreamHealthyUpdater := newMetricsUpstreamsHealthyUpdater(h, ctx)
|
||||
upstreamHealthyUpdater.init()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
package caddytls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
@ -55,7 +56,7 @@ func (MatchServerName) CaddyModule() caddy.ModuleInfo {
|
||||
|
||||
// Match matches hello based on SNI.
|
||||
func (m MatchServerName) Match(hello *tls.ClientHelloInfo) bool {
|
||||
repl := caddy.NewReplacer()
|
||||
var repl *caddy.Replacer
|
||||
// caddytls.TestServerNameMatcher calls this function without any context
|
||||
if ctx := hello.Context(); ctx != nil {
|
||||
// In some situations the existing context may have no replacer
|
||||
@ -64,6 +65,10 @@ func (m MatchServerName) Match(hello *tls.ClientHelloInfo) bool {
|
||||
}
|
||||
}
|
||||
|
||||
if repl == nil {
|
||||
repl = caddy.NewReplacer()
|
||||
}
|
||||
|
||||
for _, name := range m {
|
||||
rs := repl.ReplaceAll(name, "")
|
||||
if certmagic.MatchWildcard(hello.ServerName, rs) {
|
||||
@ -224,15 +229,28 @@ func (MatchServerNameRE) CaddyModule() caddy.ModuleInfo {
|
||||
|
||||
// Match matches hello based on SNI using a regular expression.
|
||||
func (m MatchServerNameRE) Match(hello *tls.ClientHelloInfo) bool {
|
||||
repl := caddy.NewReplacer()
|
||||
// caddytls.TestServerNameMatcher calls this function without any context
|
||||
if ctx := hello.Context(); ctx != nil {
|
||||
// Note: caddytls.TestServerNameMatcher calls this function without any context
|
||||
ctx := hello.Context()
|
||||
if ctx == nil {
|
||||
// layer4.Connection implements GetContext() to pass its context here,
|
||||
// since hello.Context() returns nil
|
||||
if mayHaveContext, ok := hello.Conn.(interface{ GetContext() context.Context }); ok {
|
||||
ctx = mayHaveContext.GetContext()
|
||||
}
|
||||
}
|
||||
|
||||
var repl *caddy.Replacer
|
||||
if ctx != nil {
|
||||
// In some situations the existing context may have no replacer
|
||||
if replAny := ctx.Value(caddy.ReplacerCtxKey); replAny != nil {
|
||||
repl = replAny.(*caddy.Replacer)
|
||||
}
|
||||
}
|
||||
|
||||
if repl == nil {
|
||||
repl = caddy.NewReplacer()
|
||||
}
|
||||
|
||||
return m.MatchRegexp.Match(hello.ServerName, repl)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user