mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-14 14:56:27 +03:00
Improve godocs all around
These will be used in the new automated documentation system
This commit is contained in:
parent
cbb405f6aa
commit
95ed603de7
26 changed files with 388 additions and 99 deletions
|
@ -28,9 +28,14 @@ func init() {
|
||||||
|
|
||||||
// HTTPBasicAuth facilitates HTTP basic authentication.
|
// HTTPBasicAuth facilitates HTTP basic authentication.
|
||||||
type HTTPBasicAuth struct {
|
type HTTPBasicAuth struct {
|
||||||
HashRaw json.RawMessage `json:"hash,omitempty" caddy:"namespace=http.authentication.hashes inline_key=algorithm"`
|
// The algorithm with which the passwords are hashed. Default: bcrypt
|
||||||
AccountList []Account `json:"accounts,omitempty"`
|
HashRaw json.RawMessage `json:"hash,omitempty" caddy:"namespace=http.authentication.hashes inline_key=algorithm"`
|
||||||
Realm string `json:"realm,omitempty"`
|
|
||||||
|
// The list of accounts to authenticate.
|
||||||
|
AccountList []Account `json:"accounts,omitempty"`
|
||||||
|
|
||||||
|
// The name of the realm. Default: restricted
|
||||||
|
Realm string `json:"realm,omitempty"`
|
||||||
|
|
||||||
Accounts map[string]Account `json:"-"`
|
Accounts map[string]Account `json:"-"`
|
||||||
Hash Comparer `json:"-"`
|
Hash Comparer `json:"-"`
|
||||||
|
@ -125,9 +130,15 @@ type Comparer interface {
|
||||||
|
|
||||||
// Account contains a username, password, and salt (if applicable).
|
// Account contains a username, password, and salt (if applicable).
|
||||||
type Account struct {
|
type Account struct {
|
||||||
|
// A user's username.
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
|
|
||||||
|
// The user's hashed password, base64-encoded.
|
||||||
Password []byte `json:"password"`
|
Password []byte `json:"password"`
|
||||||
Salt []byte `json:"salt,omitempty"` // for algorithms where external salt is needed
|
|
||||||
|
// The user's password salt, base64-encoded; for
|
||||||
|
// algorithms where external salt is needed.
|
||||||
|
Salt []byte `json:"salt,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interface guards
|
// Interface guards
|
||||||
|
|
|
@ -28,7 +28,10 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authentication is a middleware which provides user authentication.
|
// Authentication is a middleware which provides user authentication.
|
||||||
|
// Rejects requests with HTTP 401 if the request is not authenticated.
|
||||||
type Authentication struct {
|
type Authentication struct {
|
||||||
|
// A set of authentication providers. If none are specified,
|
||||||
|
// all requests will always be unauthenticated.
|
||||||
ProvidersRaw caddy.ModuleMap `json:"providers,omitempty" caddy:"namespace=http.authentication.providers"`
|
ProvidersRaw caddy.ModuleMap `json:"providers,omitempty" caddy:"namespace=http.authentication.providers"`
|
||||||
|
|
||||||
Providers map[string]Authenticator `json:"-"`
|
Providers map[string]Authenticator `json:"-"`
|
||||||
|
|
|
@ -52,9 +52,17 @@ func (BcryptHash) Compare(hashed, plaintext, _ []byte) (bool, error) {
|
||||||
|
|
||||||
// ScryptHash implements the scrypt KDF as a hash.
|
// ScryptHash implements the scrypt KDF as a hash.
|
||||||
type ScryptHash struct {
|
type ScryptHash struct {
|
||||||
N int `json:"N,omitempty"`
|
// scrypt's N parameter. If unset or 0, a safe default is used.
|
||||||
R int `json:"r,omitempty"`
|
N int `json:"N,omitempty"`
|
||||||
P int `json:"p,omitempty"`
|
|
||||||
|
// scrypt's r parameter. If unset or 0, a safe default is used.
|
||||||
|
R int `json:"r,omitempty"`
|
||||||
|
|
||||||
|
// scrypt's p parameter. If unset or 0, a safe default is used.
|
||||||
|
P int `json:"p,omitempty"`
|
||||||
|
|
||||||
|
// scrypt's key length parameter (in bytes). If unset or 0, a
|
||||||
|
// safe default is used.
|
||||||
KeyLength int `json:"key_length,omitempty"`
|
KeyLength int `json:"key_length,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,9 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Brotli can create brotli encoders. Note that brotli
|
// Brotli can create brotli encoders. Note that brotli
|
||||||
// is not known for great encoding performance.
|
// is not known for great encoding performance, and
|
||||||
|
// its use during requests is discouraged; instead,
|
||||||
|
// pre-compress the content instead.
|
||||||
type Brotli struct {
|
type Brotli struct {
|
||||||
Quality *int `json:"quality,omitempty"`
|
Quality *int `json:"quality,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,9 +39,15 @@ func init() {
|
||||||
|
|
||||||
// Encode is a middleware which can encode responses.
|
// Encode is a middleware which can encode responses.
|
||||||
type Encode struct {
|
type Encode struct {
|
||||||
|
// Selection of compression algorithms to choose from. The best one
|
||||||
|
// will be chosen based on the client's Accept-Encoding header.
|
||||||
EncodingsRaw caddy.ModuleMap `json:"encodings,omitempty" caddy:"namespace=http.encoders"`
|
EncodingsRaw caddy.ModuleMap `json:"encodings,omitempty" caddy:"namespace=http.encoders"`
|
||||||
Prefer []string `json:"prefer,omitempty"`
|
|
||||||
MinLength int `json:"minimum_length,omitempty"`
|
// If the client has no strong preference, choose this encoding. TODO: Not yet implemented
|
||||||
|
// Prefer []string `json:"prefer,omitempty"`
|
||||||
|
|
||||||
|
// Only encode responses that are at least this many bytes long.
|
||||||
|
MinLength int `json:"minimum_length,omitempty"`
|
||||||
|
|
||||||
writerPools map[string]*sync.Pool // TODO: these pools do not get reused through config reloads...
|
writerPools map[string]*sync.Pool // TODO: these pools do not get reused through config reloads...
|
||||||
}
|
}
|
||||||
|
@ -66,11 +72,9 @@ func (enc *Encode) Provision(ctx caddy.Context) error {
|
||||||
return fmt.Errorf("adding encoding %s: %v", modName, err)
|
return fmt.Errorf("adding encoding %s: %v", modName, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if enc.MinLength == 0 {
|
if enc.MinLength == 0 {
|
||||||
enc.MinLength = defaultMinLength
|
enc.MinLength = defaultMinLength
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ import (
|
||||||
|
|
||||||
// Browse configures directory browsing.
|
// Browse configures directory browsing.
|
||||||
type Browse struct {
|
type Browse struct {
|
||||||
|
// Use this template file instead of the default browse template.
|
||||||
TemplateFile string `json:"template_file,omitempty"`
|
TemplateFile string `json:"template_file,omitempty"`
|
||||||
|
|
||||||
template *template.Template
|
template *template.Template
|
||||||
|
|
|
@ -46,7 +46,13 @@ type MatchFile struct {
|
||||||
// placeholders.
|
// placeholders.
|
||||||
TryFiles []string `json:"try_files,omitempty"`
|
TryFiles []string `json:"try_files,omitempty"`
|
||||||
|
|
||||||
// How to choose a file in TryFiles.
|
// How to choose a file in TryFiles. Can be:
|
||||||
|
//
|
||||||
|
// - first_exist
|
||||||
|
// - smallest_size
|
||||||
|
// - largest_size
|
||||||
|
// - most_recently_modified
|
||||||
|
//
|
||||||
// Default is first_exist.
|
// Default is first_exist.
|
||||||
TryPolicy string `json:"try_policy,omitempty"`
|
TryPolicy string `json:"try_policy,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -64,7 +70,7 @@ func (MatchFile) CaddyModule() caddy.ModuleInfo {
|
||||||
// file {
|
// file {
|
||||||
// root <path>
|
// root <path>
|
||||||
// try_files <files...>
|
// try_files <files...>
|
||||||
// try_policy first_exist|smallest_size|largest_size|most_recent_modified
|
// try_policy first_exist|smallest_size|largest_size|most_recently_modified
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
func (m *MatchFile) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
func (m *MatchFile) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
||||||
|
@ -107,7 +113,7 @@ func (m MatchFile) Validate() error {
|
||||||
tryPolicyFirstExist,
|
tryPolicyFirstExist,
|
||||||
tryPolicyLargestSize,
|
tryPolicyLargestSize,
|
||||||
tryPolicySmallestSize,
|
tryPolicySmallestSize,
|
||||||
tryPolicyMostRecentMod:
|
tryPolicyMostRecentlyMod:
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown try policy %s", m.TryPolicy)
|
return fmt.Errorf("unknown try policy %s", m.TryPolicy)
|
||||||
}
|
}
|
||||||
|
@ -187,7 +193,7 @@ func (m MatchFile) selectFile(r *http.Request) (rel, abs string, matched bool) {
|
||||||
}
|
}
|
||||||
return smallestSuffix, smallestFilename, true
|
return smallestSuffix, smallestFilename, true
|
||||||
|
|
||||||
case tryPolicyMostRecentMod:
|
case tryPolicyMostRecentlyMod:
|
||||||
var recentDate time.Time
|
var recentDate time.Time
|
||||||
var recentFilename string
|
var recentFilename string
|
||||||
var recentSuffix string
|
var recentSuffix string
|
||||||
|
@ -238,10 +244,10 @@ func strictFileExists(file string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tryPolicyFirstExist = "first_exist"
|
tryPolicyFirstExist = "first_exist"
|
||||||
tryPolicyLargestSize = "largest_size"
|
tryPolicyLargestSize = "largest_size"
|
||||||
tryPolicySmallestSize = "smallest_size"
|
tryPolicySmallestSize = "smallest_size"
|
||||||
tryPolicyMostRecentMod = "most_recent_modified"
|
tryPolicyMostRecentlyMod = "most_recently_modified"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Interface guards
|
// Interface guards
|
||||||
|
|
|
@ -42,12 +42,29 @@ func init() {
|
||||||
|
|
||||||
// FileServer implements a static file server responder for Caddy.
|
// FileServer implements a static file server responder for Caddy.
|
||||||
type FileServer struct {
|
type FileServer struct {
|
||||||
Root string `json:"root,omitempty"` // default is current directory
|
// The path to the root of the site. Default is `{http.vars.root}` if set,
|
||||||
Hide []string `json:"hide,omitempty"`
|
// or current working directory otherwise.
|
||||||
IndexNames []string `json:"index_names,omitempty"`
|
Root string `json:"root,omitempty"`
|
||||||
Browse *Browse `json:"browse,omitempty"`
|
|
||||||
CanonicalURIs *bool `json:"canonical_uris,omitempty"`
|
// A list of files or folders to hide; the file server will pretend as if
|
||||||
PassThru bool `json:"pass_thru,omitempty"` // if 404, call next handler instead
|
// they don't exist. Accepts globular patterns like "*.hidden" or "/foo/*/bar".
|
||||||
|
Hide []string `json:"hide,omitempty"`
|
||||||
|
|
||||||
|
// The names of files to try as index files if a folder is requested.
|
||||||
|
IndexNames []string `json:"index_names,omitempty"`
|
||||||
|
|
||||||
|
// Enables file listings if a directory was requested and no index
|
||||||
|
// file is present.
|
||||||
|
Browse *Browse `json:"browse,omitempty"`
|
||||||
|
|
||||||
|
// Use redirects to enforce trailing slashes for directories, or to
|
||||||
|
// remove trailing slash from URIs for files. Default is true.
|
||||||
|
CanonicalURIs *bool `json:"canonical_uris,omitempty"`
|
||||||
|
|
||||||
|
// If pass-thru mode is enabled and a requested file is not found,
|
||||||
|
// it will invoke the next handler in the chain instead of returning
|
||||||
|
// a 404 error. By default, this is false (disabled).
|
||||||
|
PassThru bool `json:"pass_thru,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaddyModule returns the Caddy module information.
|
// CaddyModule returns the Caddy module information.
|
||||||
|
|
|
@ -28,7 +28,18 @@ func init() {
|
||||||
caddy.RegisterModule(Handler{})
|
caddy.RegisterModule(Handler{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler is a middleware which can mutate HTTP headers.
|
// Handler is a middleware which modifies request and response headers.
|
||||||
|
//
|
||||||
|
// Changes to headers are applied immediately, except for the response
|
||||||
|
// headers when Deferred is true or when Required is set. In those cases,
|
||||||
|
// the changes are applied when the headers are written to the response.
|
||||||
|
// Note that deferred changes do not take effect if an error occurs later
|
||||||
|
// in the middleware chain.
|
||||||
|
//
|
||||||
|
// Properties in this module accept placeholders.
|
||||||
|
//
|
||||||
|
// Response header operations can be conditioned upon response status code
|
||||||
|
// and/or other header values.
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
Request *HeaderOps `json:"request,omitempty"`
|
Request *HeaderOps `json:"request,omitempty"`
|
||||||
Response *RespHeaderOps `json:"response,omitempty"`
|
Response *RespHeaderOps `json:"response,omitempty"`
|
||||||
|
@ -99,12 +110,18 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhtt
|
||||||
return next.ServeHTTP(w, r)
|
return next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HeaderOps defines some operations to
|
// HeaderOps defines manipulations for HTTP headers.
|
||||||
// perform on HTTP headers.
|
|
||||||
type HeaderOps struct {
|
type HeaderOps struct {
|
||||||
Add http.Header `json:"add,omitempty"`
|
// Adds HTTP headers; does not replace any existing header fields.
|
||||||
Set http.Header `json:"set,omitempty"`
|
Add http.Header `json:"add,omitempty"`
|
||||||
Delete []string `json:"delete,omitempty"`
|
|
||||||
|
// Sets HTTP headers; replaces existing header fields.
|
||||||
|
Set http.Header `json:"set,omitempty"`
|
||||||
|
|
||||||
|
// Names of HTTP header fields to delete.
|
||||||
|
Delete []string `json:"delete,omitempty"`
|
||||||
|
|
||||||
|
// Performs substring replacements of HTTP headers in-situ.
|
||||||
Replace map[string][]Replacement `json:"replace,omitempty"`
|
Replace map[string][]Replacement `json:"replace,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,22 +152,33 @@ func (ops HeaderOps) validate() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replacement describes a string replacement,
|
// Replacement describes a string replacement,
|
||||||
// either a simple and fast sugbstring search
|
// either a simple and fast substring search
|
||||||
// or a slower but more powerful regex search.
|
// or a slower but more powerful regex search.
|
||||||
type Replacement struct {
|
type Replacement struct {
|
||||||
Search string `json:"search,omitempty"`
|
// The substring to search for.
|
||||||
|
Search string `json:"search,omitempty"`
|
||||||
|
|
||||||
|
// The regular expression to search with.
|
||||||
SearchRegexp string `json:"search_regexp,omitempty"`
|
SearchRegexp string `json:"search_regexp,omitempty"`
|
||||||
Replace string `json:"replace,omitempty"`
|
|
||||||
|
// The string with which to replace matches.
|
||||||
|
Replace string `json:"replace,omitempty"`
|
||||||
|
|
||||||
re *regexp.Regexp
|
re *regexp.Regexp
|
||||||
}
|
}
|
||||||
|
|
||||||
// RespHeaderOps is like HeaderOps, but
|
// RespHeaderOps defines manipulations for response headers.
|
||||||
// optionally deferred until response time.
|
|
||||||
type RespHeaderOps struct {
|
type RespHeaderOps struct {
|
||||||
*HeaderOps
|
*HeaderOps
|
||||||
Require *caddyhttp.ResponseMatcher `json:"require,omitempty"`
|
|
||||||
Deferred bool `json:"deferred,omitempty"`
|
// If set, header operations will be deferred until
|
||||||
|
// they are written out and only performed if the
|
||||||
|
// response matches these criteria.
|
||||||
|
Require *caddyhttp.ResponseMatcher `json:"require,omitempty"`
|
||||||
|
|
||||||
|
// If true, header operations will be deferred until
|
||||||
|
// they are written out. Superceded if Require is set.
|
||||||
|
Deferred bool `json:"deferred,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyTo applies ops to hdr using repl.
|
// ApplyTo applies ops to hdr using repl.
|
||||||
|
|
|
@ -33,11 +33,33 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache implements a simple distributed cache.
|
// Cache implements a simple distributed cache.
|
||||||
|
//
|
||||||
|
// NOTE: This module is a work-in-progress. It is
|
||||||
|
// not finished and is NOT ready for production use.
|
||||||
|
// [We need your help to finish it! Please volunteer
|
||||||
|
// in this issue.](https://github.com/caddyserver/caddy/issues/2820)
|
||||||
|
// Until it is finished, this module is subject to
|
||||||
|
// breaking changes.
|
||||||
|
//
|
||||||
|
// Caches only GET and HEAD requests. Honors the Cache-Control: no-cache header.
|
||||||
|
//
|
||||||
|
// Still TODO:
|
||||||
|
//
|
||||||
|
// - Eviction policies and API
|
||||||
|
// - Use single cache per-process
|
||||||
|
// - Preserve cache through config reloads
|
||||||
|
// - More control over what gets cached
|
||||||
type Cache struct {
|
type Cache struct {
|
||||||
Self string `json:"self,omitempty"`
|
// The network address of this cache instance; required.
|
||||||
Peers []string `json:"peers,omitempty"`
|
Self string `json:"self,omitempty"`
|
||||||
MaxSize int64 `json:"max_size,omitempty"`
|
|
||||||
group *groupcache.Group
|
// A list of network addresses of cache instances in the group.
|
||||||
|
Peers []string `json:"peers,omitempty"`
|
||||||
|
|
||||||
|
// Maximum size of the cache, in bytes. Default is 512 MB.
|
||||||
|
MaxSize int64 `json:"max_size,omitempty"`
|
||||||
|
|
||||||
|
group *groupcache.Group
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaddyModule returns the Caddy module information.
|
// CaddyModule returns the Caddy module information.
|
||||||
|
|
|
@ -695,8 +695,8 @@ func (mre *MatchRegexp) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResponseMatcher is a type which can determine if a given response
|
// ResponseMatcher is a type which can determine if an
|
||||||
// status code and its headers match some criteria.
|
// HTTP response matches some criteria.
|
||||||
type ResponseMatcher struct {
|
type ResponseMatcher struct {
|
||||||
// If set, one of these status codes would be required.
|
// If set, one of these status codes would be required.
|
||||||
// A one-digit status can be used to represent all codes
|
// A one-digit status can be used to represent all codes
|
||||||
|
|
|
@ -27,6 +27,7 @@ func init() {
|
||||||
|
|
||||||
// RequestBody is a middleware for manipulating the request body.
|
// RequestBody is a middleware for manipulating the request body.
|
||||||
type RequestBody struct {
|
type RequestBody struct {
|
||||||
|
// The maximum number of bytes to allow reading from the body by a later handler.
|
||||||
MaxSize int64 `json:"max_size,omitempty"`
|
MaxSize int64 `json:"max_size,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ type Transport struct {
|
||||||
// that 404's if the fastcgi path info is not found.
|
// that 404's if the fastcgi path info is not found.
|
||||||
SplitPath string `json:"split_path,omitempty"`
|
SplitPath string `json:"split_path,omitempty"`
|
||||||
|
|
||||||
// Extra environment variables
|
// Extra environment variables.
|
||||||
EnvVars map[string]string `json:"env,omitempty"`
|
EnvVars map[string]string `json:"env,omitempty"`
|
||||||
|
|
||||||
// The duration used to set a deadline when connecting to an upstream.
|
// The duration used to set a deadline when connecting to an upstream.
|
||||||
|
|
|
@ -31,9 +31,16 @@ import (
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HealthChecks holds configuration related to health checking.
|
// HealthChecks configures active and passive health checks.
|
||||||
type HealthChecks struct {
|
type HealthChecks struct {
|
||||||
Active *ActiveHealthChecks `json:"active,omitempty"`
|
// Active health checks run in the background on a timer. To
|
||||||
|
// minimally enable active health checks, set either path or
|
||||||
|
// port (or both).
|
||||||
|
Active *ActiveHealthChecks `json:"active,omitempty"`
|
||||||
|
|
||||||
|
// Passive health checks monitor proxied requests for errors or timeouts.
|
||||||
|
// To minimally enable passive health checks, specify at least an empty
|
||||||
|
// config object.
|
||||||
Passive *PassiveHealthChecks `json:"passive,omitempty"`
|
Passive *PassiveHealthChecks `json:"passive,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,14 +48,33 @@ type HealthChecks struct {
|
||||||
// health checks (that is, health checks which occur in a
|
// health checks (that is, health checks which occur in a
|
||||||
// background goroutine independently).
|
// background goroutine independently).
|
||||||
type ActiveHealthChecks struct {
|
type ActiveHealthChecks struct {
|
||||||
Path string `json:"path,omitempty"`
|
// The URI path to use for health checks.
|
||||||
Port int `json:"port,omitempty"`
|
Path string `json:"path,omitempty"`
|
||||||
Headers http.Header `json:"headers,omitempty"`
|
|
||||||
Interval caddy.Duration `json:"interval,omitempty"`
|
// The port to use (if different from the upstream's dial
|
||||||
Timeout caddy.Duration `json:"timeout,omitempty"`
|
// address) for health checks.
|
||||||
MaxSize int64 `json:"max_size,omitempty"`
|
Port int `json:"port,omitempty"`
|
||||||
ExpectStatus int `json:"expect_status,omitempty"`
|
|
||||||
ExpectBody string `json:"expect_body,omitempty"`
|
// HTTP headers to set on health check requests.
|
||||||
|
Headers http.Header `json:"headers,omitempty"`
|
||||||
|
|
||||||
|
// How frequently to perform active health checks (default 30s).
|
||||||
|
Interval caddy.Duration `json:"interval,omitempty"`
|
||||||
|
|
||||||
|
// How long to wait for a response from a backend before
|
||||||
|
// considering it unhealthy (default 5s).
|
||||||
|
Timeout caddy.Duration `json:"timeout,omitempty"`
|
||||||
|
|
||||||
|
// The maximum response body to download from the backend
|
||||||
|
// during a health check.
|
||||||
|
MaxSize int64 `json:"max_size,omitempty"`
|
||||||
|
|
||||||
|
// The HTTP status code to expect from a healthy backend.
|
||||||
|
ExpectStatus int `json:"expect_status,omitempty"`
|
||||||
|
|
||||||
|
// A regular expression against which to match the response
|
||||||
|
// body of a healthy backend.
|
||||||
|
ExpectBody string `json:"expect_body,omitempty"`
|
||||||
|
|
||||||
stopChan chan struct{}
|
stopChan chan struct{}
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
|
@ -60,11 +86,27 @@ type ActiveHealthChecks struct {
|
||||||
// health checks (that is, health checks which occur during
|
// health checks (that is, health checks which occur during
|
||||||
// the normal flow of request proxying).
|
// the normal flow of request proxying).
|
||||||
type PassiveHealthChecks struct {
|
type PassiveHealthChecks struct {
|
||||||
MaxFails int `json:"max_fails,omitempty"`
|
// How long to remember a failed request to a backend. A duration > 0
|
||||||
FailDuration caddy.Duration `json:"fail_duration,omitempty"`
|
// enables passive health checking. Default is 0.
|
||||||
UnhealthyRequestCount int `json:"unhealthy_request_count,omitempty"`
|
FailDuration caddy.Duration `json:"fail_duration,omitempty"`
|
||||||
UnhealthyStatus []int `json:"unhealthy_status,omitempty"`
|
|
||||||
UnhealthyLatency caddy.Duration `json:"unhealthy_latency,omitempty"`
|
// The number of failed requests within the FailDuration window to
|
||||||
|
// consider a backend as "down". Must be >= 1; default is 1. Requires
|
||||||
|
// that FailDuration be > 0.
|
||||||
|
MaxFails int `json:"max_fails,omitempty"`
|
||||||
|
|
||||||
|
// Limits the number of simultaneous requests to a backend by
|
||||||
|
// marking the backend as "down" if it has this many concurrent
|
||||||
|
// requests or more.
|
||||||
|
UnhealthyRequestCount int `json:"unhealthy_request_count,omitempty"`
|
||||||
|
|
||||||
|
// Count the request as failed if the response comes back with
|
||||||
|
// one of these status codes.
|
||||||
|
UnhealthyStatus []int `json:"unhealthy_status,omitempty"`
|
||||||
|
|
||||||
|
// Count the request as failed if the response takes at least this
|
||||||
|
// long to receive.
|
||||||
|
UnhealthyLatency caddy.Duration `json:"unhealthy_latency,omitempty"`
|
||||||
|
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,8 +61,22 @@ type UpstreamPool []*Upstream
|
||||||
type Upstream struct {
|
type Upstream struct {
|
||||||
Host `json:"-"`
|
Host `json:"-"`
|
||||||
|
|
||||||
Dial string `json:"dial,omitempty"`
|
// The [network address](/docs/json/apps/http/#servers/listen)
|
||||||
MaxRequests int `json:"max_requests,omitempty"`
|
// to dial to connect to the upstream. Must represent precisely
|
||||||
|
// one socket (i.e. no port ranges). A valid network address
|
||||||
|
// either has a host and port, or is a unix socket address.
|
||||||
|
//
|
||||||
|
// Placeholders may be used to make the upstream dynamic, but be
|
||||||
|
// aware of the health check implications of this: a single
|
||||||
|
// upstream that represents numerous (perhaps arbitrary) backends
|
||||||
|
// can be considered down if one or enough of the arbitrary
|
||||||
|
// backends is down. Also be aware of open proxy vulnerabilities.
|
||||||
|
Dial string `json:"dial,omitempty"`
|
||||||
|
|
||||||
|
// The maximum number of simultaneous requests to allow to
|
||||||
|
// this upstream. If set, overrides the global passive health
|
||||||
|
// check UnhealthyRequestCount value.
|
||||||
|
MaxRequests int `json:"max_requests,omitempty"`
|
||||||
|
|
||||||
// TODO: This could be really useful, to bind requests
|
// TODO: This could be really useful, to bind requests
|
||||||
// with certain properties to specific backends
|
// with certain properties to specific backends
|
||||||
|
|
|
@ -46,6 +46,10 @@ func init() {
|
||||||
//
|
//
|
||||||
// This transport also forces HTTP/1.1 and Keep-Alives in order
|
// This transport also forces HTTP/1.1 and Keep-Alives in order
|
||||||
// for NTLM to succeed.
|
// for NTLM to succeed.
|
||||||
|
//
|
||||||
|
// It is basically the same thing as
|
||||||
|
// [nginx's paid ntlm directive](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#ntlm)
|
||||||
|
// (but is free in Caddy!).
|
||||||
type NTLMTransport struct {
|
type NTLMTransport struct {
|
||||||
*HTTPTransport
|
*HTTPTransport
|
||||||
|
|
||||||
|
|
|
@ -41,15 +41,56 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler implements a highly configurable and production-ready reverse proxy.
|
// Handler implements a highly configurable and production-ready reverse proxy.
|
||||||
|
// Upon proxying, this module sets the following placeholders (which can be used
|
||||||
|
// both within and after this handler):
|
||||||
|
//
|
||||||
|
// {http.reverse_proxy.upstream.address}
|
||||||
|
// The full address to the upstream as given in the config
|
||||||
|
// {http.reverse_proxy.upstream.hostport}
|
||||||
|
// The host:port of the upstream
|
||||||
|
// {http.reverse_proxy.upstream.host}
|
||||||
|
// The host of the upstream
|
||||||
|
// {http.reverse_proxy.upstream.port}
|
||||||
|
// The port of the upstream
|
||||||
|
// {http.reverse_proxy.upstream.requests}
|
||||||
|
// The approximate current number of requests to the upstream
|
||||||
|
// {http.reverse_proxy.upstream.max_requests}
|
||||||
|
// The maximum approximate number of requests allowed to the upstream
|
||||||
|
// {http.reverse_proxy.upstream.fails}
|
||||||
|
// The number of recent failed requests to the upstream
|
||||||
|
//
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
TransportRaw json.RawMessage `json:"transport,omitempty" caddy:"namespace=http.reverse_proxy.transport inline_key=protocol"`
|
// Configures the method of transport for the proxy. A transport
|
||||||
CBRaw json.RawMessage `json:"circuit_breaker,omitempty" caddy:"namespace=http.reverse_proxy.circuit_breakers inline_key=type"`
|
// is what performs the actual "round trip" to the backend.
|
||||||
LoadBalancing *LoadBalancing `json:"load_balancing,omitempty"`
|
// The default transport is plaintext HTTP.
|
||||||
HealthChecks *HealthChecks `json:"health_checks,omitempty"`
|
TransportRaw json.RawMessage `json:"transport,omitempty" caddy:"namespace=http.reverse_proxy.transport inline_key=protocol"`
|
||||||
Upstreams UpstreamPool `json:"upstreams,omitempty"`
|
|
||||||
FlushInterval caddy.Duration `json:"flush_interval,omitempty"`
|
// A circuit breaker may be used to relieve pressure on a backend
|
||||||
Headers *headers.Handler `json:"headers,omitempty"`
|
// that is beginning to exhibit symptoms of stress or latency.
|
||||||
BufferRequests bool `json:"buffer_requests,omitempty"`
|
// By default, there is no circuit breaker.
|
||||||
|
CBRaw json.RawMessage `json:"circuit_breaker,omitempty" caddy:"namespace=http.reverse_proxy.circuit_breakers inline_key=type"`
|
||||||
|
|
||||||
|
// Load balancing distributes load/requests between backends.
|
||||||
|
LoadBalancing *LoadBalancing `json:"load_balancing,omitempty"`
|
||||||
|
|
||||||
|
// Health checks update the status of backends, whether they are
|
||||||
|
// up or down. Down backends will not be proxied to.
|
||||||
|
HealthChecks *HealthChecks `json:"health_checks,omitempty"`
|
||||||
|
|
||||||
|
// Upstreams is the list of backends to proxy to.
|
||||||
|
Upstreams UpstreamPool `json:"upstreams,omitempty"`
|
||||||
|
|
||||||
|
// TODO: figure out good defaults and write docs for this
|
||||||
|
// (see https://github.com/caddyserver/caddy/issues/1460)
|
||||||
|
FlushInterval caddy.Duration `json:"flush_interval,omitempty"`
|
||||||
|
|
||||||
|
// Headers manipulates headers between Caddy and the backend.
|
||||||
|
Headers *headers.Handler `json:"headers,omitempty"`
|
||||||
|
|
||||||
|
// If true, the entire request body will be read and buffered
|
||||||
|
// in memory before being proxied to the backend. This should
|
||||||
|
// be avoided if at all possible for performance reasons.
|
||||||
|
BufferRequests bool `json:"buffer_requests,omitempty"`
|
||||||
|
|
||||||
Transport http.RoundTripper `json:"-"`
|
Transport http.RoundTripper `json:"-"`
|
||||||
CB CircuitBreaker `json:"-"`
|
CB CircuitBreaker `json:"-"`
|
||||||
|
@ -140,7 +181,7 @@ func (h *Handler) Provision(ctx caddy.Context) error {
|
||||||
|
|
||||||
timeout := time.Duration(h.HealthChecks.Active.Timeout)
|
timeout := time.Duration(h.HealthChecks.Active.Timeout)
|
||||||
if timeout == 0 {
|
if timeout == 0 {
|
||||||
timeout = 10 * time.Second
|
timeout = 5 * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
h.HealthChecks.Active.stopChan = make(chan struct{})
|
h.HealthChecks.Active.stopChan = make(chan struct{})
|
||||||
|
@ -649,10 +690,30 @@ func removeConnectionHeaders(h http.Header) {
|
||||||
|
|
||||||
// LoadBalancing has parameters related to load balancing.
|
// LoadBalancing has parameters related to load balancing.
|
||||||
type LoadBalancing struct {
|
type LoadBalancing struct {
|
||||||
SelectionPolicyRaw json.RawMessage `json:"selection_policy,omitempty" caddy:"namespace=http.reverse_proxy.selection_policies inline_key=policy"`
|
// A selection policy is how to choose an available backend.
|
||||||
TryDuration caddy.Duration `json:"try_duration,omitempty"`
|
// The default policy is random selection.
|
||||||
TryInterval caddy.Duration `json:"try_interval,omitempty"`
|
SelectionPolicyRaw json.RawMessage `json:"selection_policy,omitempty" caddy:"namespace=http.reverse_proxy.selection_policies inline_key=policy"`
|
||||||
RetryMatchRaw caddyhttp.RawMatcherSets `json:"retry_match,omitempty" caddy:"namespace=http.matchers"`
|
|
||||||
|
// How long to try selecting available backends for each request
|
||||||
|
// if the next available host is down. By default, this retry is
|
||||||
|
// disabled. Clients will wait for up to this long while the load
|
||||||
|
// balancer tries to find an available upstream host.
|
||||||
|
TryDuration caddy.Duration `json:"try_duration,omitempty"`
|
||||||
|
|
||||||
|
// How long to wait between selecting the next host from the pool. Default
|
||||||
|
// is 250ms. Only relevant when a request to an upstream host fails. Be
|
||||||
|
// aware that setting this to 0 with a non-zero try_duration can cause the
|
||||||
|
// CPU to spin if all backends are down and latency is very low.
|
||||||
|
TryInterval caddy.Duration `json:"try_interval,omitempty"`
|
||||||
|
|
||||||
|
// A list of matcher sets that restricts with which requests retries are
|
||||||
|
// allowed. A request must match any of the given matcher sets in order
|
||||||
|
// to be retried if the connection to the upstream succeeded but the
|
||||||
|
// subsequent round-trip failed. If the connection to the upstream failed,
|
||||||
|
// a retry is always allowed. If unspecified, only GET requests will be
|
||||||
|
// allowed to be retried. Note that a retry is done with the next available
|
||||||
|
// host according to the load balancing policy.
|
||||||
|
RetryMatchRaw caddyhttp.RawMatcherSets `json:"retry_match,omitempty" caddy:"namespace=http.matchers"`
|
||||||
|
|
||||||
SelectionPolicy Selector `json:"-"`
|
SelectionPolicy Selector `json:"-"`
|
||||||
RetryMatch caddyhttp.MatcherSets `json:"-"`
|
RetryMatch caddyhttp.MatcherSets `json:"-"`
|
||||||
|
|
|
@ -31,16 +31,39 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewrite is a middleware which can rewrite HTTP requests.
|
// Rewrite is a middleware which can rewrite HTTP requests.
|
||||||
|
//
|
||||||
|
// The Rehandle and HTTPRedirect properties are mutually exclusive
|
||||||
|
// (you cannot both rehandle and issue a redirect).
|
||||||
|
//
|
||||||
|
// These rewrite properties are applied to a request in this order:
|
||||||
|
// Method, URI, StripPathPrefix, StripPathSuffix, URISubstring.
|
||||||
|
//
|
||||||
|
// TODO: This module is still a WIP and may experience breaking changes.
|
||||||
type Rewrite struct {
|
type Rewrite struct {
|
||||||
|
// Changes the request's HTTP verb.
|
||||||
Method string `json:"method,omitempty"`
|
Method string `json:"method,omitempty"`
|
||||||
URI string `json:"uri,omitempty"`
|
|
||||||
|
|
||||||
StripPathPrefix string `json:"strip_path_prefix,omitempty"`
|
// Changes the request's URI (path, query string, and fragment if present).
|
||||||
StripPathSuffix string `json:"strip_path_suffix,omitempty"`
|
// Only components of the URI that are specified will be changed.
|
||||||
URISubstring []replacer `json:"uri_substring,omitempty"`
|
URI string `json:"uri,omitempty"`
|
||||||
|
|
||||||
|
// Strips the given prefix from the beginning of the URI path.
|
||||||
|
StripPathPrefix string `json:"strip_path_prefix,omitempty"`
|
||||||
|
|
||||||
|
// Strips the given suffix from the end of the URI path.
|
||||||
|
StripPathSuffix string `json:"strip_path_suffix,omitempty"`
|
||||||
|
|
||||||
|
// Performs substring replacements on the URI.
|
||||||
|
URISubstring []replacer `json:"uri_substring,omitempty"`
|
||||||
|
|
||||||
|
// If set to a 3xx HTTP status code and if the URI was rewritten (changed),
|
||||||
|
// the handler will issue a simple HTTP redirect to the new URI using the
|
||||||
|
// given status code.
|
||||||
HTTPRedirect caddyhttp.WeakString `json:"http_redirect,omitempty"`
|
HTTPRedirect caddyhttp.WeakString `json:"http_redirect,omitempty"`
|
||||||
Rehandle bool `json:"rehandle,omitempty"`
|
|
||||||
|
// If true, the request will sent for rehandling after rewriting
|
||||||
|
// only if anything about the request was changed.
|
||||||
|
Rehandle bool `json:"rehandle,omitempty"`
|
||||||
|
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,8 +97,12 @@ type Server struct {
|
||||||
// in which they appear in the list.
|
// in which they appear in the list.
|
||||||
Routes RouteList `json:"routes,omitempty"`
|
Routes RouteList `json:"routes,omitempty"`
|
||||||
|
|
||||||
// Errors is how this server will handle errors returned from
|
// Errors is how this server will handle errors returned from any
|
||||||
// any of the handlers in the primary routes.
|
// of the handlers in the primary routes. If the primary handler
|
||||||
|
// chain returns an error, the error along with its recommended
|
||||||
|
// status code are bubbled back up to the HTTP server which
|
||||||
|
// executes a separate error route, specified using this property.
|
||||||
|
// The error routes work exactly like the normal routes.
|
||||||
Errors *HTTPErrorConfig `json:"errors,omitempty"`
|
Errors *HTTPErrorConfig `json:"errors,omitempty"`
|
||||||
|
|
||||||
// How to handle TLS connections.
|
// How to handle TLS connections.
|
||||||
|
@ -418,6 +422,20 @@ func (ahc AutoHTTPSConfig) Skipped(name string, skipSlice []string) bool {
|
||||||
// HTTPErrorConfig determines how to handle errors
|
// HTTPErrorConfig determines how to handle errors
|
||||||
// from the HTTP handlers.
|
// from the HTTP handlers.
|
||||||
type HTTPErrorConfig struct {
|
type HTTPErrorConfig struct {
|
||||||
|
// The routes to evaluate after the primary handler
|
||||||
|
// chain returns an error. In an error route, extra
|
||||||
|
// placeholders are available:
|
||||||
|
//
|
||||||
|
// {http.error.status_code}
|
||||||
|
// The recommended HTTP status code
|
||||||
|
// {http.error.status_text}
|
||||||
|
// The status text associated with the recommended status code
|
||||||
|
// {http.error.message}
|
||||||
|
// The error message
|
||||||
|
// {http.error.trace}
|
||||||
|
// The origin of the error
|
||||||
|
// {http.error.id}
|
||||||
|
// A short, human-conveyable ID for the error
|
||||||
Routes RouteList `json:"routes,omitempty"`
|
Routes RouteList `json:"routes,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
{
|
{
|
||||||
"handle": {
|
"handle": {
|
||||||
"handler": "starlark",
|
"handler": "starlark",
|
||||||
"script": "def setup(r):\n\t# create some middlewares specific to this request\n\ttemplates = loadModule('http.handlers.templates', {'include_root': './includes'})\n\tmidChain = execute([templates])\n\ndef serveHTTP (rw, r):\n\trw.Write('Hello world, from Starlark!')\n"
|
"script": "def setup(r):\n\t# create some middlewares specific to this request\n\ttemplates = loadModule('http.handlers.templates', {'file_root': './includes'})\n\tmidChain = execute([templates])\n\ndef serveHTTP (rw, r):\n\trw.Write('Hello world, from Starlark!')\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -27,8 +27,18 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// StaticError implements a simple handler that returns an error.
|
// StaticError implements a simple handler that returns an error.
|
||||||
|
// This handler returns an error value, but does not write a response.
|
||||||
|
// This is useful when you want the server to act as if an error
|
||||||
|
// occurred; for example, to invoke your custom error handling logic.
|
||||||
|
//
|
||||||
|
// Since this handler does not write a response, the error information
|
||||||
|
// is for use by the server to know how to handle the error.
|
||||||
type StaticError struct {
|
type StaticError struct {
|
||||||
Error string `json:"error,omitempty"`
|
// The recommended HTTP status code. Can be either an integer or a
|
||||||
|
// string if placeholders are needed. Optional. Default is 500.
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
|
||||||
|
// The error message. Optional. Default is no error message.
|
||||||
StatusCode WeakString `json:"status_code,omitempty"`
|
StatusCode WeakString `json:"status_code,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,19 @@ func init() {
|
||||||
|
|
||||||
// StaticResponse implements a simple responder for static responses.
|
// StaticResponse implements a simple responder for static responses.
|
||||||
type StaticResponse struct {
|
type StaticResponse struct {
|
||||||
StatusCode WeakString `json:"status_code,omitempty"`
|
// The HTTP status code to respond with. Can be an integer or,
|
||||||
Headers http.Header `json:"headers,omitempty"`
|
// if needing to use a placeholder, a string.
|
||||||
Body string `json:"body,omitempty"`
|
StatusCode WeakString `json:"status_code,omitempty"`
|
||||||
Close bool `json:"close,omitempty"`
|
|
||||||
|
// Header fields to set on the response.
|
||||||
|
Headers http.Header `json:"headers,omitempty"`
|
||||||
|
|
||||||
|
// The response body.
|
||||||
|
Body string `json:"body,omitempty"`
|
||||||
|
|
||||||
|
// If true, the server will close the client's connection
|
||||||
|
// after writing the response.
|
||||||
|
Close bool `json:"close,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaddyModule returns the Caddy module information.
|
// CaddyModule returns the Caddy module information.
|
||||||
|
|
|
@ -37,7 +37,11 @@ func init() {
|
||||||
// is only returned to the entry point at the server if there is an
|
// is only returned to the entry point at the server if there is an
|
||||||
// additional error returned from the errors routes.
|
// additional error returned from the errors routes.
|
||||||
type Subroute struct {
|
type Subroute struct {
|
||||||
Routes RouteList `json:"routes,omitempty"`
|
// The primary list of routes to compile and execute.
|
||||||
|
Routes RouteList `json:"routes,omitempty"`
|
||||||
|
|
||||||
|
// If the primary routes return an error, error handling
|
||||||
|
// can be promoted to this configuration instead.
|
||||||
Errors *HTTPErrorConfig `json:"errors,omitempty"`
|
Errors *HTTPErrorConfig `json:"errors,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
|
||||||
return nil, h.ArgErr()
|
return nil, h.ArgErr()
|
||||||
}
|
}
|
||||||
case "root":
|
case "root":
|
||||||
if !h.Args(&t.IncludeRoot) {
|
if !h.Args(&t.FileRoot) {
|
||||||
return nil, h.ArgErr()
|
return nil, h.ArgErr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,8 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// VarsMiddleware is an HTTP middleware which sets variables
|
// VarsMiddleware is an HTTP middleware which sets variables
|
||||||
// in the context, mainly for use by placeholders.
|
// in the context, mainly for use by placeholders. The
|
||||||
|
// placeholders have the form: `{http.vars.variable_name}`
|
||||||
type VarsMiddleware map[string]string
|
type VarsMiddleware map[string]string
|
||||||
|
|
||||||
// CaddyModule returns the Caddy module information.
|
// CaddyModule returns the Caddy module information.
|
||||||
|
|
|
@ -36,7 +36,7 @@ func init() {
|
||||||
|
|
||||||
// ConsoleEncoder encodes log entries that are mostly human-readable.
|
// ConsoleEncoder encodes log entries that are mostly human-readable.
|
||||||
type ConsoleEncoder struct {
|
type ConsoleEncoder struct {
|
||||||
zapcore.Encoder
|
zapcore.Encoder `json:"-"`
|
||||||
LogEncoderConfig
|
LogEncoderConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,8 +56,8 @@ func (ce *ConsoleEncoder) Provision(_ caddy.Context) error {
|
||||||
|
|
||||||
// JSONEncoder encodes entries as JSON.
|
// JSONEncoder encodes entries as JSON.
|
||||||
type JSONEncoder struct {
|
type JSONEncoder struct {
|
||||||
zapcore.Encoder
|
zapcore.Encoder `json:"-"`
|
||||||
*LogEncoderConfig
|
LogEncoderConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaddyModule returns the Caddy module information.
|
// CaddyModule returns the Caddy module information.
|
||||||
|
@ -77,7 +77,7 @@ func (je *JSONEncoder) Provision(_ caddy.Context) error {
|
||||||
// LogfmtEncoder encodes log entries as logfmt:
|
// LogfmtEncoder encodes log entries as logfmt:
|
||||||
// https://www.brandur.org/logfmt
|
// https://www.brandur.org/logfmt
|
||||||
type LogfmtEncoder struct {
|
type LogfmtEncoder struct {
|
||||||
zapcore.Encoder
|
zapcore.Encoder `json:"-"`
|
||||||
LogEncoderConfig
|
LogEncoderConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,9 +100,9 @@ func (lfe *LogfmtEncoder) Provision(_ caddy.Context) error {
|
||||||
// for custom, self-encoded log entries that consist of a
|
// for custom, self-encoded log entries that consist of a
|
||||||
// single field in the structured log entry.
|
// single field in the structured log entry.
|
||||||
type StringEncoder struct {
|
type StringEncoder struct {
|
||||||
zapcore.Encoder
|
zapcore.Encoder `json:"-"`
|
||||||
FieldName string `json:"field,omitempty"`
|
FieldName string `json:"field,omitempty"`
|
||||||
FallbackRaw json.RawMessage `json:"fallback,omitempty" caddy:"namespace=caddy.logging.encoders inline_key=format"`
|
FallbackRaw json.RawMessage `json:"fallback,omitempty" caddy:"namespace=caddy.logging.encoders inline_key=format"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaddyModule returns the Caddy module information.
|
// CaddyModule returns the Caddy module information.
|
||||||
|
|
Loading…
Reference in a new issue