kenginehttp

package
v1.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 29, 2024 License: Apache-2.0 Imports: 69 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// DefaultHTTPPort is the default port for HTTP.
	DefaultHTTPPort = 80

	// DefaultHTTPSPort is the default port for HTTPS.
	DefaultHTTPSPort = 443
)
View Source
const (
	// Variable name used to indicate that this request
	// should be omitted from the access logs
	LogSkipVar string = "log_skip"

	// For adding additional fields to the access logs
	ExtraLogFieldsCtxKey kengine.CtxKey = "extra_log_fields"

	// Variable name used to indicate the logger to be used
	AccessLoggerNameVarKey string = "access_logger_names"
)
View Source
const (
	// For referencing the server instance
	ServerCtxKey kengine.CtxKey = "server"

	// For the request's variable table
	VarsCtxKey kengine.CtxKey = "vars"

	// For a partial copy of the unmodified request that
	// originally came into the server's entry handler
	OriginalRequestCtxKey kengine.CtxKey = "original_request"

	// For referencing underlying net.Conn
	ConnCtxKey kengine.CtxKey = "conn"

	// For tracking whether the client is a trusted proxy
	TrustedProxyVarKey string = "trusted_proxy"

	// For tracking the real client IP (affected by trusted_proxy)
	ClientIPVarKey string = "client_ip"
)

Context keys for HTTP request context values.

View Source
const ErrorCtxKey = kengine.CtxKey("handler_chain_error")

ErrorCtxKey is the context key to use when storing an error (for use with context.Context).

View Source
const MatcherErrorVarKey = "matchers.error"

MatcherErrorVarKey is the key used for the variable that holds an optional error emitted from a request matcher, to short-circuit the handler chain, since matchers cannot return errors via the RequestMatcher interface.

View Source
const MatcherNameCtxKey = "matcher_name"

Variables

View Source
var (
	CELTypeJSON = cel.MapType(cel.StringType, cel.DynType)
)

Variables used for replacing Kengine placeholders in CEL expressions with a proper CEL function call; this is just for syntactic sugar.

View Source
var ErrNotImplemented = fmt.Errorf("method not implemented")

ErrNotImplemented is returned when an underlying ResponseWriter does not implement the required method.

Functions

func CELMatcherDecorator

func CELMatcherDecorator(funcName string, fac CELMatcherFactory) interpreter.InterpretableDecorator

CELMatcherDecorator matches a call overload generated by a CEL macro that takes a single argument, and optimizes the implementation to precompile the matcher and return a function that references the precompiled and provisioned matcher.

func CELMatcherImpl

func CELMatcherImpl(macroName, funcName string, matcherDataTypes []*cel.Type, fac CELMatcherFactory) (cel.Library, error)

CELMatcherImpl creates a new cel.Library based on the following pieces of data:

  • macroName: the function name to be used within CEL. This will be a macro and not a function proper.
  • funcName: the function overload name generated by the CEL macro used to represent the matcher.
  • matcherDataTypes: the argument types to the macro.
  • fac: a matcherFactory implementation which converts from CEL constant values to a Matcher instance.

Note, macro names and function names must not collide with other macros or functions exposed within CEL expressions, or an error will be produced during the expression matcher plan time.

The existing CELMatcherImpl support methods are configured to support a limited set of function signatures. For strong type validation you may need to provide a custom macro which does a more detailed analysis of the CEL literal provided to the macro as an argument.

func CELMatcherRuntimeFunction

func CELMatcherRuntimeFunction(funcName string, fac CELMatcherFactory) functions.BinaryOp

CELMatcherRuntimeFunction creates a function binding for when the input to the matcher is dynamically resolved rather than a set of static constant values.

func CELValueToMapStrList

func CELValueToMapStrList(data ref.Val) (map[string][]string, error)

CELValueToMapStrList converts a CEL value to a map[string][]string

Earlier validation stages should guarantee that the value has this type at compile time, and that the runtime value type is map[string]any. The reason for the slight difference in value type is that CEL allows for map literals containing heterogeneous values, in this case string and list of string.

func CIDRExpressionToPrefix

func CIDRExpressionToPrefix(expr string) (netip.Prefix, error)

CIDRExpressionToPrefix takes a string which could be either a CIDR expression or a single IP address, and returns a netip.Prefix.

func CleanPath

func CleanPath(p string, collapseSlashes bool) string

CleanPath cleans path p according to path.Clean(), but only merges repeated slashes if collapseSlashes is true, and always preserves trailing slashes.

func GetVar

func GetVar(ctx context.Context, key string) any

GetVar gets a value out of the context's variable table by key. If the key does not exist, the return value will be nil.

func NewMatcherCELLibrary

func NewMatcherCELLibrary(envOptions []cel.EnvOption, programOptions []cel.ProgramOption) cel.Library

NewMatcherCELLibrary creates a matcherLibrary from option setes.

func NewTestReplacer

func NewTestReplacer(req *http.Request) *kengine.Replacer

NewTestReplacer creates a replacer for an http.Request for use in tests that are not in this package

func ParseKenginefileNestedMatcherSet

func ParseKenginefileNestedMatcherSet(d *kenginefile.Dispenser) (kengine.ModuleMap, error)

ParseKenginefileNestedMatcher parses the Kenginefile tokens for a nested matcher set, and returns its raw module map value.

func ParseNamedResponseMatcher

func ParseNamedResponseMatcher(d *kenginefile.Dispenser, matchers map[string]ResponseMatcher) error

ParseNamedResponseMatcher parses the tokens of a named response matcher.

@name {
    header <field> [<value>]
    status <code...>
}

Or, single line syntax:

@name [header <field> [<value>]] | [status <code...>]

func PrepareRequest

func PrepareRequest(r *http.Request, repl *kengine.Replacer, w http.ResponseWriter, s *Server) *http.Request

PrepareRequest fills the request r for use in a Kengine HTTP handler chain. w and s can be nil, but the handlers will lose response placeholders and access to the server.

func PrivateRangesCIDR

func PrivateRangesCIDR() []string

PrivateRangesCIDR returns a list of private CIDR range strings, which can be used as a configuration shortcut. Note: this function is used at least by mholt/kengine-l4.

func RegisterNetworkHTTP3

func RegisterNetworkHTTP3(originalNetwork, h3Network string)

RegisterNetworkHTTP3 registers a mapping from non-HTTP/3 network to HTTP/3 network. This should be called during init() and will panic if the network type is standard, reserved, or already registered.

EXPERIMENTAL: Subject to change.

func SanitizedPathJoin

func SanitizedPathJoin(root, reqPath string) string

SanitizedPathJoin performs filepath.Join(root, reqPath) that is safe against directory traversal attacks. It uses logic similar to that in the Go standard library, specifically in the implementation of http.Dir. The root is assumed to be a trusted path, but reqPath is not; and the output will never be outside of root. The resulting path can be used with the local file system. If root is empty, the current directory is assumed. If the cleaned request path is deemed not local according to lexical processing (i.e. ignoring links), it will be rejected as unsafe and only the root will be returned.

func SetVar

func SetVar(ctx context.Context, key string, value any)

SetVar sets a value in the context's variable table with the given key. It overwrites any previous value with the same key.

If the value is nil (note: non-nil interface with nil underlying value does not count) and the key exists in the table, the key+value will be deleted from the table.

func StatusCodeMatches

func StatusCodeMatches(actual, configured int) bool

StatusCodeMatches returns true if a real HTTP status code matches the configured status code, which may be either a real HTTP status code or an integer representing a class of codes (e.g. 4 for all 4xx statuses).

Types

type App

type App struct {
	// HTTPPort specifies the port to use for HTTP (as opposed to HTTPS),
	// which is used when setting up HTTP->HTTPS redirects or ACME HTTP
	// challenge solvers. Default: 80.
	HTTPPort int `json:"http_port,omitempty"`

	// HTTPSPort specifies the port to use for HTTPS, which is used when
	// solving the ACME TLS-ALPN challenges, or whenever HTTPS is needed
	// but no specific port number is given. Default: 443.
	HTTPSPort int `json:"https_port,omitempty"`

	// GracePeriod is how long to wait for active connections when shutting
	// down the servers. During the grace period, no new connections are
	// accepted, idle connections are closed, and active connections will
	// be given the full length of time to become idle and close.
	// Once the grace period is over, connections will be forcefully closed.
	// If zero, the grace period is eternal. Default: 0.
	GracePeriod kengine.Duration `json:"grace_period,omitempty"`

	// ShutdownDelay is how long to wait before initiating the grace
	// period. When this app is stopping (e.g. during a config reload or
	// process exit), all servers will be shut down. Normally this immediately
	// initiates the grace period. However, if this delay is configured, servers
	// will not be shut down until the delay is over. During this time, servers
	// continue to function normally and allow new connections. At the end, the
	// grace period will begin. This can be useful to allow downstream load
	// balancers time to move this instance out of the rotation without hiccups.
	//
	// When shutdown has been scheduled, placeholders {http.shutting_down} (bool)
	// and {http.time_until_shutdown} (duration) may be useful for health checks.
	ShutdownDelay kengine.Duration `json:"shutdown_delay,omitempty"`

	// Servers is the list of servers, keyed by arbitrary names chosen
	// at your discretion for your own convenience; the keys do not
	// affect functionality.
	Servers map[string]*Server `json:"servers,omitempty"`
	// contains filtered or unexported fields
}

App is a robust, production-ready HTTP server.

HTTPS is enabled by default if host matchers with qualifying names are used in any of routes; certificates are automatically provisioned and renewed. Additionally, automatic HTTPS will also enable HTTPS for servers that listen only on the HTTPS port but which do not have any TLS connection policies defined by adding a good, default TLS connection policy.

In HTTP routes, additional placeholders are available (replace any `*`):

Placeholder | Description ------------|--------------- `{http.request.body}` | The request body (⚠️ inefficient; use only for debugging) `{http.request.cookie.*}` | HTTP request cookie `{http.request.duration}` | Time up to now spent handling the request (after decoding headers from client) `{http.request.duration_ms}` | Same as 'duration', but in milliseconds. `{http.request.uuid}` | The request unique identifier `{http.request.header.*}` | Specific request header field `{http.request.host}` | The host part of the request's Host header `{http.request.host.labels.*}` | Request host labels (0-based from right); e.g. for foo.example.com: 0=com, 1=example, 2=foo `{http.request.hostport}` | The host and port from the request's Host header `{http.request.method}` | The request method `{http.request.orig_method}` | The request's original method `{http.request.orig_uri}` | The request's original URI `{http.request.orig_uri.path}` | The request's original path `{http.request.orig_uri.path.*}` | Parts of the original path, split by `/` (0-based from left) `{http.request.orig_uri.path.dir}` | The request's original directory `{http.request.orig_uri.path.file}` | The request's original filename `{http.request.orig_uri.query}` | The request's original query string (without `?`) `{http.request.port}` | The port part of the request's Host header `{http.request.proto}` | The protocol of the request `{http.request.local.host}` | The host (IP) part of the local address the connection arrived on `{http.request.local.port}` | The port part of the local address the connection arrived on `{http.request.local}` | The local address the connection arrived on `{http.request.remote.host}` | The host (IP) part of the remote client's address `{http.request.remote.port}` | The port part of the remote client's address `{http.request.remote}` | The address of the remote client `{http.request.scheme}` | The request scheme, typically `http` or `https` `{http.request.tls.version}` | The TLS version name `{http.request.tls.cipher_suite}` | The TLS cipher suite `{http.request.tls.resumed}` | The TLS connection resumed a previous connection `{http.request.tls.proto}` | The negotiated next protocol `{http.request.tls.proto_mutual}` | The negotiated next protocol was advertised by the server `{http.request.tls.server_name}` | The server name requested by the client, if any `{http.request.tls.client.fingerprint}` | The SHA256 checksum of the client certificate `{http.request.tls.client.public_key}` | The public key of the client certificate. `{http.request.tls.client.public_key_sha256}` | The SHA256 checksum of the client's public key. `{http.request.tls.client.certificate_pem}` | The PEM-encoded value of the certificate. `{http.request.tls.client.certificate_der_base64}` | The base64-encoded value of the certificate. `{http.request.tls.client.issuer}` | The issuer DN of the client certificate `{http.request.tls.client.serial}` | The serial number of the client certificate `{http.request.tls.client.subject}` | The subject DN of the client certificate `{http.request.tls.client.san.dns_names.*}` | SAN DNS names(index optional) `{http.request.tls.client.san.emails.*}` | SAN email addresses (index optional) `{http.request.tls.client.san.ips.*}` | SAN IP addresses (index optional) `{http.request.tls.client.san.uris.*}` | SAN URIs (index optional) `{http.request.uri}` | The full request URI `{http.request.uri.path}` | The path component of the request URI `{http.request.uri.path.*}` | Parts of the path, split by `/` (0-based from left) `{http.request.uri.path.dir}` | The directory, excluding leaf filename `{http.request.uri.path.file}` | The filename of the path, excluding directory `{http.request.uri.query}` | The query string (without `?`) `{http.request.uri.query.*}` | Individual query string value `{http.response.header.*}` | Specific response header field `{http.vars.*}` | Custom variables in the HTTP handler chain `{http.shutting_down}` | True if the HTTP app is shutting down `{http.time_until_shutdown}` | Time until HTTP server shutdown, if scheduled

func (App) KengineModule

func (App) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (*App) Provision

func (app *App) Provision(ctx kengine.Context) error

Provision sets up the app.

func (*App) Start

func (app *App) Start() error

Start runs the app. It finishes automatic HTTPS if enabled, including management of certificates.

func (*App) Stop

func (app *App) Stop() error

Stop gracefully shuts down the HTTP server.

func (*App) Validate

func (app *App) Validate() error

Validate ensures the app's configuration is valid.

type AutoHTTPSConfig

type AutoHTTPSConfig struct {
	// If true, automatic HTTPS will be entirely disabled,
	// including certificate management and redirects.
	Disabled bool `json:"disable,omitempty"`

	// If true, only automatic HTTP->HTTPS redirects will
	// be disabled, but other auto-HTTPS features will
	// remain enabled.
	DisableRedir bool `json:"disable_redirects,omitempty"`

	// If true, automatic certificate management will be
	// disabled, but other auto-HTTPS features will
	// remain enabled.
	DisableCerts bool `json:"disable_certificates,omitempty"`

	// Hosts/domain names listed here will not be included
	// in automatic HTTPS (they will not have certificates
	// loaded nor redirects applied).
	Skip []string `json:"skip,omitempty"`

	// Hosts/domain names listed here will still be enabled
	// for automatic HTTPS (unless in the Skip list), except
	// that certificates will not be provisioned and managed
	// for these names.
	SkipCerts []string `json:"skip_certificates,omitempty"`

	// By default, automatic HTTPS will obtain and renew
	// certificates for qualifying hostnames. However, if
	// a certificate with a matching SAN is already loaded
	// into the cache, certificate management will not be
	// enabled. To force automated certificate management
	// regardless of loaded certificates, set this to true.
	IgnoreLoadedCerts bool `json:"ignore_loaded_certificates,omitempty"`
}

AutoHTTPSConfig is used to disable automatic HTTPS or certain aspects of it for a specific server. HTTPS is enabled automatically and by default when qualifying hostnames are available from the config.

type CELLibraryProducer

type CELLibraryProducer interface {
	// CELLibrary creates a cel.Library which makes it possible to use the
	// target object within CEL expression matchers.
	CELLibrary(kengine.Context) (cel.Library, error)
}

CELLibraryProducer provide CEL libraries that expose a Matcher implementation as a first class function within the CEL expression matcher.

type CELMatcherFactory

type CELMatcherFactory func(data ref.Val) (RequestMatcher, error)

CELMatcherFactory converts a constant CEL value into a RequestMatcher.

type ExtraLogFields

type ExtraLogFields struct {
	// contains filtered or unexported fields
}

ExtraLogFields is a list of extra fields to log with every request.

func (*ExtraLogFields) Add

func (e *ExtraLogFields) Add(field zap.Field)

Add adds a field to the list of extra fields to log.

func (*ExtraLogFields) Set

func (e *ExtraLogFields) Set(field zap.Field)

Set sets a field in the list of extra fields to log. If the field already exists, it is replaced.

type HTTPErrorConfig

type HTTPErrorConfig struct {
	// The routes to evaluate after the primary handler
	// chain returns an error. In an error route, extra
	// placeholders are available:
	//
	// Placeholder | Description
	// ------------|---------------
	// `{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}`          | An identifier for this occurrence of the error
	Routes RouteList `json:"routes,omitempty"`
}

HTTPErrorConfig determines how to handle errors from the HTTP handlers.

func (*HTTPErrorConfig) WithError

func (*HTTPErrorConfig) WithError(r *http.Request, err error) *http.Request

WithError makes a shallow copy of r to add the error to its context, and sets placeholders on the request's replacer related to err. It returns the modified request which has the error information in its context and replacer. It overwrites any existing error values that are stored.

type HTTPRedirectListenerWrapper

type HTTPRedirectListenerWrapper struct {
	// MaxHeaderBytes is the maximum size to parse from a client's
	// HTTP request headers. Default: 1 MB
	MaxHeaderBytes int64 `json:"max_header_bytes,omitempty"`
}

HTTPRedirectListenerWrapper provides HTTP->HTTPS redirects for connections that come on the TLS port as an HTTP request, by detecting using the first few bytes that it's not a TLS handshake, but instead an HTTP request.

This is especially useful when using a non-standard HTTPS port. A user may simply type the address in their browser without the https:// scheme, which would cause the browser to attempt the connection over HTTP, but this would cause a "Client sent an HTTP request to an HTTPS server" error response.

This listener wrapper must be placed BEFORE the "tls" listener wrapper, for it to work properly.

func (HTTPRedirectListenerWrapper) KengineModule

func (*HTTPRedirectListenerWrapper) UnmarshalKenginefile

func (h *HTTPRedirectListenerWrapper) UnmarshalKenginefile(d *kenginefile.Dispenser) error

func (*HTTPRedirectListenerWrapper) WrapListener

type Handler

type Handler interface {
	ServeHTTP(http.ResponseWriter, *http.Request) error
}

Handler is like http.Handler except ServeHTTP may return an error.

If any handler encounters an error, it should be returned for proper handling. Return values should be propagated down the middleware chain by returning it unchanged. Returned errors should not be re-wrapped if they are already HandlerError values.

type HandlerError

type HandlerError struct {
	Err        error // the original error value and message
	StatusCode int   // the HTTP status code to associate with this error

	ID    string // generated; for identifying this error in logs
	Trace string // produced from call stack
}

HandlerError is a serializable representation of an error from within an HTTP handler.

func Error

func Error(statusCode int, err error) HandlerError

Error is a convenient way for a Handler to populate the essential fields of a HandlerError. If err is itself a HandlerError, then any essential fields that are not set will be populated.

func (HandlerError) Error

func (e HandlerError) Error() string

func (HandlerError) Unwrap

func (e HandlerError) Unwrap() error

Unwrap returns the underlying error value. See the `errors` package for info.

type HandlerFunc

type HandlerFunc func(http.ResponseWriter, *http.Request) error

HandlerFunc is a convenience type like http.HandlerFunc.

func (HandlerFunc) ServeHTTP

func (f HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) error

ServeHTTP implements the Handler interface.

type IPRangeSource

type IPRangeSource interface {
	GetIPRanges(*http.Request) []netip.Prefix
}

IPRangeSource gets a list of IP ranges.

The request is passed as an argument to allow plugin implementations to have more flexibility. But, a plugin MUST NOT modify the request. The caller will have read the `r.RemoteAddr` before getting IP ranges.

This should be a very fast function -- instant if possible. The list of IP ranges should be sourced as soon as possible if loaded from an external source (i.e. initially loaded during Provisioning), so that it's ready to be used when requests start getting handled. A read lock should probably be used to get the cached value if the ranges can change at runtime (e.g. periodically refreshed). Using a `kengine.UsagePool` may be a good idea to avoid having refetch the values when a config reload occurs, which would waste time.

If the list of IP ranges cannot be sourced, then provisioning SHOULD fail. Getting the IP ranges at runtime MUST NOT fail, because it would cancel incoming requests. If refreshing the list fails, then the previous list of IP ranges should continue to be returned so that the server can continue to operate normally.

type Invoke

type Invoke struct {
	// Name is the key of the named route to execute
	Name string `json:"name,omitempty"`
}

Invoke implements a handler that compiles and executes a named route that was defined on the server.

EXPERIMENTAL: Subject to change or removal.

func (Invoke) KengineModule

func (Invoke) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (*Invoke) ServeHTTP

func (invoke *Invoke) ServeHTTP(w http.ResponseWriter, r *http.Request, next Handler) error

type LoggableHTTPHeader

type LoggableHTTPHeader struct {
	http.Header

	ShouldLogCredentials bool
}

LoggableHTTPHeader makes an HTTP header loggable with zap.Object(). Headers with potentially sensitive information (Cookie, Set-Cookie, Authorization, and Proxy-Authorization) are logged with empty values.

func (LoggableHTTPHeader) MarshalLogObject

func (h LoggableHTTPHeader) MarshalLogObject(enc zapcore.ObjectEncoder) error

MarshalLogObject satisfies the zapcore.ObjectMarshaler interface.

type LoggableHTTPRequest

type LoggableHTTPRequest struct {
	*http.Request

	ShouldLogCredentials bool
}

LoggableHTTPRequest makes an HTTP request loggable with zap.Object().

func (LoggableHTTPRequest) MarshalLogObject

func (r LoggableHTTPRequest) MarshalLogObject(enc zapcore.ObjectEncoder) error

MarshalLogObject satisfies the zapcore.ObjectMarshaler interface.

type LoggableStringArray

type LoggableStringArray []string

LoggableStringArray makes a slice of strings marshalable for logging.

func (LoggableStringArray) MarshalLogArray

func (sa LoggableStringArray) MarshalLogArray(enc zapcore.ArrayEncoder) error

MarshalLogArray satisfies the zapcore.ArrayMarshaler interface.

type LoggableTLSConnState

type LoggableTLSConnState tls.ConnectionState

LoggableTLSConnState makes a TLS connection state loggable with zap.Object().

func (LoggableTLSConnState) MarshalLogObject

func (t LoggableTLSConnState) MarshalLogObject(enc zapcore.ObjectEncoder) error

MarshalLogObject satisfies the zapcore.ObjectMarshaler interface.

type MatchClientIP

type MatchClientIP struct {
	// The IPs or CIDR ranges to match.
	Ranges []string `json:"ranges,omitempty"`
	// contains filtered or unexported fields
}

MatchClientIP matches requests by the client IP address, i.e. the resolved address, considering trusted proxies.

func (MatchClientIP) CELLibrary

func (MatchClientIP) CELLibrary(ctx kengine.Context) (cel.Library, error)

CELLibrary produces options that expose this matcher for use in CEL expression matchers.

Example:

expression client_ip('192.168.0.0/16', '172.16.0.0/12', '10.0.0.0/8')

func (MatchClientIP) KengineModule

func (MatchClientIP) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (MatchClientIP) Match

func (m MatchClientIP) Match(r *http.Request) bool

Match returns true if r matches m.

func (*MatchClientIP) Provision

func (m *MatchClientIP) Provision(ctx kengine.Context) error

Provision parses m's IP ranges, either from IP or CIDR expressions.

func (*MatchClientIP) UnmarshalKenginefile

func (m *MatchClientIP) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile implements kenginefile.Unmarshaler.

type MatchExpression

type MatchExpression struct {
	// The CEL expression to evaluate. Any Kengine placeholders
	// will be expanded and situated into proper CEL function
	// calls before evaluating.
	Expr string `json:"expr,omitempty"`

	// Name is an optional name for this matcher.
	// This is used to populate the name for regexp
	// matchers that appear in the expression.
	Name string `json:"name,omitempty"`
	// contains filtered or unexported fields
}

MatchExpression matches requests by evaluating a [CEL](https://github.com/google/cel-spec) expression. This enables complex logic to be expressed using a comfortable, familiar syntax. Please refer to [the standard definitions of CEL functions and operators](https://github.com/google/cel-spec/blob/master/doc/langdef.md#standard-definitions).

This matcher's JSON interface is actually a string, not a struct. The generated docs are not correct because this type has custom marshaling logic.

COMPATIBILITY NOTE: This module is still experimental and is not subject to Kengine's compatibility guarantee.

func (MatchExpression) KengineModule

func (MatchExpression) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (MatchExpression) MarshalJSON

func (m MatchExpression) MarshalJSON() ([]byte, error)

MarshalJSON marshals m's expression.

func (MatchExpression) Match

func (m MatchExpression) Match(r *http.Request) bool

Match returns true if r matches m.

func (*MatchExpression) Provision

func (m *MatchExpression) Provision(ctx kengine.Context) error

Provision sets ups m.

func (*MatchExpression) UnmarshalJSON

func (m *MatchExpression) UnmarshalJSON(data []byte) error

UnmarshalJSON unmarshals m's expression.

func (*MatchExpression) UnmarshalKenginefile

func (m *MatchExpression) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile implements kenginefile.Unmarshaler.

type MatchHeader

type MatchHeader http.Header

MatchHeader matches requests by header fields. The key is the field name and the array is the list of field values. It performs fast, exact string comparisons of the field values. Fast prefix, suffix, and substring matches can also be done by suffixing, prefixing, or surrounding the value with the wildcard `*` character, respectively. If a list is null, the header must not exist. If the list is empty, the field must simply exist, regardless of its value.

**NOTE:** Notice that header values are arrays, not singular values. This is because repeated fields are valid in headers, and each one may have a different value. This matcher will match for a field if any one of its configured values matches in the header. Backend applications relying on headers MUST take into consideration that header field values are arrays and can have multiple values.

func (MatchHeader) CELLibrary

func (MatchHeader) CELLibrary(_ kengine.Context) (cel.Library, error)

CELLibrary produces options that expose this matcher for use in CEL expression matchers.

Example:

expression header({'content-type': 'image/png'})
expression header({'foo': ['bar', 'baz']}) // match bar or baz

func (MatchHeader) KengineModule

func (MatchHeader) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (MatchHeader) Match

func (m MatchHeader) Match(r *http.Request) bool

Match returns true if r matches m.

func (*MatchHeader) UnmarshalKenginefile

func (m *MatchHeader) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile implements kenginefile.Unmarshaler.

type MatchHeaderRE

type MatchHeaderRE map[string]*MatchRegexp

MatchHeaderRE matches requests by a regular expression on header fields.

Upon a match, it adds placeholders to the request: `{http.regexp.name.capture_group}` where `name` is the regular expression's name, and `capture_group` is either the named or positional capture group from the expression itself. If no name is given, then the placeholder omits the name: `{http.regexp.capture_group}` (potentially leading to collisions).

func (MatchHeaderRE) CELLibrary

func (MatchHeaderRE) CELLibrary(ctx kengine.Context) (cel.Library, error)

CELLibrary produces options that expose this matcher for use in CEL expression matchers.

Example:

expression header_regexp('foo', 'Field', 'fo+')

func (MatchHeaderRE) KengineModule

func (MatchHeaderRE) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (MatchHeaderRE) Match

func (m MatchHeaderRE) Match(r *http.Request) bool

Match returns true if r matches m.

func (MatchHeaderRE) Provision

func (m MatchHeaderRE) Provision(ctx kengine.Context) error

Provision compiles m's regular expressions.

func (*MatchHeaderRE) UnmarshalKenginefile

func (m *MatchHeaderRE) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile implements kenginefile.Unmarshaler.

func (MatchHeaderRE) Validate

func (m MatchHeaderRE) Validate() error

Validate validates m's regular expressions.

type MatchHost

type MatchHost []string

MatchHost matches requests by the Host value (case-insensitive).

When used in a top-level HTTP route, [qualifying domain names](/docs/automatic-https#hostname-requirements) may trigger [automatic HTTPS](/docs/automatic-https), which automatically provisions and renews certificates for you. Before doing this, you should ensure that DNS records for these domains are properly configured, especially A/AAAA pointed at your server.

Automatic HTTPS can be [customized or disabled](/docs/modules/http#servers/automatic_https).

Wildcards (`*`) may be used to represent exactly one label of the hostname, in accordance with RFC 1034 (because host matchers are also used for automatic HTTPS which influences TLS certificates). Thus, a host of `*` matches hosts like `localhost` or `internal` but not `example.com`. To catch all hosts, omit the host matcher entirely.

The wildcard can be useful for matching all subdomains, for example: `*.example.com` matches `foo.example.com` but not `foo.bar.example.com`.

Duplicate entries will return an error.

func (MatchHost) CELLibrary

func (MatchHost) CELLibrary(ctx kengine.Context) (cel.Library, error)

CELLibrary produces options that expose this matcher for use in CEL expression matchers.

Example:

expression host('localhost')

func (MatchHost) KengineModule

func (MatchHost) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (MatchHost) Match

func (m MatchHost) Match(r *http.Request) bool

Match returns true if r matches m.

func (MatchHost) Provision

func (m MatchHost) Provision(_ kengine.Context) error

Provision sets up and validates m, including making it more efficient for large lists.

func (*MatchHost) UnmarshalKenginefile

func (m *MatchHost) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile implements kenginefile.Unmarshaler.

type MatchMethod

type MatchMethod []string

MatchMethod matches requests by the method.

func (MatchMethod) CELLibrary

func (MatchMethod) CELLibrary(_ kengine.Context) (cel.Library, error)

CELLibrary produces options that expose this matcher for use in CEL expression matchers.

Example:

expression method('PUT', 'POST')

func (MatchMethod) KengineModule

func (MatchMethod) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (MatchMethod) Match

func (m MatchMethod) Match(r *http.Request) bool

Match returns true if r matches m.

func (*MatchMethod) UnmarshalKenginefile

func (m *MatchMethod) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile implements kenginefile.Unmarshaler.

type MatchNot

type MatchNot struct {
	MatcherSetsRaw []kengine.ModuleMap `json:"-" kengine:"namespace=http.matchers"`
	MatcherSets    []MatcherSet        `json:"-"`
}

MatchNot matches requests by negating the results of its matcher sets. A single "not" matcher takes one or more matcher sets. Each matcher set is OR'ed; in other words, if any matcher set returns true, the final result of the "not" matcher is false. Individual matchers within a set work the same (i.e. different matchers in the same set are AND'ed).

NOTE: The generated docs which describe the structure of this module are wrong because of how this type unmarshals JSON in a custom way. The correct structure is:

```json [

{},
{}

] ```

where each of the array elements is a matcher set, i.e. an object keyed by matcher name.

func (MatchNot) KengineModule

func (MatchNot) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (MatchNot) MarshalJSON

func (m MatchNot) MarshalJSON() ([]byte, error)

MarshalJSON satisfies json.Marshaler by marshaling m's raw matcher sets.

func (MatchNot) Match

func (m MatchNot) Match(r *http.Request) bool

Match returns true if r matches m. Since this matcher negates the embedded matchers, false is returned if any of its matcher sets return true.

func (*MatchNot) Provision

func (m *MatchNot) Provision(ctx kengine.Context) error

Provision loads the matcher modules to be negated.

func (*MatchNot) UnmarshalJSON

func (m *MatchNot) UnmarshalJSON(data []byte) error

UnmarshalJSON satisfies json.Unmarshaler. It puts the JSON bytes directly into m's MatcherSetsRaw field.

func (*MatchNot) UnmarshalKenginefile

func (m *MatchNot) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile implements kenginefile.Unmarshaler.

type MatchPath

type MatchPath []string

MatchPath case-insensitively matches requests by the URI's path. Path matching is exact, not prefix-based, giving you more control and clarity over matching. Wildcards (`*`) may be used:

- At the end only, for a prefix match (`/prefix/*`) - At the beginning only, for a suffix match (`*.suffix`) - On both sides only, for a substring match (`*/contains/*`) - In the middle, for a globular match (`/accounts/*/info`)

Slashes are significant; i.e. `/foo*` matches `/foo`, `/foo/`, `/foo/bar`, and `/foobar`; but `/foo/*` does not match `/foo` or `/foobar`. Valid paths start with a slash `/`.

Because there are, in general, multiple possible escaped forms of any path, path matchers operate in unescaped space; that is, path matchers should be written in their unescaped form to prevent ambiguities and possible security issues, as all request paths will be normalized to their unescaped forms before matcher evaluation.

However, escape sequences in a match pattern are supported; they are compared with the request's raw/escaped path for those bytes only. In other words, a matcher of `/foo%2Fbar` will match a request path of precisely `/foo%2Fbar`, but not `/foo/bar`. It follows that matching the literal percent sign (%) in normalized space can be done using the escaped form, `%25`.

Even though wildcards (`*`) operate in the normalized space, the special escaped wildcard (`%*`), which is not a valid escape sequence, may be used in place of a span that should NOT be decoded; that is, `/bands/%*` will match `/bands/AC%2fDC` whereas `/bands/*` will not.

Even though path matching is done in normalized space, the special wildcard `%*` may be used in place of a span that should NOT be decoded; that is, `/bands/%*/` will match `/bands/AC%2fDC/` whereas `/bands/*/` will not.

This matcher is fast, so it does not support regular expressions or capture groups. For slower but more powerful matching, use the path_regexp matcher. (Note that due to the special treatment of escape sequences in matcher patterns, they may perform slightly slower in high-traffic environments.)

func (MatchPath) CELLibrary

func (MatchPath) CELLibrary(ctx kengine.Context) (cel.Library, error)

CELLibrary produces options that expose this matcher for use in CEL expression matchers.

Example:

expression path('*substring*', '*suffix')

func (MatchPath) KengineModule

func (MatchPath) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (MatchPath) Match

func (m MatchPath) Match(r *http.Request) bool

Match returns true if r matches m.

func (MatchPath) Provision

func (m MatchPath) Provision(_ kengine.Context) error

Provision lower-cases the paths in m to ensure case-insensitive matching.

func (*MatchPath) UnmarshalKenginefile

func (m *MatchPath) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile implements kenginefile.Unmarshaler.

type MatchPathRE

type MatchPathRE struct{ MatchRegexp }

MatchPathRE matches requests by a regular expression on the URI's path. Path matching is performed in the unescaped (decoded) form of the path.

Upon a match, it adds placeholders to the request: `{http.regexp.name.capture_group}` where `name` is the regular expression's name, and `capture_group` is either the named or positional capture group from the expression itself. If no name is given, then the placeholder omits the name: `{http.regexp.capture_group}` (potentially leading to collisions).

func (MatchPathRE) CELLibrary

func (MatchPathRE) CELLibrary(ctx kengine.Context) (cel.Library, error)

CELLibrary produces options that expose this matcher for use in CEL expression matchers.

Example:

expression path_regexp('^/bar')

func (MatchPathRE) KengineModule

func (MatchPathRE) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (MatchPathRE) Match

func (m MatchPathRE) Match(r *http.Request) bool

Match returns true if r matches m.

type MatchProtocol

type MatchProtocol string

MatchProtocol matches requests by protocol. Recognized values are "http", "https", and "grpc" for broad protocol matches, or specific HTTP versions can be specified like so: "http/1", "http/1.1", "http/2", "http/3", or minimum versions: "http/2+", etc.

func (MatchProtocol) CELLibrary

func (MatchProtocol) CELLibrary(_ kengine.Context) (cel.Library, error)

CELLibrary produces options that expose this matcher for use in CEL expression matchers.

Example:

expression protocol('https')

func (MatchProtocol) KengineModule

func (MatchProtocol) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (MatchProtocol) Match

func (m MatchProtocol) Match(r *http.Request) bool

Match returns true if r matches m.

func (*MatchProtocol) UnmarshalKenginefile

func (m *MatchProtocol) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile implements kenginefile.Unmarshaler.

type MatchQuery

type MatchQuery url.Values

MatchQuery matches requests by the URI's query string. It takes a JSON object keyed by the query keys, with an array of string values to match for that key. Query key matches are exact, but wildcards may be used for value matches. Both keys and values may be placeholders.

An example of the structure to match `?key=value&topic=api&query=something` is:

```json

{
	"key": ["value"],
	"topic": ["api"],
	"query": ["*"]
}

```

Invalid query strings, including those with bad escapings or illegal characters like semicolons, will fail to parse and thus fail to match.

**NOTE:** Notice that query string values are arrays, not singular values. This is because repeated keys are valid in query strings, and each one may have a different value. This matcher will match for a key if any one of its configured values is assigned in the query string. Backend applications relying on query strings MUST take into consideration that query string values are arrays and can have multiple values.

func (MatchQuery) CELLibrary

func (MatchQuery) CELLibrary(_ kengine.Context) (cel.Library, error)

CELLibrary produces options that expose this matcher for use in CEL expression matchers.

Example:

expression query({'sort': 'asc'}) || query({'foo': ['*bar*', 'baz']})

func (MatchQuery) KengineModule

func (MatchQuery) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (MatchQuery) Match

func (m MatchQuery) Match(r *http.Request) bool

Match returns true if r matches m. An empty m matches an empty query string.

func (*MatchQuery) UnmarshalKenginefile

func (m *MatchQuery) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile implements kenginefile.Unmarshaler.

type MatchRegexp

type MatchRegexp struct {
	// A unique name for this regular expression. Optional,
	// but useful to prevent overwriting captures from other
	// regexp matchers.
	Name string `json:"name,omitempty"`

	// The regular expression to evaluate, in RE2 syntax,
	// which is the same general syntax used by Go, Perl,
	// and Python. For details, see
	// [Go's regexp package](https://golang.org/pkg/regexp/).
	// Captures are accessible via placeholders. Unnamed
	// capture groups are exposed as their numeric, 1-based
	// index, while named capture groups are available by
	// the capture group name.
	Pattern string `json:"pattern"`
	// contains filtered or unexported fields
}

MatchRegexp is an embedable type for matching using regular expressions. It adds placeholders to the request's replacer.

func (*MatchRegexp) Match

func (mre *MatchRegexp) Match(input string, repl *kengine.Replacer) bool

Match returns true if input matches the compiled regular expression in mre. It sets values on the replacer repl associated with capture groups, using the given scope (namespace).

func (*MatchRegexp) Provision

func (mre *MatchRegexp) Provision(kengine.Context) error

Provision compiles the regular expression.

func (*MatchRegexp) UnmarshalKenginefile

func (mre *MatchRegexp) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile implements kenginefile.Unmarshaler.

func (*MatchRegexp) Validate

func (mre *MatchRegexp) Validate() error

Validate ensures mre is set up correctly.

type MatchRemoteIP

type MatchRemoteIP struct {
	// The IPs or CIDR ranges to match.
	Ranges []string `json:"ranges,omitempty"`
	// contains filtered or unexported fields
}

MatchRemoteIP matches requests by the remote IP address, i.e. the IP address of the direct connection to Kengine.

func (MatchRemoteIP) CELLibrary

func (MatchRemoteIP) CELLibrary(ctx kengine.Context) (cel.Library, error)

CELLibrary produces options that expose this matcher for use in CEL expression matchers.

Example:

expression remote_ip('192.168.0.0/16', '172.16.0.0/12', '10.0.0.0/8')

func (MatchRemoteIP) KengineModule

func (MatchRemoteIP) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (MatchRemoteIP) Match

func (m MatchRemoteIP) Match(r *http.Request) bool

Match returns true if r matches m.

func (*MatchRemoteIP) Provision

func (m *MatchRemoteIP) Provision(ctx kengine.Context) error

Provision parses m's IP ranges, either from IP or CIDR expressions.

func (*MatchRemoteIP) UnmarshalKenginefile

func (m *MatchRemoteIP) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile implements kenginefile.Unmarshaler.

type MatchTLS

type MatchTLS struct {
	// Matches if the TLS handshake has completed. QUIC 0-RTT early
	// data may arrive before the handshake completes. Generally, it
	// is unsafe to replay these requests if they are not idempotent;
	// additionally, the remote IP of early data packets can more
	// easily be spoofed. It is conventional to respond with HTTP 425
	// Too Early if the request cannot risk being processed in this
	// state.
	HandshakeComplete *bool `json:"handshake_complete,omitempty"`
}

MatchTLS matches HTTP requests based on the underlying TLS connection state. If this matcher is specified but the request did not come over TLS, it will never match. If this matcher is specified but is empty and the request did come in over TLS, it will always match.

func (MatchTLS) KengineModule

func (MatchTLS) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (MatchTLS) Match

func (m MatchTLS) Match(r *http.Request) bool

Match returns true if r matches m.

func (*MatchTLS) UnmarshalKenginefile

func (m *MatchTLS) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile parses Kenginefile tokens for this matcher. Syntax:

... tls [early_data]

EXPERIMENTAL SYNTAX: Subject to change.

type MatchVarsRE

type MatchVarsRE map[string]*MatchRegexp

MatchVarsRE matches the value of the context variables by a given regular expression.

Upon a match, it adds placeholders to the request: `{http.regexp.name.capture_group}` where `name` is the regular expression's name, and `capture_group` is either the named or positional capture group from the expression itself. If no name is given, then the placeholder omits the name: `{http.regexp.capture_group}` (potentially leading to collisions).

func (MatchVarsRE) KengineModule

func (MatchVarsRE) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (MatchVarsRE) Match

func (m MatchVarsRE) Match(r *http.Request) bool

Match returns true if r matches m.

func (MatchVarsRE) Provision

func (m MatchVarsRE) Provision(ctx kengine.Context) error

Provision compiles m's regular expressions.

func (*MatchVarsRE) UnmarshalKenginefile

func (m *MatchVarsRE) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile implements kenginefile.Unmarshaler.

func (MatchVarsRE) Validate

func (m MatchVarsRE) Validate() error

Validate validates m's regular expressions.

type MatcherSet

type MatcherSet []RequestMatcher

MatcherSet is a set of matchers which must all match in order for the request to be matched successfully.

func (MatcherSet) Match

func (mset MatcherSet) Match(r *http.Request) bool

Match returns true if the request matches all matchers in mset or if there are no matchers.

type MatcherSets

type MatcherSets []MatcherSet

MatcherSets is a group of matcher sets capable of checking whether a request matches any of the sets.

func (MatcherSets) AnyMatch

func (ms MatcherSets) AnyMatch(req *http.Request) bool

AnyMatch returns true if req matches any of the matcher sets in ms or if there are no matchers, in which case the request always matches.

func (*MatcherSets) FromInterface

func (ms *MatcherSets) FromInterface(matcherSets any) error

FromInterface fills ms from an 'any' value obtained from LoadModule.

func (MatcherSets) String

func (ms MatcherSets) String() string

TODO: Is this used?

type Metrics

type Metrics struct{}

Metrics configures metrics observations. EXPERIMENTAL and subject to change or removal.

type Middleware

type Middleware func(Handler) Handler

Middleware chains one Handler to the next by being passed the next Handler in the chain.

type MiddlewareHandler

type MiddlewareHandler interface {
	ServeHTTP(http.ResponseWriter, *http.Request, Handler) error
}

MiddlewareHandler is like Handler except it takes as a third argument the next handler in the chain. The next handler will never be nil, but may be a no-op handler if this is the last handler in the chain. Handlers which act as middleware should call the next handler's ServeHTTP method so as to propagate the request down the chain properly. Handlers which act as responders (content origins) need not invoke the next handler, since the last handler in the chain should be the first to write the response.

type RawMatcherSets

type RawMatcherSets []kengine.ModuleMap

RawMatcherSets is a group of matcher sets in their raw, JSON form.

type RequestMatcher

type RequestMatcher interface {
	Match(*http.Request) bool
}

RequestMatcher is a type that can match to a request. A route matcher MUST NOT modify the request, with the only exception being its context.

type ResponseHandler

type ResponseHandler struct {
	// The response matcher for this handler. If empty/nil,
	// it always matches.
	Match *ResponseMatcher `json:"match,omitempty"`

	// To write the original response body but with a different
	// status code, set this field to the desired status code.
	// If set, this takes priority over routes.
	StatusCode WeakString `json:"status_code,omitempty"`

	// The list of HTTP routes to execute if no status code is
	// specified. If evaluated, the original response body
	// will not be written.
	Routes RouteList `json:"routes,omitempty"`
}

ResponseHandler pairs a response matcher with custom handling logic. Either the status code can be changed to something else while using the original response body, or, if a status code is not set, it can execute a custom route list; this is useful for executing handler routes based on the properties of an HTTP response that has not been written out to the client yet.

To use this type, provision it at module load time, then when ready to use, match the response against its matcher; if it matches (or doesn't have a matcher), change the status code on the response if configured; otherwise invoke the routes by calling `rh.Routes.Compile(next).ServeHTTP(rw, req)` (or similar).

func (*ResponseHandler) Provision

func (rh *ResponseHandler) Provision(ctx kengine.Context) error

Provision sets up the routes in rh.

type ResponseMatcher

type ResponseMatcher struct {
	// If set, one of these status codes would be required.
	// A one-digit status can be used to represent all codes
	// in that class (e.g. 3 for all 3xx codes).
	StatusCode []int `json:"status_code,omitempty"`

	// If set, each header specified must be one of the
	// specified values, with the same logic used by the
	// [request header matcher](/docs/json/apps/http/servers/routes/match/header/).
	Headers http.Header `json:"headers,omitempty"`
}

ResponseMatcher is a type which can determine if an HTTP response matches some criteria.

func (ResponseMatcher) Match

func (rm ResponseMatcher) Match(statusCode int, hdr http.Header) bool

Match returns true if the given statusCode and hdr match rm.

type ResponseRecorder

type ResponseRecorder interface {
	http.ResponseWriter
	Status() int
	Buffer() *bytes.Buffer
	Buffered() bool
	Size() int
	WriteResponse() error
}

ResponseRecorder is a http.ResponseWriter that records responses instead of writing them to the client. See docs for NewResponseRecorder for proper usage.

func NewResponseRecorder

func NewResponseRecorder(w http.ResponseWriter, buf *bytes.Buffer, shouldBuffer ShouldBufferFunc) ResponseRecorder

NewResponseRecorder returns a new ResponseRecorder that can be used instead of a standard http.ResponseWriter. The recorder is useful for middlewares which need to buffer a response and potentially process its entire body before actually writing the response to the underlying writer. Of course, buffering the entire body has a memory overhead, but sometimes there is no way to avoid buffering the whole response, hence the existence of this type. Still, if at all practical, handlers should strive to stream responses by wrapping Write and WriteHeader methods instead of buffering whole response bodies.

Buffering is actually optional. The shouldBuffer function will be called just before the headers are written. If it returns true, the headers and body will be buffered by this recorder and not written to the underlying writer; if false, the headers will be written immediately and the body will be streamed out directly to the underlying writer. If shouldBuffer is nil, the response will never be buffered and will always be streamed directly to the writer.

You can know if shouldBuffer returned true by calling Buffered().

The provided buffer buf should be obtained from a pool for best performance (see the sync.Pool type).

Proper usage of a recorder looks like this:

rec := kenginehttp.NewResponseRecorder(w, buf, shouldBuffer)
err := next.ServeHTTP(rec, req)
if err != nil {
    return err
}
if !rec.Buffered() {
    return nil
}
// process the buffered response here

The header map is not buffered; i.e. the ResponseRecorder's Header() method returns the same header map of the underlying ResponseWriter. This is a crucial design decision to allow HTTP trailers to be flushed properly (https://github.com/khulnasoft/kengine/issues/3236).

Once you are ready to write the response, there are two ways you can do it. The easier way is to have the recorder do it:

rec.WriteResponse()

This writes the recorded response headers as well as the buffered body. Or, you may wish to do it yourself, especially if you manipulated the buffered body. First you will need to write the headers with the recorded status code, then write the body (this example writes the recorder's body buffer, but you might have your own body to write instead):

w.WriteHeader(rec.Status())
io.Copy(w, rec.Buffer())

As a special case, 1xx responses are not buffered nor recorded because they are not the final response; they are passed through directly to the underlying ResponseWriter.

type ResponseWriterWrapper

type ResponseWriterWrapper struct {
	http.ResponseWriter
}

ResponseWriterWrapper wraps an underlying ResponseWriter and promotes its Pusher method as well. To use this type, embed a pointer to it within your own struct type that implements the http.ResponseWriter interface, then call methods on the embedded value.

func (*ResponseWriterWrapper) Push

func (rww *ResponseWriterWrapper) Push(target string, opts *http.PushOptions) error

Push implements http.Pusher. It simply calls the underlying ResponseWriter's Push method if there is one, or returns ErrNotImplemented otherwise.

func (*ResponseWriterWrapper) ReadFrom

func (rww *ResponseWriterWrapper) ReadFrom(r io.Reader) (n int64, err error)

ReadFrom implements io.ReaderFrom. It simply calls io.Copy, which uses io.ReaderFrom if available.

func (*ResponseWriterWrapper) Unwrap

Unwrap returns the underlying ResponseWriter, necessary for http.ResponseController to work correctly.

type Route

type Route struct {
	// Group is an optional name for a group to which this
	// route belongs. Grouping a route makes it mutually
	// exclusive with others in its group; if a route belongs
	// to a group, only the first matching route in that group
	// will be executed.
	Group string `json:"group,omitempty"`

	// The matcher sets which will be used to qualify this
	// route for a request (essentially the "if" statement
	// of this route). Each matcher set is OR'ed, but matchers
	// within a set are AND'ed together.
	MatcherSetsRaw RawMatcherSets `json:"match,omitempty" kengine:"namespace=http.matchers"`

	// The list of handlers for this route. Upon matching a request, they are chained
	// together in a middleware fashion: requests flow from the first handler to the last
	// (top of the list to the bottom), with the possibility that any handler could stop
	// the chain and/or return an error. Responses flow back through the chain (bottom of
	// the list to the top) as they are written out to the client.
	//
	// Not all handlers call the next handler in the chain. For example, the reverse_proxy
	// handler always sends a request upstream or returns an error. Thus, configuring
	// handlers after reverse_proxy in the same route is illogical, since they would never
	// be executed. You will want to put handlers which originate the response at the very
	// end of your route(s). The documentation for a module should state whether it invokes
	// the next handler, but sometimes it is common sense.
	//
	// Some handlers manipulate the response. Remember that requests flow down the list, and
	// responses flow up the list.
	//
	// For example, if you wanted to use both `templates` and `encode` handlers, you would
	// need to put `templates` after `encode` in your route, because responses flow up.
	// Thus, `templates` will be able to parse and execute the plain-text response as a
	// template, and then return it up to the `encode` handler which will then compress it
	// into a binary format.
	//
	// If `templates` came before `encode`, then `encode` would write a compressed,
	// binary-encoded response to `templates` which would not be able to parse the response
	// properly.
	//
	// The correct order, then, is this:
	//
	//     [
	//         {"handler": "encode"},
	//         {"handler": "templates"},
	//         {"handler": "file_server"}
	//     ]
	//
	// The request flows ⬇️ DOWN (`encode` -> `templates` -> `file_server`).
	//
	// 1. First, `encode` will choose how to `encode` the response and wrap the response.
	// 2. Then, `templates` will wrap the response with a buffer.
	// 3. Finally, `file_server` will originate the content from a file.
	//
	// The response flows ⬆️ UP (`file_server` -> `templates` -> `encode`):
	//
	// 1. First, `file_server` will write the file to the response.
	// 2. That write will be buffered and then executed by `templates`.
	// 3. Lastly, the write from `templates` will flow into `encode` which will compress the stream.
	//
	// If you think of routes in this way, it will be easy and even fun to solve the puzzle of writing correct routes.
	HandlersRaw []json.RawMessage `json:"handle,omitempty" kengine:"namespace=http.handlers inline_key=handler"`

	// If true, no more routes will be executed after this one.
	Terminal bool `json:"terminal,omitempty"`

	// decoded values
	MatcherSets MatcherSets         `json:"-"`
	Handlers    []MiddlewareHandler `json:"-"`
	// contains filtered or unexported fields
}

Route consists of a set of rules for matching HTTP requests, a list of handlers to execute, and optional flow control parameters which customize the handling of HTTP requests in a highly flexible and performant manner.

func (Route) Compile

func (r Route) Compile(next Handler) Handler

Compile prepares a middleware chain from the route list. This should only be done once during the request, just before the middleware chain is executed.

func (Route) Empty

func (r Route) Empty() bool

Empty returns true if the route has all zero/default values.

func (*Route) Provision

func (r *Route) Provision(ctx kengine.Context, metrics *Metrics) error

Provision sets up both the matchers and handlers in the route.

func (*Route) ProvisionHandlers

func (r *Route) ProvisionHandlers(ctx kengine.Context, metrics *Metrics) error

ProvisionHandlers sets up all the handlers by loading the handler modules. Only call this method directly if you need to set up matchers and handlers separately without having to provision a second time; otherwise use Provision instead.

func (*Route) ProvisionMatchers

func (r *Route) ProvisionMatchers(ctx kengine.Context) error

ProvisionMatchers sets up all the matchers by loading the matcher modules. Only call this method directly if you need to set up matchers and handlers separately without having to provision a second time; otherwise use Provision instead.

func (Route) String

func (r Route) String() string

type RouteList

type RouteList []Route

RouteList is a list of server routes that can create a middleware chain.

func (RouteList) Compile

func (routes RouteList) Compile(next Handler) Handler

Compile prepares a middleware chain from the route list. This should only be done either once during provisioning for top-level routes, or on each request just before the middleware chain is executed for subroutes.

func (RouteList) Provision

func (routes RouteList) Provision(ctx kengine.Context) error

Provision sets up both the matchers and handlers in the routes.

func (RouteList) ProvisionHandlers

func (routes RouteList) ProvisionHandlers(ctx kengine.Context, metrics *Metrics) error

ProvisionHandlers sets up all the handlers by loading the handler modules. Only call this method directly if you need to set up matchers and handlers separately without having to provision a second time; otherwise use Provision instead.

func (RouteList) ProvisionMatchers

func (routes RouteList) ProvisionMatchers(ctx kengine.Context) error

ProvisionMatchers sets up all the matchers by loading the matcher modules. Only call this method directly if you need to set up matchers and handlers separately without having to provision a second time; otherwise use Provision instead.

type Server

type Server struct {
	// Socket addresses to which to bind listeners. Accepts
	// [network addresses](/docs/conventions#network-addresses)
	// that may include port ranges. Listener addresses must
	// be unique; they cannot be repeated across all defined
	// servers.
	Listen []string `json:"listen,omitempty"`

	// A list of listener wrapper modules, which can modify the behavior
	// of the base listener. They are applied in the given order.
	ListenerWrappersRaw []json.RawMessage `json:"listener_wrappers,omitempty" kengine:"namespace=kengine.listeners inline_key=wrapper"`

	// How long to allow a read from a client's upload. Setting this
	// to a short, non-zero value can mitigate slowloris attacks, but
	// may also affect legitimately slow clients.
	ReadTimeout kengine.Duration `json:"read_timeout,omitempty"`

	// ReadHeaderTimeout is like ReadTimeout but for request headers.
	ReadHeaderTimeout kengine.Duration `json:"read_header_timeout,omitempty"`

	// WriteTimeout is how long to allow a write to a client. Note
	// that setting this to a small value when serving large files
	// may negatively affect legitimately slow clients.
	WriteTimeout kengine.Duration `json:"write_timeout,omitempty"`

	// IdleTimeout is the maximum time to wait for the next request
	// when keep-alives are enabled. If zero, a default timeout of
	// 5m is applied to help avoid resource exhaustion.
	IdleTimeout kengine.Duration `json:"idle_timeout,omitempty"`

	// KeepAliveInterval is the interval at which TCP keepalive packets
	// are sent to keep the connection alive at the TCP layer when no other
	// data is being transmitted. The default is 15s.
	KeepAliveInterval kengine.Duration `json:"keepalive_interval,omitempty"`

	// MaxHeaderBytes is the maximum size to parse from a client's
	// HTTP request headers.
	MaxHeaderBytes int `json:"max_header_bytes,omitempty"`

	// Enable full-duplex communication for HTTP/1 requests.
	// Only has an effect if Kengine was built with Go 1.21 or later.
	//
	// For HTTP/1 requests, the Go HTTP server by default consumes any
	// unread portion of the request body before beginning to write the
	// response, preventing handlers from concurrently reading from the
	// request and writing the response. Enabling this option disables
	// this behavior and permits handlers to continue to read from the
	// request while concurrently writing the response.
	//
	// For HTTP/2 requests, the Go HTTP server always permits concurrent
	// reads and responses, so this option has no effect.
	//
	// Test thoroughly with your HTTP clients, as some older clients may
	// not support full-duplex HTTP/1 which can cause them to deadlock.
	// See https://github.com/golang/go/issues/57786 for more info.
	//
	// TODO: This is an EXPERIMENTAL feature. Subject to change or removal.
	EnableFullDuplex bool `json:"enable_full_duplex,omitempty"`

	// Routes describes how this server will handle requests.
	// Routes are executed sequentially. First a route's matchers
	// are evaluated, then its grouping. If it matches and has
	// not been mutually-excluded by its grouping, then its
	// handlers are executed sequentially. The sequence of invoked
	// handlers comprises a compiled middleware chain that flows
	// from each matching route and its handlers to the next.
	//
	// By default, all unrouted requests receive a 200 OK response
	// to indicate the server is working.
	Routes RouteList `json:"routes,omitempty"`

	// Errors is how this server will handle errors returned from any
	// 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"`

	// NamedRoutes describes a mapping of reusable routes that can be
	// invoked by their name. This can be used to optimize memory usage
	// when the same route is needed for many subroutes, by having
	// the handlers and matchers be only provisioned once, but used from
	// many places. These routes are not executed unless they are invoked
	// from another route.
	//
	// EXPERIMENTAL: Subject to change or removal.
	NamedRoutes map[string]*Route `json:"named_routes,omitempty"`

	// How to handle TLS connections. At least one policy is
	// required to enable HTTPS on this server if automatic
	// HTTPS is disabled or does not apply.
	TLSConnPolicies kenginetls.ConnectionPolicies `json:"tls_connection_policies,omitempty"`

	// AutoHTTPS configures or disables automatic HTTPS within this server.
	// HTTPS is enabled automatically and by default when qualifying names
	// are present in a Host matcher and/or when the server is listening
	// only on the HTTPS port.
	AutoHTTPS *AutoHTTPSConfig `json:"automatic_https,omitempty"`

	// If true, will require that a request's Host header match
	// the value of the ServerName sent by the client's TLS
	// ClientHello; often a necessary safeguard when using TLS
	// client authentication.
	StrictSNIHost *bool `json:"strict_sni_host,omitempty"`

	// A module which provides a source of IP ranges, from which
	// requests should be trusted. By default, no proxies are
	// trusted.
	//
	// On its own, this configuration will not do anything,
	// but it can be used as a default set of ranges for
	// handlers or matchers in routes to pick up, instead
	// of needing to configure each of them. See the
	// `reverse_proxy` handler for example, which uses this
	// to trust sensitive incoming `X-Forwarded-*` headers.
	TrustedProxiesRaw json.RawMessage `json:"trusted_proxies,omitempty" kengine:"namespace=http.ip_sources inline_key=source"`

	// The headers from which the client IP address could be
	// read from. These will be considered in order, with the
	// first good value being used as the client IP.
	// By default, only `X-Forwarded-For` is considered.
	//
	// This depends on `trusted_proxies` being configured and
	// the request being validated as coming from a trusted
	// proxy, otherwise the client IP will be set to the direct
	// remote IP address.
	ClientIPHeaders []string `json:"client_ip_headers,omitempty"`

	// If greater than zero, enables strict ClientIPHeaders
	// (default X-Forwarded-For) parsing. If enabled, the
	// ClientIPHeaders will be parsed from right to left, and
	// the first value that is both valid and doesn't match the
	// trusted proxy list will be used as client IP. If zero,
	// the ClientIPHeaders will be parsed from left to right,
	// and the first value that is a valid IP address will be
	// used as client IP.
	//
	// This depends on `trusted_proxies` being configured.
	// This option is disabled by default.
	TrustedProxiesStrict int `json:"trusted_proxies_strict,omitempty"`

	// Enables access logging and configures how access logs are handled
	// in this server. To minimally enable access logs, simply set this
	// to a non-null, empty struct.
	Logs *ServerLogConfig `json:"logs,omitempty"`

	// Protocols specifies which HTTP protocols to enable.
	// Supported values are:
	//
	// - `h1` (HTTP/1.1)
	// - `h2` (HTTP/2)
	// - `h2c` (cleartext HTTP/2)
	// - `h3` (HTTP/3)
	//
	// If enabling `h2` or `h2c`, `h1` must also be enabled;
	// this is due to current limitations in the Go standard
	// library.
	//
	// HTTP/2 operates only over TLS (HTTPS). HTTP/3 opens
	// a UDP socket to serve QUIC connections.
	//
	// H2C operates over plain TCP if the client supports it;
	// however, because this is not implemented by the Go
	// standard library, other server options are not compatible
	// and will not be applied to H2C requests. Do not enable this
	// only to achieve maximum client compatibility. In practice,
	// very few clients implement H2C, and even fewer require it.
	// Enabling H2C can be useful for serving/proxying gRPC
	// if encryption is not possible or desired.
	//
	// We recommend for most users to simply let Kengine use the
	// default settings.
	//
	// Default: `[h1 h2 h3]`
	Protocols []string `json:"protocols,omitempty"`

	// If set, metrics observations will be enabled.
	// This setting is EXPERIMENTAL and subject to change.
	Metrics *Metrics `json:"metrics,omitempty"`
	// contains filtered or unexported fields
}

Server describes an HTTP server.

func (*Server) Listeners

func (s *Server) Listeners() []net.Listener

Listeners returns the server's listeners. These are active listeners, so calling Accept() or Close() on them will probably break things. They are made available here for read-only purposes (e.g. Addr()) and for type-asserting for purposes where you know what you're doing.

EXPERIMENTAL: Subject to change or removal.

func (*Server) Name

func (s *Server) Name() string

Name returns the server's name.

func (*Server) RegisterConnContext

func (s *Server) RegisterConnContext(f func(ctx context.Context, c net.Conn) context.Context)

RegisterConnContext registers f to be invoked as part of s.ConnContext.

func (*Server) RegisterConnState

func (s *Server) RegisterConnState(f func(net.Conn, http.ConnState))

RegisterConnState registers f to be invoked on s.ConnState.

func (*Server) RegisterOnShutdown

func (s *Server) RegisterOnShutdown(f func())

RegisterOnShutdown registers f to be invoked when the server begins to shut down.

func (*Server) RegisterOnStop

func (s *Server) RegisterOnStop(f func(context.Context) error)

RegisterOnStop registers f to be invoked after the server has shut down completely.

EXPERIMENTAL: Subject to change or removal.

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP is the entry point for all HTTP requests.

type ServerLogConfig

type ServerLogConfig struct {
	// The default logger name for all logs emitted by this server for
	// hostnames that are not in the logger_names map.
	DefaultLoggerName string `json:"default_logger_name,omitempty"`

	// LoggerNames maps request hostnames to one or more custom logger
	// names. For example, a mapping of `"example.com": ["example"]` would
	// cause access logs from requests with a Host of example.com to be
	// emitted by a logger named "http.log.access.example". If there are
	// multiple logger names, then the log will be emitted to all of them.
	// If the logger name is an empty, the default logger is used, i.e.
	// the logger "http.log.access".
	//
	// Keys must be hostnames (without ports), and may contain wildcards
	// to match subdomains. The value is an array of logger names.
	//
	// For backwards compatibility, if the value is a string, it is treated
	// as a single-element array.
	LoggerNames map[string]StringArray `json:"logger_names,omitempty"`

	// By default, all requests to this server will be logged if
	// access logging is enabled. This field lists the request
	// hosts for which access logging should be disabled.
	SkipHosts []string `json:"skip_hosts,omitempty"`

	// If true, requests to any host not appearing in the
	// logger_names map will not be logged.
	SkipUnmappedHosts bool `json:"skip_unmapped_hosts,omitempty"`

	// If true, credentials that are otherwise omitted, will be logged.
	// The definition of credentials is defined by https://fetch.spec.whatwg.org/#credentials,
	// and this includes some request and response headers, i.e `Cookie`,
	// `Set-Cookie`, `Authorization`, and `Proxy-Authorization`.
	ShouldLogCredentials bool `json:"should_log_credentials,omitempty"`

	// Log each individual handler that is invoked.
	// Requires that the log emit at DEBUG level.
	//
	// NOTE: This may log the configuration of your
	// HTTP handler modules; do not enable this in
	// insecure contexts when there is sensitive
	// data in the configuration.
	//
	// EXPERIMENTAL: Subject to change or removal.
	Trace bool `json:"trace,omitempty"`
}

ServerLogConfig describes a server's logging configuration. If enabled without customization, all requests to this server are logged to the default logger; logger destinations may be customized per-request-host.

type ShouldBufferFunc

type ShouldBufferFunc func(status int, header http.Header) bool

ShouldBufferFunc is a function that returns true if the response should be buffered, given the pending HTTP status code and response headers.

type StaticError

type StaticError struct {
	// The error message. Optional. Default is no error message.
	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.
	StatusCode WeakString `json:"status_code,omitempty"`
}

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.

func (StaticError) KengineModule

func (StaticError) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (StaticError) ServeHTTP

func (e StaticError) ServeHTTP(w http.ResponseWriter, r *http.Request, _ Handler) error

func (*StaticError) UnmarshalKenginefile

func (e *StaticError) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile sets up the handler from Kenginefile tokens. Syntax:

error [<matcher>] <status>|<message> [<status>] {
    message <text>
}

If there is just one argument (other than the matcher), it is considered to be a status code if it's a valid positive integer of 3 digits.

type StaticIPRange

type StaticIPRange struct {
	// A static list of IP ranges (supports CIDR notation).
	Ranges []string `json:"ranges,omitempty"`
	// contains filtered or unexported fields
}

StaticIPRange provides a static range of IP address prefixes (CIDRs).

func (*StaticIPRange) GetIPRanges

func (s *StaticIPRange) GetIPRanges(_ *http.Request) []netip.Prefix

func (StaticIPRange) KengineModule

func (StaticIPRange) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (*StaticIPRange) Provision

func (s *StaticIPRange) Provision(ctx kengine.Context) error

func (*StaticIPRange) UnmarshalKenginefile

func (m *StaticIPRange) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile implements kenginefile.Unmarshaler.

type StaticResponse

type StaticResponse struct {
	// The HTTP status code to respond with. Can be an integer or,
	// if needing to use a placeholder, a string.
	//
	// If the status code is 103 (Early Hints), the response headers
	// will be written to the client immediately, the body will be
	// ignored, and the next handler will be invoked. This behavior
	// is EXPERIMENTAL while RFC 8297 is a draft, and may be changed
	// or removed.
	StatusCode WeakString `json:"status_code,omitempty"`

	// Header fields to set on the response; overwrites any existing
	// header fields of the same names after normalization.
	Headers http.Header `json:"headers,omitempty"`

	// The response body. If non-empty, the Content-Type header may
	// be added automatically if it is not explicitly configured nor
	// already set on the response; the default value is
	// "text/plain; charset=utf-8" unless the body is a valid JSON object
	// or array, in which case the value will be "application/json".
	// Other than those common special cases the Content-Type header
	// should be set explicitly if it is desired because MIME sniffing
	// is disabled for safety.
	Body string `json:"body,omitempty"`

	// If true, the server will close the client's connection
	// after writing the response.
	Close bool `json:"close,omitempty"`

	// Immediately and forcefully closes the connection without
	// writing a response. Interrupts any other HTTP streams on
	// the same connection.
	Abort bool `json:"abort,omitempty"`
}

StaticResponse implements a simple responder for static responses.

func (StaticResponse) KengineModule

func (StaticResponse) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (StaticResponse) ServeHTTP

func (s StaticResponse) ServeHTTP(w http.ResponseWriter, r *http.Request, next Handler) error

func (*StaticResponse) UnmarshalKenginefile

func (s *StaticResponse) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile sets up the handler from Kenginefile tokens. Syntax:

respond [<matcher>] <status>|<body> [<status>] {
    body <text>
    close
}

If there is just one argument (other than the matcher), it is considered to be a status code if it's a valid positive integer of 3 digits.

type StringArray

type StringArray []string

StringArray is a slices of strings, but also accepts a single string as a value when JSON unmarshaling, converting it to a slice of one string.

func (*StringArray) UnmarshalJSON

func (sa *StringArray) UnmarshalJSON(b []byte) error

UnmarshalJSON satisfies json.Unmarshaler.

type Subroute

type Subroute struct {
	// 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"`
}

Subroute implements a handler that compiles and executes routes. This is useful for a batch of routes that all inherit the same matchers, or for multiple routes that should be treated as a single route.

You can also use subroutes to handle errors from its handlers. First the primary routes will be executed, and if they return an error, the errors routes will be executed; in that case, an error is only returned to the entry point at the server if there is an additional error returned from the errors routes.

func (Subroute) KengineModule

func (Subroute) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (*Subroute) Provision

func (sr *Subroute) Provision(ctx kengine.Context) error

Provision sets up subrouting.

func (*Subroute) ServeHTTP

func (sr *Subroute) ServeHTTP(w http.ResponseWriter, r *http.Request, next Handler) error

type VarsMatcher

type VarsMatcher map[string][]string

VarsMatcher is an HTTP request matcher which can match requests based on variables in the context or placeholder values. The key is the placeholder or name of the variable, and the values are possible values the variable can be in order to match (logical OR'ed).

If the key is surrounded by `{ }` it is assumed to be a placeholder. Otherwise, it will be considered a variable name.

Placeholders in the keys are not expanded, but placeholders in the values are.

func (VarsMatcher) KengineModule

func (VarsMatcher) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (VarsMatcher) Match

func (m VarsMatcher) Match(r *http.Request) bool

Match matches a request based on variables in the context, or placeholders if the key is not a variable.

func (*VarsMatcher) UnmarshalKenginefile

func (m *VarsMatcher) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile implements kenginefile.Unmarshaler.

type VarsMiddleware

type VarsMiddleware map[string]any

VarsMiddleware is an HTTP middleware which sets variables to have values that can be used in the HTTP request handler chain. The primary way to access variables is with placeholders, which have the form: `{http.vars.variable_name}`, or with the `vars` and `vars_regexp` request matchers.

The key is the variable name, and the value is the value of the variable. Both the name and value may use or contain placeholders.

func (VarsMiddleware) KengineModule

func (VarsMiddleware) KengineModule() kengine.ModuleInfo

KengineModule returns the Kengine module information.

func (VarsMiddleware) ServeHTTP

func (m VarsMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next Handler) error

func (*VarsMiddleware) UnmarshalKenginefile

func (m *VarsMiddleware) UnmarshalKenginefile(d *kenginefile.Dispenser) error

UnmarshalKenginefile implements kenginefile.Unmarshaler. Syntax:

vars [<name> <val>] {
    <name> <val>
    ...
}

type WeakString

type WeakString string

WeakString is a type that unmarshals any JSON value as a string literal, with the following exceptions:

1. actual string values are decoded as strings; and 2. null is decoded as empty string;

and provides methods for getting the value as various primitive types. However, using this type removes any type safety as far as deserializing JSON is concerned.

func (WeakString) Bool

func (ws WeakString) Bool() bool

Bool returns ws as a boolean. If ws is not a boolean, false is returned.

func (WeakString) Float64

func (ws WeakString) Float64() float64

Float64 returns ws as a float64. If ws is not a float value, the zero value is returned.

func (WeakString) Int

func (ws WeakString) Int() int

Int returns ws as an integer. If ws is not an integer, 0 is returned.

func (WeakString) MarshalJSON

func (ws WeakString) MarshalJSON() ([]byte, error)

MarshalJSON marshals was a boolean if true or false, a number if an integer, or a string otherwise.

func (WeakString) String

func (ws WeakString) String() string

String returns ws as a string.

func (*WeakString) UnmarshalJSON

func (ws *WeakString) UnmarshalJSON(b []byte) error

UnmarshalJSON satisfies json.Unmarshaler according to this type's documentation.

Directories

Path Synopsis
Package encode implements an encoder middleware for Kengine.
Package encode implements an encoder middleware for Kengine.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL