middleware

package
v0.0.0-...-9446fd8 Latest Latest
Warning

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

Go to latest
Published: Feb 18, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var DefaultSecureConfig = SecureConfig{
	XSSProtection:      "1; mode=block",
	ContentTypeNosniff: "nosniff",
	XFrameOptions:      "SAMEORIGIN",
}
View Source
var ErrCSRFInvalid = keratin.NewHTTPError(http.StatusForbidden, "invalid csrf token")

ErrCSRFInvalid is returned when CSRF check fails

Functions

func BodyLimit

func BodyLimit(cfg BodyLimitConfig, skippers ...Skipper) func(keratin.Handler) keratin.Handler

func BodyRereadable

func BodyRereadable(skippers ...Skipper) func(keratin.Handler) keratin.Handler

func CORS

func CORS(cfg CORSConfig, skippers ...Skipper) func(http.Handler) http.Handler

func CSRF

func CSRF(cfg CSRFConfig, skippers ...Skipper) func(keratin.Handler) keratin.Handler

func CheckMethod

func CheckMethod(method, pattern string) (string, bool)

func CtxCSRF

func CtxCSRF(ctx context.Context) string

func CtxRequestID

func CtxRequestID(ctx context.Context) string

func HTTPRecover

func HTTPRecover(cfg RecoverConfig, logger *slog.Logger) func(next http.Handler) http.Handler

func Recover

func Recover(cfg RecoverConfig) func(keratin.Handler) keratin.Handler

func RequestID

func RequestID(cfg RequestIDConfig, skippers ...Skipper) func(keratin.Handler) keratin.Handler

RequestID returns a middleware that reads RequestIDConfig.TargetHeader (`X-Request-ID`) header value or when the header value is empty, generates that value and sets request ID to response as RequestIDConfig.TargetHeader (`X-Request-Id`) value.

func RequestLogger

func RequestLogger(cfg RequestLoggerConfig, skippers ...Skipper) func(keratin.Handler) keratin.Handler

func Secure

func Secure(cfg SecureConfig, skippers ...Skipper) func(keratin.Handler) keratin.Handler

Types

type BodyLimitConfig

type BodyLimitConfig struct {
	// Maximum allowed size for a request body, default is 32MB.
	// If Limit is less to 0, no limit is applied.
	Limit int64 `env:"LIMIT" json:"limit,omitempty" yaml:"limit,omitempty"`
}

func (*BodyLimitConfig) SetDefaults

func (c *BodyLimitConfig) SetDefaults()

type CORSConfig

type CORSConfig struct {
	// AllowOrigins determines the value of the Access-Control-Allow-Origin
	// response header.  This header defines a list of origins that may access the
	// resource.
	//
	// Origin consist of following parts: `scheme + "://" + host + optional ":" + port`
	// Wildcard can be used, but has to be set explicitly []string{"*"}
	// Example: `https://example.com`, `http://example.com:8080`, `*`
	//
	// Security: use extreme caution when handling the origin, and carefully
	// validate any logic. Remember that attackers may register hostile domain names.
	// See https://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html
	// See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
	//
	// Mandatory.
	AllowOrigins []string `env:"ALLOW_ORIGINS" json:"allowOrigins,omitempty" yaml:"allowOrigins,omitempty"`

	// UnsafeAllowOriginFunc is an optional custom function to validate the origin. It takes the
	// origin as an argument and returns
	// - string, allowed origin
	// - bool, true if allowed or false otherwise.
	// - error, if an error is returned, it is returned immediately by the handler.
	// If this option is set, AllowOrigins is ignored.
	//
	// Security: use extreme caution when handling the origin, and carefully
	// validate any logic. Remember that attackers may register hostile (sub)domain names.
	// See https://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html
	//
	// Sub-domain checks example:
	// 		UnsafeAllowOriginFunc: func(r *http.Request, origin string) (string, bool, error) {
	//			if strings.HasSuffix(origin, ".example.com") {
	//				return origin, true, nil
	//			}
	//			return "", false, nil
	//		},
	//
	// Optional.
	UnsafeAllowOriginFunc func(r *http.Request, origin string) (allowedOrigin string, allowed bool, err error) `json:"-" yaml:"-"`

	// AllowMethods determines the value of the Access-Control-Allow-Methods
	// response header. This header specified the list of methods allowed when
	// accessing the resource. This is used in response to a preflight request.
	//
	// If `allowMethods` is left empty, this middleware will fill for preflight
	// request `Access-Control-Allow-Methods` header value
	// from `Allow` header that keratin.Router set into request context.
	//
	// See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods
	AllowMethods []string `env:"ALLOW_METHODS" json:"allowMethods,omitempty" yaml:"allowMethods,omitempty"`

	// AllowHeaders determines the value of the Access-Control-Allow-Headers
	// response header.  This header is used in response to a preflight request to
	// indicate which HTTP headers can be used when making the actual request.
	//
	// Optional. Defaults to empty list. No domains allowed for CORS.
	//
	// See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
	AllowHeaders []string `env:"ALLOW_HEADERS" json:"allowHeaders,omitempty" yaml:"allowHeaders,omitempty"`

	// AllowCredentials determines the value of the
	// Access-Control-Allow-Credentials response header.  This header indicates
	// whether or not the response to the request can be exposed when the
	// credentials mode (Request.credentials) is true. When used as part of a
	// response to a preflight request, this indicates whether or not the actual
	// request can be made using credentials.  See also
	// [MDN: Access-Control-Allow-Credentials].
	//
	// Optional. Default value false, in which case the header is not set.
	//
	// Security: avoid using `AllowCredentials = true` with `AllowOrigins = *`.
	// See "Exploiting CORS misconfigurations for Bitcoins and bounties",
	// https://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html
	//
	// See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials
	AllowCredentials bool `env:"ALLOW_CREDENTIALS" json:"allowCredentials,omitempty" yaml:"allowCredentials,omitempty"`

	// ExposeHeaders determines the value of Access-Control-Expose-Headers, which
	// defines a list of headers that clients are allowed to access.
	//
	// Optional. Default value []string{}, in which case the header is not set.
	//
	// See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Header
	ExposeHeaders []string `env:"EXPOSE_HEADERS" json:"exposeHeaders,omitempty" yaml:"exposeHeaders,omitempty"`

	// MaxAge determines the value of the Access-Control-Max-Age response header.
	// This header indicates how long (in seconds) the results of a preflight
	// request can be cached.
	// The header is set only if MaxAge != 0, negative value sends "0" which instructs browsers not to cache that response.
	//
	// Optional. Default value 0 - meaning header is not sent.
	//
	// See also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
	MaxAge int `env:"MAX_AGE" json:"maxAge,omitempty" yaml:"maxAge,omitempty"`
}

type CSRFConfig

type CSRFConfig struct {
	// TrustedOrigin permits any request with `Sec-Fetch-Site` header whose `Origin` header
	// exactly matches the specified value.
	// Values should be formated as Origin header "scheme://host[:port]".
	//
	// See [Origin]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin
	// See [Sec-Fetch-Site]: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#fetch-metadata-headers
	TrustedOrigins []string `env:"TRUSTED_ORIGINS" json:"trustedOrigins,omitempty" yaml:"trustedOrigins,omitempty"`

	// AllowSecFetchSameSite allows custom behaviour for `Sec-Fetch-Site` requests that are about to
	// fail with CRSF error, to be allowed or replaced with custom error.
	// This function applies to `Sec-Fetch-Site` values:
	// - `same-site` 		same registrable domain (subdomain and/or different port)
	// - `cross-site`		request originates from different site
	// See [Sec-Fetch-Site]: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#fetch-metadata-headers
	AllowSecFetchSiteFunc func(r *http.Request) (bool, error) `json:"-" yaml:"-"`

	// TokenLength is the length of the generated token.
	TokenLength uint8 `env:"TOKEN_LENGTH" json:"tokenLength,omitempty" yaml:"tokenLength,omitempty"`

	// TokenLookup is a string in the form of "<source>:<name>" or "<source>:<name>,<source>:<name>" that is used
	// to extract token from the request.
	// Optional. Default value "header:X-CSRF-Token".
	// Possible values:
	// - "header:<name>" or "header:<name>:<cut-prefix>"
	// - "query:<name>"
	// - "form:<name>"
	// Multiple sources example:
	// - "header:X-CSRF-Token,query:csrf"
	TokenLookup string `env:"TOKEN_LOOKUP" json:"tokenLookup,omitempty" yaml:"tokenLookup,omitempty"`

	// Generator defines a function to generate token.
	// Optional. Defaults tp randomString(TokenLength).
	Generator func() string `json:"-" yaml:"-"`

	// Name of the CSRF cookie. This cookie will store CSRF token.
	// Optional. Default value "csrf".
	CookieName string `env:"COOKIE_NAME" json:"cookieName,omitempty" yaml:"cookieName,omitempty"`

	// Domain of the CSRF cookie.
	// Optional. Default value none.
	CookieDomain string `env:"COOKIE_DOMAIN" json:"cookieDomain,omitempty" yaml:"cookieDomain,omitempty"`

	// Path of the CSRF cookie.
	// Optional. Default value none.
	CookiePath string `env:"COOKIE_PATH" json:"cookiePath,omitempty" yaml:"cookiePath,omitempty"`

	// Max age (in seconds) of the CSRF cookie.
	// Optional. Default value 86400 (24hr).
	CookieMaxAge int `env:"COOKIE_MAX_AGE" json:"cookieMaxAge,omitempty" yaml:"cookieMaxAge,omitempty"`

	// Indicates if CSRF cookie is secure.
	// Optional. Default value false.
	CookieSecure bool `env:"COOKIE_SECURE" json:"cookieSecure,omitempty" yaml:"cookieSecure,omitempty"`

	// Indicates if CSRF cookie is HTTP only.
	// Optional. Default value false.
	CookieHTTPOnly bool `env:"COOKIE_HTTP_ONLY" json:"cookieHTTPOnly,omitempty" yaml:"cookieHTTPOnly,omitempty"`

	// Indicates SameSite mode of the CSRF cookie.
	// Optional. Default value SameSiteDefaultMode.
	CookieSameSite http.SameSite `env:"COOKIE_SAME_SITE" json:"cookieSameSite,omitempty" yaml:"cookieSameSite,omitempty"`

	// ErrorHandler defines a function which is executed for returning custom errors.
	ErrorHandler func(r *http.Request, err error) error `json:"-" yaml:"-"`
}

func (*CSRFConfig) SetDefaults

func (c *CSRFConfig) SetDefaults()

type ErrorStatusFunc

type ErrorStatusFunc func(context.Context, error) int

ErrorStatusFunc return an error code.

type ExtractorSource

type ExtractorSource string

ExtractorSource is type to indicate source for extracted value

const (
	// ExtractorSourceHeader means value was extracted from request header
	ExtractorSourceHeader ExtractorSource = "header"
	// ExtractorSourceQuery means value was extracted from request query parameters
	ExtractorSourceQuery ExtractorSource = "query"
	// ExtractorSourcePathParam means value was extracted from route path parameters
	ExtractorSourcePathParam ExtractorSource = "param"
	// ExtractorSourceCookie means value was extracted from request cookies
	ExtractorSourceCookie ExtractorSource = "cookie"
	// ExtractorSourceForm means value was extracted from request form values
	ExtractorSourceForm ExtractorSource = "form"
)

type RecoverConfig

type RecoverConfig struct {
	// Size of the stack to be printed.
	// Optional. Default value 2KB.
	StackSize int `env:"STACK_SIZE" json:"stackSize,omitempty" yaml:"stackSize,omitempty"`
}

func (*RecoverConfig) SetDefaults

func (c *RecoverConfig) SetDefaults()

type RequestIDConfig

type RequestIDConfig struct {
	// Generator defines a function to generate an ID.
	// Optional. Default value random.String(32).
	Generator func() string

	// TargetHeader defines what header to look for to populate the id.
	// Optional. Default value is `X-Request-Id`
	TargetHeader string
}

RequestIDConfig defines the config for RequestID middleware.

func (*RequestIDConfig) SetDefaults

func (c *RequestIDConfig) SetDefaults()

type RequestLoggerAttrsFunc

type RequestLoggerAttrsFunc func(w http.ResponseWriter, r *http.Request, metadata RequestMetadata) []slog.Attr

RequestLoggerAttrsFunc defines a function type for generating logging attributes based on HTTP request and response.

func RequestLoggerAttrs

func RequestLoggerAttrs() RequestLoggerAttrsFunc

type RequestLoggerConfig

type RequestLoggerConfig struct {
	// RequestLoggerAttrsFunc defines a function type for generating logging attributes based on HTTP request and response.
	RequestLoggerAttrsFunc `json:"-" yaml:"-"`

	// ErrorStatusFunc return an error code.
	ErrorStatusFunc `json:"-" yaml:"-"`

	// Logger is the logger used to log the request.
	Logger *slog.Logger `json:"-" yaml:"-"`
}

func (*RequestLoggerConfig) SetDefaults

func (c *RequestLoggerConfig) SetDefaults()

type RequestMetadata

type RequestMetadata struct {
	StatusCode int
	Error      error
	StartTime  time.Time
	EndTime    time.Time
}

type SecureConfig

type SecureConfig struct {
	// XSSProtection provides protection against cross-site scripting attack (XSS)
	// by setting the `X-XSS-Protection` header.
	// Optional. Default value "".
	XSSProtection string `env:"XSS_PROTECTION" json:"xssProtection,omitempty" yaml:"xssProtection,omitempty"`

	// ContentTypeNosniff provides protection against overriding Content-Type
	// header by setting the `X-Content-Type-Options` header.
	// Optional. Default value "".
	ContentTypeNosniff string `env:"CONTENT_TYPE_NOSNIFF" json:"contentTypeNosniff,omitempty" yaml:"contentTypeNosniff,omitempty"`

	// XFrameOptions can be used to indicate whether or not a browser should
	// be allowed to render a page in a <frame>, <iframe> or <object> .
	// Sites can use this to avoid clickjacking attacks, by ensuring that their
	// content is not embedded into other sites.provides protection against
	// clickjacking.
	// Optional. Default value "".
	// Possible values:
	// - "SAMEORIGIN" - The page can only be displayed in a frame on the same origin as the page itself.
	// - "DENY" - The page cannot be displayed in a frame, regardless of the site attempting to do so.
	// - "ALLOW-FROM uri" - The page can only be displayed in a frame on the specified origin.
	XFrameOptions string `env:"X_FRAME_OPTIONS" json:"xFrameOptions,omitempty" yaml:"xFrameOptions,omitempty"`

	// HSTSMaxAge sets the `Strict-Transport-Security` header to indicate how
	// long (in seconds) browsers should remember that this site is only to
	// be accessed using HTTPS. This reduces your exposure to some SSL-stripping
	// man-in-the-middle (MITM) attacks.
	// Optional. Default value 0.
	HSTSMaxAge int `env:"HSTS_MAX_AGE" json:"hstsMaxAge,omitempty" yaml:"hstsMaxAge,omitempty"`

	// HSTSExcludeSubdomains won't include subdomains tag in the `Strict Transport Security`
	// header, excluding all subdomains from security policy. It has no effect
	// unless HSTSMaxAge is set to a non-zero value.
	// Optional. Default value false.
	HSTSExcludeSubdomains bool `env:"HSTS_EXCLUDE_SUBDOMAINS" json:"hstsExcludeSubdomains,omitempty" yaml:"hstsExcludeSubdomains,omitempty"`

	// ContentSecurityPolicy sets the `Content-Security-Policy` header providing
	// security against cross-site scripting (XSS), clickjacking and other code
	// injection attacks resulting from execution of malicious content in the
	// trusted web page context.
	// Optional. Default value "".
	ContentSecurityPolicy string `env:"CONTENT_SECURITY_POLICY" json:"contentSecurityPolicy,omitempty" yaml:"contentSecurityPolicy,omitempty"`

	// CSPReportOnly would use the `Content-Security-Policy-Report-Only` header instead
	// of the `Content-Security-Policy` header. This allows iterative updates of the
	// content security policy by only reporting the violations that would
	// have occurred instead of blocking the resource.
	// Optional. Default value false.
	CSPReportOnly bool `env:"CSP_REPORT_ONLY" json:"cspReportOnly,omitempty" yaml:"cspReportOnly,omitempty"`

	// HSTSPreloadEnabled will add the preload tag in the `Strict Transport Security`
	// header, which enables the domain to be included in the HSTS preload list
	// maintained by Chrome (and used by Firefox and Safari): https://hstspreload.org/
	// Optional.  Default value false.
	HSTSPreloadEnabled bool `env:"HSTS_PRELOAD_ENABLED" json:"hstsPreloadEnabled,omitempty" yaml:"hstsPreloadEnabled,omitempty"`

	// ReferrerPolicy sets the `Referrer-Policy` header providing security against
	// leaking potentially sensitive request paths to third parties.
	// Optional. Default value "".
	ReferrerPolicy string `env:"REFERRER_POLICY" json:"referrerPolicy,omitempty" yaml:"referrerPolicy,omitempty"`
}

type Skipper

type Skipper func(*http.Request) bool

func ChainSkipper

func ChainSkipper(skippers ...Skipper) Skipper

func EqualPathSkipper

func EqualPathSkipper(paths ...string) Skipper

func ExpressionSkipper

func ExpressionSkipper[Env any](fn func(*http.Request) Env, expressions ...string) Skipper

ExpressionSkipper creates a Skipper function that evaluates expressions against an environment generated from requests.

Documentation can be found here: https://expr-lang.org/

func PrefixPathSkipper

func PrefixPathSkipper(prefixes ...string) Skipper

func SuffixPathSkipper

func SuffixPathSkipper(suffixes ...string) Skipper

type ValueExtractorError

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

ValueExtractorError is error type when middleware extractor is unable to extract value from lookups

func (*ValueExtractorError) Error

func (e *ValueExtractorError) Error() string

Error returns errors text

type ValuesExtractor

type ValuesExtractor func(r *http.Request) ([]string, ExtractorSource, error)

ValuesExtractor defines a function for extracting values (keys/tokens) from the given context.

func CreateExtractors

func CreateExtractors(lookups string, limit uint) ([]ValuesExtractor, error)

CreateExtractors creates ValuesExtractors from given lookups. lookups is a string in the form of "<source>:<name>" or "<source>:<name>,<source>:<name>" that is used to extract key from the request. Possible values:

  • "header:<name>" or "header:<name>:<cut-prefix>" `<cut-prefix>` is argument value to cut/trim prefix of the extracted value. This is useful if header value has static prefix like `Authorization: <auth-scheme> <authorisation-parameters>` where part that we want to cut is `<auth-scheme> ` note the space at the end. In case of basic authentication `Authorization: Basic <credentials>` prefix we want to remove is `Basic `.
  • "query:<name>"
  • "param:<name>"
  • "form:<name>"
  • "cookie:<name>"

Multiple sources example: - "header:Authorization,header:X-Api-Key"

limit sets the maximum amount how many lookups can be returned.

Jump to

Keyboard shortcuts

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