mirror of
https://github.com/caddyserver/caddy.git
synced 2026-05-28 01:32:30 -04:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d9a83376b | |||
| df5edf6bdb | |||
| 908e956927 | |||
| 2f7ceb5774 | |||
| e89c9a45b9 | |||
| e9ac48b4be | |||
| e55570298a | |||
| 87f63b125b | |||
| 801ec75669 | |||
| c8219d0e95 | |||
| 36fce3fa18 | |||
| 547f069564 | |||
| d9fbef92fc | |||
| 1a4c857bb9 | |||
| 65c489a0c3 | |||
| db55da59ef | |||
| b4c7313cc7 | |||
| b809ed71ed | |||
| 0259853a41 | |||
| f0ea489d89 | |||
| 648207063e | |||
| 9782ea3400 | |||
| 11a082c060 | |||
| 15adb893d5 | |||
| 16834d64de | |||
| ec2de22ab1 | |||
| 979c413f04 | |||
| ae5e2d96b7 |
@@ -16,7 +16,6 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
goos:
|
goos:
|
||||||
- 'aix'
|
|
||||||
- 'android'
|
- 'android'
|
||||||
- 'linux'
|
- 'linux'
|
||||||
- 'solaris'
|
- 'solaris'
|
||||||
@@ -63,12 +62,11 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 0
|
||||||
GOOS: ${{ matrix.goos }}
|
GOOS: ${{ matrix.goos }}
|
||||||
GOARCH: ${{ matrix.goos == 'aix' && 'ppc64' || 'amd64' }}
|
|
||||||
shell: bash
|
shell: bash
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
working-directory: ./cmd/caddy
|
working-directory: ./cmd/caddy
|
||||||
run: |
|
run: |
|
||||||
GOOS=$GOOS GOARCH=$GOARCH go build -trimpath -o caddy-"$GOOS"-$GOARCH 2> /dev/null
|
GOOS=$GOOS go build -trimpath -o caddy-"$GOOS"-amd64 2> /dev/null
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "::warning ::$GOOS Build Failed"
|
echo "::warning ::$GOOS Build Failed"
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ func init() {
|
|||||||
if env, exists := os.LookupEnv("CADDY_ADMIN"); exists {
|
if env, exists := os.LookupEnv("CADDY_ADMIN"); exists {
|
||||||
DefaultAdminListen = env
|
DefaultAdminListen = env
|
||||||
}
|
}
|
||||||
RegisterNamespace("caddy.config_loaders", []interface{}{(*ConfigLoader)(nil)})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AdminConfig configures Caddy's API endpoint, which is used
|
// AdminConfig configures Caddy's API endpoint, which is used
|
||||||
|
|||||||
@@ -41,15 +41,6 @@ import (
|
|||||||
"github.com/caddyserver/caddy/v2/notify"
|
"github.com/caddyserver/caddy/v2/notify"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
RegisterNamespace("", []interface{}{
|
|
||||||
(*App)(nil),
|
|
||||||
})
|
|
||||||
RegisterNamespace("caddy.storage", []interface{}{
|
|
||||||
(*StorageConverter)(nil),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Config is the top (or beginning) of the Caddy configuration structure.
|
// Config is the top (or beginning) of the Caddy configuration structure.
|
||||||
// Caddy config is expressed natively as a JSON document. If you prefer
|
// Caddy config is expressed natively as a JSON document. If you prefer
|
||||||
// not to work with JSON directly, there are [many config adapters](/docs/config-adapters)
|
// not to work with JSON directly, there are [many config adapters](/docs/config-adapters)
|
||||||
@@ -81,15 +72,11 @@ type Config struct {
|
|||||||
// module is `caddy.storage.file_system` (the local file system),
|
// module is `caddy.storage.file_system` (the local file system),
|
||||||
// and the default path
|
// and the default path
|
||||||
// [depends on the OS and environment](/docs/conventions#data-directory).
|
// [depends on the OS and environment](/docs/conventions#data-directory).
|
||||||
// A storage `module` should implement the following interfaces:
|
|
||||||
// - [StorageConverter](https://pkg.go.dev/github.com/caddyserver/caddy/v2#StorageConverter)
|
|
||||||
StorageRaw json.RawMessage `json:"storage,omitempty" caddy:"namespace=caddy.storage inline_key=module"`
|
StorageRaw json.RawMessage `json:"storage,omitempty" caddy:"namespace=caddy.storage inline_key=module"`
|
||||||
|
|
||||||
// AppsRaw are the apps that Caddy will load and run. The
|
// AppsRaw are the apps that Caddy will load and run. The
|
||||||
// app module name is the key, and the app's config is the
|
// app module name is the key, and the app's config is the
|
||||||
// associated value.
|
// associated value.
|
||||||
// An `app` should implement the following interfaces:
|
|
||||||
// - [caddy.App](https://pkg.go.dev/github.com/caddyserver/caddy/v2?tab=doc#App)
|
|
||||||
AppsRaw ModuleMap `json:"apps,omitempty" caddy:"namespace="`
|
AppsRaw ModuleMap `json:"apps,omitempty" caddy:"namespace="`
|
||||||
|
|
||||||
apps map[string]App
|
apps map[string]App
|
||||||
@@ -838,18 +825,13 @@ func ParseDuration(s string) (time.Duration, error) {
|
|||||||
// regardless of storage configuration, since each instance is intended to
|
// regardless of storage configuration, since each instance is intended to
|
||||||
// have its own unique ID.
|
// have its own unique ID.
|
||||||
func InstanceID() (uuid.UUID, error) {
|
func InstanceID() (uuid.UUID, error) {
|
||||||
appDataDir := AppDataDir()
|
uuidFilePath := filepath.Join(AppDataDir(), "instance.uuid")
|
||||||
uuidFilePath := filepath.Join(appDataDir, "instance.uuid")
|
|
||||||
uuidFileBytes, err := os.ReadFile(uuidFilePath)
|
uuidFileBytes, err := os.ReadFile(uuidFilePath)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
uuid, err := uuid.NewRandom()
|
uuid, err := uuid.NewRandom()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return uuid, err
|
return uuid, err
|
||||||
}
|
}
|
||||||
err = os.MkdirAll(appDataDir, 0o600)
|
|
||||||
if err != nil {
|
|
||||||
return uuid, err
|
|
||||||
}
|
|
||||||
err = os.WriteFile(uuidFilePath, []byte(uuid.String()), 0o600)
|
err = os.WriteFile(uuidFilePath, []byte(uuid.String()), 0o600)
|
||||||
return uuid, err
|
return uuid, err
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ func placeholderShorthands() []string {
|
|||||||
"{remote_port}", "{http.request.remote.port}",
|
"{remote_port}", "{http.request.remote.port}",
|
||||||
"{scheme}", "{http.request.scheme}",
|
"{scheme}", "{http.request.scheme}",
|
||||||
"{uri}", "{http.request.uri}",
|
"{uri}", "{http.request.uri}",
|
||||||
"{uuid}", "{http.request.uuid}",
|
|
||||||
"{tls_cipher}", "{http.request.tls.cipher_suite}",
|
"{tls_cipher}", "{http.request.tls.cipher_suite}",
|
||||||
"{tls_version}", "{http.request.tls.version}",
|
"{tls_version}", "{http.request.tls.version}",
|
||||||
"{tls_client_fingerprint}", "{http.request.tls.client.fingerprint}",
|
"{tls_client_fingerprint}", "{http.request.tls.client.fingerprint}",
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
package integration
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/caddyserver/caddy/v2"
|
|
||||||
_ "github.com/caddyserver/caddy/v2/modules/standard"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Validates that Caddy's registered internal modules implement the necessary interfaces of their
|
|
||||||
// respective namespaces
|
|
||||||
func TestTypes(t *testing.T) {
|
|
||||||
var i int
|
|
||||||
for _, v := range caddy.Modules() {
|
|
||||||
mod, _ := caddy.GetModule(v)
|
|
||||||
if ok, err := caddy.ConformsToNamespace(mod.New(), mod.ID.Namespace()); !ok {
|
|
||||||
t.Errorf("%s", err)
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
t.Logf("Passed through %d modules", i)
|
|
||||||
}
|
|
||||||
@@ -203,7 +203,6 @@ func cmdExportStorage(fl Flags) (int, error) {
|
|||||||
Name: k,
|
Name: k,
|
||||||
Mode: 0o600,
|
Mode: 0o600,
|
||||||
Size: int64(len(v)),
|
Size: int64(len(v)),
|
||||||
ModTime: info.Modified,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = tw.WriteHeader(hdr); err != nil {
|
if err = tw.WriteHeader(hdr); err != nil {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ require (
|
|||||||
github.com/google/uuid v1.3.1
|
github.com/google/uuid v1.3.1
|
||||||
github.com/klauspost/compress v1.17.0
|
github.com/klauspost/compress v1.17.0
|
||||||
github.com/klauspost/cpuid/v2 v2.2.5
|
github.com/klauspost/cpuid/v2 v2.2.5
|
||||||
|
github.com/mastercactapus/proxyprotocol v0.0.4
|
||||||
github.com/mholt/acmez v1.2.0
|
github.com/mholt/acmez v1.2.0
|
||||||
github.com/prometheus/client_golang v1.15.1
|
github.com/prometheus/client_golang v1.15.1
|
||||||
github.com/quic-go/quic-go v0.40.0
|
github.com/quic-go/quic-go v0.40.0
|
||||||
@@ -116,7 +117,6 @@ require (
|
|||||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||||
github.com/mitchellh/go-ps v1.0.0 // indirect
|
github.com/mitchellh/go-ps v1.0.0 // indirect
|
||||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||||
github.com/pires/go-proxyproto v0.7.0
|
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/prometheus/client_model v0.4.0 // indirect
|
github.com/prometheus/client_model v0.4.0 // indirect
|
||||||
github.com/prometheus/common v0.42.0 // indirect
|
github.com/prometheus/common v0.42.0 // indirect
|
||||||
|
|||||||
@@ -352,6 +352,8 @@ github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0Q
|
|||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
|
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
|
||||||
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
|
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
|
||||||
|
github.com/mastercactapus/proxyprotocol v0.0.4 h1:qSY75IZF30ZqIU9iW1ip3I7gTnm8wRAnGWqPxCBVgq0=
|
||||||
|
github.com/mastercactapus/proxyprotocol v0.0.4/go.mod h1:X8FRVEDZz9FkrIoL4QYTBF4Ka4ELwTv0sah0/5NxCPw=
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
@@ -431,8 +433,6 @@ github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9
|
|||||||
github.com/peterbourgon/diskv/v3 v3.0.1 h1:x06SQA46+PKIUftmEujdwSEpIx8kR+M9eLYsUxeYveU=
|
github.com/peterbourgon/diskv/v3 v3.0.1 h1:x06SQA46+PKIUftmEujdwSEpIx8kR+M9eLYsUxeYveU=
|
||||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||||
github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs=
|
|
||||||
github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4=
|
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
|||||||
@@ -37,12 +37,6 @@ import (
|
|||||||
"github.com/caddyserver/caddy/v2/internal"
|
"github.com/caddyserver/caddy/v2/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
RegisterNamespace("caddy.listeners", []interface{}{
|
|
||||||
(*ListenerWrapper)(nil),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetworkAddress represents one or more network addresses.
|
// NetworkAddress represents one or more network addresses.
|
||||||
// It contains the individual components for a parsed network
|
// It contains the individual components for a parsed network
|
||||||
// address of the form accepted by ParseNetworkAddress().
|
// address of the form accepted by ParseNetworkAddress().
|
||||||
|
|||||||
@@ -33,12 +33,6 @@ func init() {
|
|||||||
RegisterModule(StdoutWriter{})
|
RegisterModule(StdoutWriter{})
|
||||||
RegisterModule(StderrWriter{})
|
RegisterModule(StderrWriter{})
|
||||||
RegisterModule(DiscardWriter{})
|
RegisterModule(DiscardWriter{})
|
||||||
RegisterNamespace("caddy.logging.encoders", []interface{}{
|
|
||||||
(*zapcore.Encoder)(nil),
|
|
||||||
})
|
|
||||||
RegisterNamespace("caddy.logging.writers", []interface{}{
|
|
||||||
(*WriterOpener)(nil),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logging facilitates logging within Caddy. The default log is
|
// Logging facilitates logging within Caddy. The default log is
|
||||||
@@ -271,8 +265,6 @@ type BaseLog struct {
|
|||||||
WriterRaw json.RawMessage `json:"writer,omitempty" caddy:"namespace=caddy.logging.writers inline_key=output"`
|
WriterRaw json.RawMessage `json:"writer,omitempty" caddy:"namespace=caddy.logging.writers inline_key=output"`
|
||||||
|
|
||||||
// The encoder is how the log entries are formatted or encoded.
|
// The encoder is how the log entries are formatted or encoded.
|
||||||
// An `encoder` should implement the following interfaces:
|
|
||||||
// - [zapcore.Encoder](https://pkg.go.dev/go.uber.org/zap/zapcore#Encoder)
|
|
||||||
EncoderRaw json.RawMessage `json:"encoder,omitempty" caddy:"namespace=caddy.logging.encoders inline_key=format"`
|
EncoderRaw json.RawMessage `json:"encoder,omitempty" caddy:"namespace=caddy.logging.encoders inline_key=format"`
|
||||||
|
|
||||||
// Level is the minimum level to emit, and is inclusive.
|
// Level is the minimum level to emit, and is inclusive.
|
||||||
|
|||||||
@@ -31,13 +31,6 @@ import (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
caddy.RegisterModule(HTTPBasicAuth{})
|
caddy.RegisterModule(HTTPBasicAuth{})
|
||||||
|
|
||||||
caddy.RegisterNamespace("http.authentication.hashes", []interface{}{
|
|
||||||
(*Comparer)(nil),
|
|
||||||
})
|
|
||||||
caddy.RegisterNamespace("http.authentication.providers", []interface{}{
|
|
||||||
(*Authenticator)(nil),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPBasicAuth facilitates HTTP basic authentication.
|
// HTTPBasicAuth facilitates HTTP basic authentication.
|
||||||
|
|||||||
@@ -37,9 +37,6 @@ import (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
caddy.RegisterModule(Encode{})
|
caddy.RegisterModule(Encode{})
|
||||||
caddy.RegisterNamespace("http.encoders", []interface{}{
|
|
||||||
(*Encoding)(nil),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode is a middleware which can encode responses.
|
// Encode is a middleware which can encode responses.
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ package fileserver
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@@ -32,14 +31,13 @@ import (
|
|||||||
"github.com/caddyserver/caddy/v2"
|
"github.com/caddyserver/caddy/v2"
|
||||||
"github.com/caddyserver/caddy/v2/caddyconfig"
|
"github.com/caddyserver/caddy/v2/caddyconfig"
|
||||||
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
|
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
|
||||||
"github.com/caddyserver/caddy/v2/modules/caddyhttp/encode"
|
|
||||||
caddytpl "github.com/caddyserver/caddy/v2/modules/caddyhttp/templates"
|
caddytpl "github.com/caddyserver/caddy/v2/modules/caddyhttp/templates"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
caddycmd.RegisterCommand(caddycmd.Command{
|
caddycmd.RegisterCommand(caddycmd.Command{
|
||||||
Name: "file-server",
|
Name: "file-server",
|
||||||
Usage: "[--domain <example.com>] [--root <path>] [--listen <addr>] [--browse] [--access-log] [--precompressed]",
|
Usage: "[--domain <example.com>] [--root <path>] [--listen <addr>] [--browse] [--access-log]",
|
||||||
Short: "Spins up a production-ready file server",
|
Short: "Spins up a production-ready file server",
|
||||||
Long: `
|
Long: `
|
||||||
A simple but production-ready file server. Useful for quick deployments,
|
A simple but production-ready file server. Useful for quick deployments,
|
||||||
@@ -52,9 +50,6 @@ will be changed to the HTTPS port and the server will use HTTPS. If using
|
|||||||
a public domain, ensure A/AAAA records are properly configured before
|
a public domain, ensure A/AAAA records are properly configured before
|
||||||
using this option.
|
using this option.
|
||||||
|
|
||||||
By default, Zstandard and Gzip compression are enabled. Use --no-compress
|
|
||||||
to disable compression.
|
|
||||||
|
|
||||||
If --browse is enabled, requests for folders without an index file will
|
If --browse is enabled, requests for folders without an index file will
|
||||||
respond with a file listing.`,
|
respond with a file listing.`,
|
||||||
CobraFunc: func(cmd *cobra.Command) {
|
CobraFunc: func(cmd *cobra.Command) {
|
||||||
@@ -65,8 +60,6 @@ respond with a file listing.`,
|
|||||||
cmd.Flags().BoolP("templates", "t", false, "Enable template rendering")
|
cmd.Flags().BoolP("templates", "t", false, "Enable template rendering")
|
||||||
cmd.Flags().BoolP("access-log", "a", false, "Enable the access log")
|
cmd.Flags().BoolP("access-log", "a", false, "Enable the access log")
|
||||||
cmd.Flags().BoolP("debug", "v", false, "Enable verbose debug logs")
|
cmd.Flags().BoolP("debug", "v", false, "Enable verbose debug logs")
|
||||||
cmd.Flags().BoolP("no-compress", "", false, "Disable Zstandard and Gzip compression")
|
|
||||||
cmd.Flags().StringSliceP("precompressed", "p", []string{}, "Specify precompression file extensions. Compression preference implied from flag order.")
|
|
||||||
cmd.RunE = caddycmd.WrapCommandFuncForCobra(cmdFileServer)
|
cmd.RunE = caddycmd.WrapCommandFuncForCobra(cmdFileServer)
|
||||||
cmd.AddCommand(&cobra.Command{
|
cmd.AddCommand(&cobra.Command{
|
||||||
Use: "export-template",
|
Use: "export-template",
|
||||||
@@ -91,64 +84,15 @@ func cmdFileServer(fs caddycmd.Flags) (int, error) {
|
|||||||
templates := fs.Bool("templates")
|
templates := fs.Bool("templates")
|
||||||
accessLog := fs.Bool("access-log")
|
accessLog := fs.Bool("access-log")
|
||||||
debug := fs.Bool("debug")
|
debug := fs.Bool("debug")
|
||||||
compress := !fs.Bool("no-compress")
|
|
||||||
precompressed, err := fs.GetStringSlice("precompressed")
|
|
||||||
if err != nil {
|
|
||||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("invalid precompressed flag: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var handlers []json.RawMessage
|
var handlers []json.RawMessage
|
||||||
|
|
||||||
if compress {
|
|
||||||
zstd, err := caddy.GetModule("http.encoders.zstd")
|
|
||||||
if err != nil {
|
|
||||||
return caddy.ExitCodeFailedStartup, err
|
|
||||||
}
|
|
||||||
|
|
||||||
gzip, err := caddy.GetModule("http.encoders.gzip")
|
|
||||||
if err != nil {
|
|
||||||
return caddy.ExitCodeFailedStartup, err
|
|
||||||
}
|
|
||||||
|
|
||||||
handlers = append(handlers, caddyconfig.JSONModuleObject(encode.Encode{
|
|
||||||
EncodingsRaw: caddy.ModuleMap{
|
|
||||||
"zstd": caddyconfig.JSON(zstd.New(), nil),
|
|
||||||
"gzip": caddyconfig.JSON(gzip.New(), nil),
|
|
||||||
},
|
|
||||||
Prefer: []string{"zstd", "gzip"},
|
|
||||||
}, "handler", "encode", nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
if templates {
|
if templates {
|
||||||
handler := caddytpl.Templates{FileRoot: root}
|
handler := caddytpl.Templates{FileRoot: root}
|
||||||
handlers = append(handlers, caddyconfig.JSONModuleObject(handler, "handler", "templates", nil))
|
handlers = append(handlers, caddyconfig.JSONModuleObject(handler, "handler", "templates", nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
handler := FileServer{Root: root}
|
handler := FileServer{Root: root}
|
||||||
|
|
||||||
if len(precompressed) != 0 {
|
|
||||||
// logic mirrors modules/caddyhttp/fileserver/caddyfile.go case "precompressed"
|
|
||||||
var order []string
|
|
||||||
for _, compression := range precompressed {
|
|
||||||
modID := "http.precompressed." + compression
|
|
||||||
mod, err := caddy.GetModule(modID)
|
|
||||||
if err != nil {
|
|
||||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("getting module named '%s': %v", modID, err)
|
|
||||||
}
|
|
||||||
inst := mod.New()
|
|
||||||
precompress, ok := inst.(encode.Precompressed)
|
|
||||||
if !ok {
|
|
||||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("module %s is not a precompressor; is %T", modID, inst)
|
|
||||||
}
|
|
||||||
if handler.PrecompressedRaw == nil {
|
|
||||||
handler.PrecompressedRaw = make(caddy.ModuleMap)
|
|
||||||
}
|
|
||||||
handler.PrecompressedRaw[compression] = caddyconfig.JSON(precompress, nil)
|
|
||||||
order = append(order, compression)
|
|
||||||
}
|
|
||||||
handler.PrecompressedOrder = order
|
|
||||||
}
|
|
||||||
|
|
||||||
if browse {
|
if browse {
|
||||||
handler.Browse = new(Browse)
|
handler.Browse = new(Browse)
|
||||||
}
|
}
|
||||||
@@ -210,7 +154,7 @@ func cmdFileServer(fs caddycmd.Flags) (int, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = caddy.Run(cfg)
|
err := caddy.Run(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return caddy.ExitCodeFailedStartup, err
|
return caddy.ExitCodeFailedStartup, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,10 +38,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
caddy.RegisterNamespace("http.precompressed", []interface{}{
|
|
||||||
(*encode.Precompressed)(nil),
|
|
||||||
})
|
|
||||||
|
|
||||||
caddy.RegisterModule(FileServer{})
|
caddy.RegisterModule(FileServer{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,18 +151,6 @@ func (e *ExtraLogFields) Add(field zap.Field) {
|
|||||||
e.fields = append(e.fields, field)
|
e.fields = append(e.fields, field)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sets a field in the list of extra fields to log.
|
|
||||||
// If the field already exists, it is replaced.
|
|
||||||
func (e *ExtraLogFields) Set(field zap.Field) {
|
|
||||||
for i := range e.fields {
|
|
||||||
if e.fields[i].Key == field.Key {
|
|
||||||
e.fields[i] = field
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
e.fields = append(e.fields, field)
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Variable name used to indicate that this request
|
// Variable name used to indicate that this request
|
||||||
// should be omitted from the access logs
|
// should be omitted from the access logs
|
||||||
|
|||||||
@@ -197,8 +197,6 @@ type (
|
|||||||
// where each of the array elements is a matcher set, i.e. an
|
// where each of the array elements is a matcher set, i.e. an
|
||||||
// object keyed by matcher name.
|
// object keyed by matcher name.
|
||||||
MatchNot struct {
|
MatchNot struct {
|
||||||
// A `matcher` should implement the following interfaces:
|
|
||||||
// - [caddyhttp.RequestMatcher](https://pkg.go.dev/github.com/caddyserver/caddy/v2/modules/caddyhttp?tab=doc#RequestMatcher)
|
|
||||||
MatcherSetsRaw []caddy.ModuleMap `json:"-" caddy:"namespace=http.matchers"`
|
MatcherSetsRaw []caddy.ModuleMap `json:"-" caddy:"namespace=http.matchers"`
|
||||||
MatcherSets []MatcherSet `json:"-"`
|
MatcherSets []MatcherSet `json:"-"`
|
||||||
}
|
}
|
||||||
@@ -214,9 +212,6 @@ func init() {
|
|||||||
caddy.RegisterModule(MatchHeaderRE{})
|
caddy.RegisterModule(MatchHeaderRE{})
|
||||||
caddy.RegisterModule(new(MatchProtocol))
|
caddy.RegisterModule(new(MatchProtocol))
|
||||||
caddy.RegisterModule(MatchNot{})
|
caddy.RegisterModule(MatchNot{})
|
||||||
caddy.RegisterNamespace("http.matchers", []interface{}{
|
|
||||||
(*RequestMatcher)(nil),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaddyModule returns the Caddy module information.
|
// CaddyModule returns the Caddy module information.
|
||||||
|
|||||||
@@ -15,11 +15,11 @@
|
|||||||
package proxyprotocol
|
package proxyprotocol
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
goproxy "github.com/pires/go-proxyproto"
|
"github.com/mastercactapus/proxyprotocol"
|
||||||
|
|
||||||
"github.com/caddyserver/caddy/v2"
|
"github.com/caddyserver/caddy/v2"
|
||||||
)
|
)
|
||||||
@@ -38,74 +38,32 @@ type ListenerWrapper struct {
|
|||||||
// Allow is an optional list of CIDR ranges to
|
// Allow is an optional list of CIDR ranges to
|
||||||
// allow/require PROXY headers from.
|
// allow/require PROXY headers from.
|
||||||
Allow []string `json:"allow,omitempty"`
|
Allow []string `json:"allow,omitempty"`
|
||||||
allow []netip.Prefix
|
|
||||||
|
|
||||||
// Denby is an optional list of CIDR ranges to
|
rules []proxyprotocol.Rule
|
||||||
// deny PROXY headers from.
|
|
||||||
Deny []string `json:"deny,omitempty"`
|
|
||||||
deny []netip.Prefix
|
|
||||||
|
|
||||||
// Accepted values are: ignore, use, reject, require, skip
|
|
||||||
// default: ignore
|
|
||||||
// Policy definitions are here: https://pkg.go.dev/github.com/pires/go-proxyproto@v0.7.0#Policy
|
|
||||||
FallbackPolicy Policy `json:"fallback_policy,omitempty"`
|
|
||||||
|
|
||||||
policy goproxy.PolicyFunc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provision sets up the listener wrapper.
|
// Provision sets up the listener wrapper.
|
||||||
func (pp *ListenerWrapper) Provision(ctx caddy.Context) error {
|
func (pp *ListenerWrapper) Provision(ctx caddy.Context) error {
|
||||||
for _, cidr := range pp.Allow {
|
rules := make([]proxyprotocol.Rule, 0, len(pp.Allow))
|
||||||
ipnet, err := netip.ParsePrefix(cidr)
|
for _, s := range pp.Allow {
|
||||||
|
_, n, err := net.ParseCIDR(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("invalid subnet '%s': %w", s, err)
|
||||||
}
|
}
|
||||||
pp.allow = append(pp.allow, ipnet)
|
rules = append(rules, proxyprotocol.Rule{
|
||||||
}
|
Timeout: time.Duration(pp.Timeout),
|
||||||
for _, cidr := range pp.Deny {
|
Subnet: n,
|
||||||
ipnet, err := netip.ParsePrefix(cidr)
|
})
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
pp.deny = append(pp.deny, ipnet)
|
|
||||||
}
|
|
||||||
pp.policy = func(upstream net.Addr) (goproxy.Policy, error) {
|
|
||||||
// trust unix sockets
|
|
||||||
if network := upstream.Network(); caddy.IsUnixNetwork(network) {
|
|
||||||
return goproxy.USE, nil
|
|
||||||
}
|
|
||||||
ret := pp.FallbackPolicy
|
|
||||||
host, _, err := net.SplitHostPort(upstream.String())
|
|
||||||
if err != nil {
|
|
||||||
return goproxy.REJECT, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ip, err := netip.ParseAddr(host)
|
pp.rules = rules
|
||||||
if err != nil {
|
|
||||||
return goproxy.REJECT, err
|
|
||||||
}
|
|
||||||
for _, ipnet := range pp.deny {
|
|
||||||
if ipnet.Contains(ip) {
|
|
||||||
return goproxy.REJECT, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, ipnet := range pp.allow {
|
|
||||||
if ipnet.Contains(ip) {
|
|
||||||
ret = PolicyUSE
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return policyToGoProxyPolicy[ret], nil
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WrapListener adds PROXY protocol support to the listener.
|
// WrapListener adds PROXY protocol support to the listener.
|
||||||
func (pp *ListenerWrapper) WrapListener(l net.Listener) net.Listener {
|
func (pp *ListenerWrapper) WrapListener(l net.Listener) net.Listener {
|
||||||
pl := &goproxy.Listener{
|
pl := proxyprotocol.NewListener(l, time.Duration(pp.Timeout))
|
||||||
Listener: l,
|
pl.SetFilter(pp.rules)
|
||||||
ReadHeaderTimeout: time.Duration(pp.Timeout),
|
|
||||||
}
|
|
||||||
pl.Policy = pp.policy
|
|
||||||
return pl
|
return pl
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,6 @@ func (ListenerWrapper) CaddyModule() caddy.ModuleInfo {
|
|||||||
// proxy_protocol {
|
// proxy_protocol {
|
||||||
// timeout <duration>
|
// timeout <duration>
|
||||||
// allow <IPs...>
|
// allow <IPs...>
|
||||||
// deny <IPs...>
|
|
||||||
// fallback_policy <policy>
|
|
||||||
// }
|
// }
|
||||||
func (w *ListenerWrapper) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
func (w *ListenerWrapper) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
||||||
for d.Next() {
|
for d.Next() {
|
||||||
@@ -59,17 +57,7 @@ func (w *ListenerWrapper) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
|||||||
|
|
||||||
case "allow":
|
case "allow":
|
||||||
w.Allow = append(w.Allow, d.RemainingArgs()...)
|
w.Allow = append(w.Allow, d.RemainingArgs()...)
|
||||||
case "deny":
|
|
||||||
w.Deny = append(w.Deny, d.RemainingArgs()...)
|
|
||||||
case "fallback_policy":
|
|
||||||
if !d.NextArg() {
|
|
||||||
return d.ArgErr()
|
|
||||||
}
|
|
||||||
p, err := parsePolicy(d.Val())
|
|
||||||
if err != nil {
|
|
||||||
return d.WrapErr(err)
|
|
||||||
}
|
|
||||||
w.FallbackPolicy = p
|
|
||||||
default:
|
default:
|
||||||
return d.ArgErr()
|
return d.ArgErr()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
package proxyprotocol
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
goproxy "github.com/pires/go-proxyproto"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Policy int
|
|
||||||
|
|
||||||
// as defined in: https://pkg.go.dev/github.com/pires/go-proxyproto@v0.7.0#Policy
|
|
||||||
const (
|
|
||||||
// IGNORE address from PROXY header, but accept connection
|
|
||||||
PolicyIGNORE Policy = iota
|
|
||||||
// USE address from PROXY header
|
|
||||||
PolicyUSE
|
|
||||||
// REJECT connection when PROXY header is sent
|
|
||||||
// Note: even though the first read on the connection returns an error if
|
|
||||||
// a PROXY header is present, subsequent reads do not. It is the task of
|
|
||||||
// the code using the connection to handle that case properly.
|
|
||||||
PolicyREJECT
|
|
||||||
// REQUIRE connection to send PROXY header, reject if not present
|
|
||||||
// Note: even though the first read on the connection returns an error if
|
|
||||||
// a PROXY header is not present, subsequent reads do not. It is the task
|
|
||||||
// of the code using the connection to handle that case properly.
|
|
||||||
PolicyREQUIRE
|
|
||||||
// SKIP accepts a connection without requiring the PROXY header
|
|
||||||
// Note: an example usage can be found in the SkipProxyHeaderForCIDR
|
|
||||||
// function.
|
|
||||||
PolicySKIP
|
|
||||||
)
|
|
||||||
|
|
||||||
var policyToGoProxyPolicy = map[Policy]goproxy.Policy{
|
|
||||||
PolicyUSE: goproxy.USE,
|
|
||||||
PolicyIGNORE: goproxy.IGNORE,
|
|
||||||
PolicyREJECT: goproxy.REJECT,
|
|
||||||
PolicyREQUIRE: goproxy.REQUIRE,
|
|
||||||
PolicySKIP: goproxy.SKIP,
|
|
||||||
}
|
|
||||||
|
|
||||||
var policyMap = map[Policy]string{
|
|
||||||
PolicyUSE: "USE",
|
|
||||||
PolicyIGNORE: "IGNORE",
|
|
||||||
PolicyREJECT: "REJECT",
|
|
||||||
PolicyREQUIRE: "REQUIRE",
|
|
||||||
PolicySKIP: "SKIP",
|
|
||||||
}
|
|
||||||
|
|
||||||
var policyMapRev = map[string]Policy{
|
|
||||||
"USE": PolicyUSE,
|
|
||||||
"IGNORE": PolicyIGNORE,
|
|
||||||
"REJECT": PolicyREJECT,
|
|
||||||
"REQUIRE": PolicyREQUIRE,
|
|
||||||
"SKIP": PolicySKIP,
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalText implements the text marshaller method.
|
|
||||||
func (x Policy) MarshalText() ([]byte, error) {
|
|
||||||
return []byte(policyMap[x]), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalText implements the text unmarshaller method.
|
|
||||||
func (x *Policy) UnmarshalText(text []byte) error {
|
|
||||||
name := string(text)
|
|
||||||
tmp, err := parsePolicy(name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*x = tmp
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parsePolicy(name string) (Policy, error) {
|
|
||||||
if x, ok := policyMapRev[strings.ToUpper(name)]; ok {
|
|
||||||
return x, nil
|
|
||||||
}
|
|
||||||
return Policy(0), fmt.Errorf("%s is %w", name, errInvalidPolicy)
|
|
||||||
}
|
|
||||||
|
|
||||||
var errInvalidPolicy = errors.New("invalid policy")
|
|
||||||
@@ -40,7 +40,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/caddyserver/caddy/v2"
|
"github.com/caddyserver/caddy/v2"
|
||||||
"github.com/caddyserver/caddy/v2/modules/caddytls"
|
"github.com/caddyserver/caddy/v2/modules/caddytls"
|
||||||
@@ -158,17 +157,9 @@ func addHTTPVarsToReplacer(repl *caddy.Replacer, req *http.Request, w http.Respo
|
|||||||
case "http.request.duration_ms":
|
case "http.request.duration_ms":
|
||||||
start := GetVar(req.Context(), "start_time").(time.Time)
|
start := GetVar(req.Context(), "start_time").(time.Time)
|
||||||
return time.Since(start).Seconds() * 1e3, true // multiply seconds to preserve decimal (see #4666)
|
return time.Since(start).Seconds() * 1e3, true // multiply seconds to preserve decimal (see #4666)
|
||||||
|
|
||||||
case "http.request.uuid":
|
case "http.request.uuid":
|
||||||
// fetch the UUID for this request
|
|
||||||
id := GetVar(req.Context(), "uuid").(*requestID)
|
id := GetVar(req.Context(), "uuid").(*requestID)
|
||||||
|
|
||||||
// set it to this request's access log
|
|
||||||
extra := req.Context().Value(ExtraLogFieldsCtxKey).(*ExtraLogFields)
|
|
||||||
extra.Set(zap.String("uuid", id.String()))
|
|
||||||
|
|
||||||
return id.String(), true
|
return id.String(), true
|
||||||
|
|
||||||
case "http.request.body":
|
case "http.request.body":
|
||||||
if req.Body == nil {
|
if req.Body == nil {
|
||||||
return "", true
|
return "", true
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pires/go-proxyproto"
|
"github.com/mastercactapus/proxyprotocol"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
|
|
||||||
@@ -207,42 +207,44 @@ func (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, e
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("failed to get proxy protocol info from context")
|
return nil, fmt.Errorf("failed to get proxy protocol info from context")
|
||||||
}
|
}
|
||||||
header := proxyproto.Header{
|
|
||||||
SourceAddr: &net.TCPAddr{
|
// The src and dst have to be of the some address family. As we don't know the original
|
||||||
IP: proxyProtocolInfo.AddrPort.Addr().AsSlice(),
|
// dst address (it's kind of impossible to know) and this address is generelly of very
|
||||||
Port: int(proxyProtocolInfo.AddrPort.Port()),
|
|
||||||
Zone: proxyProtocolInfo.AddrPort.Addr().Zone(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// The src and dst have to be of the same address family. As we don't know the original
|
|
||||||
// dst address (it's kind of impossible to know) and this address is generally of very
|
|
||||||
// little interest, we just set it to all zeros.
|
// little interest, we just set it to all zeros.
|
||||||
|
var destIP net.IP
|
||||||
switch {
|
switch {
|
||||||
case proxyProtocolInfo.AddrPort.Addr().Is4():
|
case proxyProtocolInfo.AddrPort.Addr().Is4():
|
||||||
header.TransportProtocol = proxyproto.TCPv4
|
destIP = net.IPv4zero
|
||||||
header.DestinationAddr = &net.TCPAddr{
|
|
||||||
IP: net.IPv4zero,
|
|
||||||
}
|
|
||||||
case proxyProtocolInfo.AddrPort.Addr().Is6():
|
case proxyProtocolInfo.AddrPort.Addr().Is6():
|
||||||
header.TransportProtocol = proxyproto.TCPv6
|
destIP = net.IPv6zero
|
||||||
header.DestinationAddr = &net.TCPAddr{
|
|
||||||
IP: net.IPv6zero,
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unexpected remote addr type in proxy protocol info")
|
return nil, fmt.Errorf("unexpected remote addr type in proxy protocol info")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: We should probably migrate away from net.IP to use netip.Addr,
|
||||||
|
// but due to the upstream dependency, we can't do that yet.
|
||||||
switch h.ProxyProtocol {
|
switch h.ProxyProtocol {
|
||||||
case "v1":
|
case "v1":
|
||||||
header.Version = 1
|
header := proxyprotocol.HeaderV1{
|
||||||
|
SrcIP: net.IP(proxyProtocolInfo.AddrPort.Addr().AsSlice()),
|
||||||
|
SrcPort: int(proxyProtocolInfo.AddrPort.Port()),
|
||||||
|
DestIP: destIP,
|
||||||
|
DestPort: 0,
|
||||||
|
}
|
||||||
caddyCtx.Logger().Debug("sending proxy protocol header v1", zap.Any("header", header))
|
caddyCtx.Logger().Debug("sending proxy protocol header v1", zap.Any("header", header))
|
||||||
|
_, err = header.WriteTo(conn)
|
||||||
case "v2":
|
case "v2":
|
||||||
header.Version = 2
|
header := proxyprotocol.HeaderV2{
|
||||||
|
Command: proxyprotocol.CmdProxy,
|
||||||
|
Src: &net.TCPAddr{IP: net.IP(proxyProtocolInfo.AddrPort.Addr().AsSlice()), Port: int(proxyProtocolInfo.AddrPort.Port())},
|
||||||
|
Dest: &net.TCPAddr{IP: destIP, Port: 0},
|
||||||
|
}
|
||||||
caddyCtx.Logger().Debug("sending proxy protocol header v2", zap.Any("header", header))
|
caddyCtx.Logger().Debug("sending proxy protocol header v2", zap.Any("header", header))
|
||||||
|
_, err = header.WriteTo(conn)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unexpected proxy protocol version")
|
return nil, fmt.Errorf("unexpected proxy protocol version")
|
||||||
}
|
}
|
||||||
_, err = header.WriteTo(conn)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// identify this error as one that occurred during
|
// identify this error as one that occurred during
|
||||||
// dialing, which can be important when trying to
|
// dialing, which can be important when trying to
|
||||||
|
|||||||
@@ -45,19 +45,6 @@ import (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
caddy.RegisterModule(Handler{})
|
caddy.RegisterModule(Handler{})
|
||||||
|
|
||||||
caddy.RegisterNamespace("http.reverse_proxy.circuit_breakers", []interface{}{
|
|
||||||
(*CircuitBreaker)(nil),
|
|
||||||
})
|
|
||||||
caddy.RegisterNamespace("http.reverse_proxy.selection_policies", []interface{}{
|
|
||||||
(*Selector)(nil),
|
|
||||||
})
|
|
||||||
caddy.RegisterNamespace("http.reverse_proxy.transport", []interface{}{
|
|
||||||
(*http.RoundTripper)(nil),
|
|
||||||
})
|
|
||||||
caddy.RegisterNamespace("http.reverse_proxy.upstreams", []interface{}{
|
|
||||||
(*UpstreamSource)(nil),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler implements a highly configurable and production-ready reverse proxy.
|
// Handler implements a highly configurable and production-ready reverse proxy.
|
||||||
|
|||||||
@@ -22,12 +22,6 @@ import (
|
|||||||
"github.com/caddyserver/caddy/v2"
|
"github.com/caddyserver/caddy/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
caddy.RegisterNamespace("http.handlers", []interface{}{
|
|
||||||
(*MiddlewareHandler)(nil),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Route consists of a set of rules for matching HTTP requests,
|
// Route consists of a set of rules for matching HTTP requests,
|
||||||
// a list of handlers to execute, and optional flow control
|
// a list of handlers to execute, and optional flow control
|
||||||
// parameters which customize the handling of HTTP requests
|
// parameters which customize the handling of HTTP requests
|
||||||
|
|||||||
@@ -30,18 +30,6 @@ import (
|
|||||||
"github.com/caddyserver/caddy/v2"
|
"github.com/caddyserver/caddy/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
caddy.RegisterNamespace("dns.provider", []interface{}{
|
|
||||||
(*acmez.Solver)(nil),
|
|
||||||
})
|
|
||||||
caddy.RegisterNamespace("tls.get_certificate", []interface{}{
|
|
||||||
(*certmagic.Manager)(nil),
|
|
||||||
})
|
|
||||||
caddy.RegisterNamespace("tls.issuance", []interface{}{
|
|
||||||
(*certmagic.Issuer)(nil),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// AutomationConfig governs the automated management of TLS certificates.
|
// AutomationConfig governs the automated management of TLS certificates.
|
||||||
type AutomationConfig struct {
|
type AutomationConfig struct {
|
||||||
// The list of automation policies. The first policy matching
|
// The list of automation policies. The first policy matching
|
||||||
|
|||||||
@@ -33,9 +33,6 @@ import (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
caddy.RegisterModule(LeafCertClientAuth{})
|
caddy.RegisterModule(LeafCertClientAuth{})
|
||||||
caddy.RegisterNamespace("tls.handshake_match", []interface{}{
|
|
||||||
(*ConnectionMatcher)(nil),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConnectionPolicies govern the establishment of TLS connections. It is
|
// ConnectionPolicies govern the establishment of TLS connections. It is
|
||||||
|
|||||||
@@ -28,12 +28,6 @@ import (
|
|||||||
"github.com/caddyserver/caddy/v2"
|
"github.com/caddyserver/caddy/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
caddy.RegisterNamespace("tls.stek", []interface{}{
|
|
||||||
(*STEKProvider)(nil),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// SessionTicketService configures and manages TLS session tickets.
|
// SessionTicketService configures and manages TLS session tickets.
|
||||||
type SessionTicketService struct {
|
type SessionTicketService struct {
|
||||||
// KeySource is the method by which Caddy produces or obtains
|
// KeySource is the method by which Caddy produces or obtains
|
||||||
|
|||||||
@@ -35,10 +35,6 @@ import (
|
|||||||
func init() {
|
func init() {
|
||||||
caddy.RegisterModule(TLS{})
|
caddy.RegisterModule(TLS{})
|
||||||
caddy.RegisterModule(AutomateLoader{})
|
caddy.RegisterModule(AutomateLoader{})
|
||||||
|
|
||||||
caddy.RegisterNamespace("tls.certificates", []interface{}{
|
|
||||||
(*CertificateLoader)(nil),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -656,11 +652,6 @@ func (AutomateLoader) CaddyModule() caddy.ModuleInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadCertificates is a stub so AutomateLoader can implement CertificateLoader
|
|
||||||
func (AutomateLoader) LoadCertificates() ([]Certificate, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CertCacheOptions configures the certificate cache.
|
// CertCacheOptions configures the certificate cache.
|
||||||
type CertCacheOptions struct {
|
type CertCacheOptions struct {
|
||||||
// Maximum number of certificates to allow in the
|
// Maximum number of certificates to allow in the
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
package caddy
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
var namespaceTypes map[string][]reflect.Type = make(map[string][]reflect.Type)
|
|
||||||
|
|
||||||
func RegisterNamespace(namespace string, vals []interface{}) {
|
|
||||||
var types []reflect.Type
|
|
||||||
for _, v := range vals {
|
|
||||||
reflect.TypeOf(v).Elem()
|
|
||||||
}
|
|
||||||
if _, ok := namespaceTypes[namespace]; ok {
|
|
||||||
panic("namespace is already registered")
|
|
||||||
}
|
|
||||||
namespaceTypes[namespace] = types
|
|
||||||
}
|
|
||||||
|
|
||||||
// NamespaceTypes returns a copy of Caddy's namespace->type registry
|
|
||||||
func NamespaceTypes() map[string][]reflect.Type {
|
|
||||||
copy := make(map[string][]reflect.Type)
|
|
||||||
for namespace, typeSlice := range namespaceTypes {
|
|
||||||
copy[namespace] = typeSlice
|
|
||||||
}
|
|
||||||
return copy
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConformsToNamespace validates the given module implements all the mandatory types of a given namespace
|
|
||||||
func ConformsToNamespace(mod Module, namespace string) (bool, error) {
|
|
||||||
modType := reflect.TypeOf(mod)
|
|
||||||
for _, t := range namespaceTypes[namespace] {
|
|
||||||
if !modType.Implements(t) {
|
|
||||||
return false, fmt.Errorf("%s does not implement %s", modType, t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user