zeno

package module
v0.0.0-...-ffedc89 Latest Latest
Warning

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

Go to latest
Published: Jun 29, 2025 License: MIT Imports: 21 Imported by: 0

README

Zeno Web framework

Zeno is an ultra-fast, lightweight web framework for Go, built on top of fasthttp. It focuses on maximum performance, developer productivity, and modern features — perfect for building blazing-fast APIs and backend services.

Documentation

Overview

Package zeno provides a high-performance HTTP router and framework.

Package zeno provides a high-performance HTTP router based on a radix tree structure with support for inline parameters, optional and wildcard tokens, and pattern-matching using regular expressions.

Index

Constants

View Source
const (
	// HeaderAccept specifies media types acceptable for the response.
	HeaderAccept = "Accept"

	// HeaderAcceptCharset specifies acceptable character sets.
	HeaderAcceptCharset = "Accept-Charset"

	// HeaderAcceptEncoding specifies acceptable content encodings (e.g., gzip, deflate).
	HeaderAcceptEncoding = "Accept-Encoding"

	// HeaderAcceptLanguage specifies preferred natural languages for the response.
	HeaderAcceptLanguage = "Accept-Language"

	// HeaderAcceptRanges indicates that the server supports range requests.
	HeaderAcceptRanges = "Accept-Ranges"

	// HeaderAccessControlAllowOrigin specifies the origins that are allowed to access the resource.
	HeaderAccessControlAllowOrigin = "Access-Control-Allow-Origin"

	// HeaderAccessControlAllowMethods specifies the HTTP methods allowed when accessing the resource.
	HeaderAccessControlAllowMethods = "Access-Control-Allow-Methods"

	// HeaderAccessControlAllowHeaders specifies which headers can be used during the actual request.
	HeaderAccessControlAllowHeaders = "Access-Control-Allow-Headers"

	// HeaderAccessControlExposeHeaders indicates which headers can be exposed to the client.
	HeaderAccessControlExposeHeaders = "Access-Control-Expose-Headers"

	// HeaderAccessControlMaxAge indicates how long the results of a preflight request can be cached.
	HeaderAccessControlMaxAge = "Access-Control-Max-Age"

	// HeaderAccessControlRequestMethod is used in preflight requests to specify the method being used.
	HeaderAccessControlRequestMethod = "Access-Control-Request-Method"

	// HeaderAccessControlRequestHeaders is used in preflight requests to indicate which HTTP headers will be used.
	HeaderAccessControlRequestHeaders = "Access-Control-Request-Headers"

	// HeaderAge indicates the age of the object in a cache.
	HeaderAge = "Age"

	// HeaderAllow lists the allowed methods for a resource.
	HeaderAllow = "Allow"

	// HeaderAuthorization contains credentials for authenticating the user agent.
	HeaderAuthorization = "Authorization"

	// HeaderCacheControl specifies directives for caching mechanisms.
	HeaderCacheControl = "Cache-Control"

	// HeaderConnection controls whether the network connection stays open after the transaction finishes.
	HeaderConnection = "Connection"

	// HeaderContentDisposition indicates if the content should be displayed inline or as an attachment.
	HeaderContentDisposition = "Content-Disposition"

	// HeaderContentEncoding specifies the encoding used on the data.
	HeaderContentEncoding = "Content-Encoding"

	// HeaderContentLanguage describes the natural language(s) of the intended audience.
	HeaderContentLanguage = "Content-Language"

	// HeaderContentLength indicates the size of the message body.
	HeaderContentLength = "Content-Length"

	// HeaderContentLocation indicates an alternate location for the returned data.
	HeaderContentLocation = "Content-Location"

	// HeaderContentRange specifies where in a full body message a partial message belongs.
	HeaderContentRange = "Content-Range"

	// HeaderContentType indicates the media type of the resource.
	HeaderContentType = "Content-Type"

	// HeaderCookie contains stored HTTP cookies previously sent by the server.
	HeaderCookie = "Cookie"

	// HeaderDate represents the date and time at which the message was originated.
	HeaderDate = "Date"

	// HeaderETag is a unique identifier for a specific version of a resource.
	HeaderETag = "ETag"

	// HeaderExpect indicates expectations that need to be fulfilled before sending the request body.
	HeaderExpect = "Expect"

	// HeaderExpires gives the date/time after which the response is considered stale.
	HeaderExpires = "Expires"

	// HeaderForwarded is used to identify the originating IP address of a client.
	HeaderForwarded = "Forwarded"

	// HeaderFrom indicates the email address of the user making the request.
	HeaderFrom = "From"

	// HeaderHost specifies the domain name of the server and optionally the port.
	HeaderHost = "Host"

	// HeaderIfMatch makes the request conditional on the resource matching a given ETag.
	HeaderIfMatch = "If-Match"

	// HeaderIfModifiedSince makes the request conditional: it will only be successful if the resource has been modified since the given date.
	HeaderIfModifiedSince = "If-Modified-Since"

	// HeaderIfNoneMatch makes the request conditional: it will only be successful if the resource does not match the given ETag(s).
	HeaderIfNoneMatch = "If-None-Match"

	// HeaderIfRange makes a range request conditional based on ETag or modification date.
	HeaderIfRange = "If-Range"

	// HeaderIfUnmodifiedSince makes the request conditional: it will only be successful if the resource has not been modified since the given date.
	HeaderIfUnmodifiedSince = "If-Unmodified-Since"

	// HeaderLastModified indicates the date and time the resource was last modified.
	HeaderLastModified = "Last-Modified"

	// HeaderLink provides links to related resources.
	HeaderLink = "Link"

	// HeaderLocation indicates the URL to redirect a page to.
	HeaderLocation = "Location"

	// HeaderMaxForwards is used with TRACE and OPTIONS to limit the number of times a message can be forwarded.
	HeaderMaxForwards = "Max-Forwards"

	// HeaderOrigin indicates where the request originated (used in CORS).
	HeaderOrigin = "Origin"

	// HeaderPragma includes implementation-specific directives that may apply to any recipient along the request/response chain.
	HeaderPragma = "Pragma"

	// HeaderProxyAuthenticate defines the authentication method that should be used to access a resource behind a proxy.
	HeaderProxyAuthenticate = "Proxy-Authenticate"

	// HeaderProxyAuthorization contains credentials to authenticate a user agent with a proxy server.
	HeaderProxyAuthorization = "Proxy-Authorization"

	// HeaderRange specifies the range of bytes a client is requesting.
	HeaderRange = "Range"

	// HeaderReferer indicates the address of the previous web page from which a link to the currently requested page was followed.
	HeaderReferer = "Referer"

	// HeaderRetryAfter indicates how long the user agent should wait before making a follow-up request.
	HeaderRetryAfter = "Retry-After"

	// HeaderServer contains information about the software used by the origin server.
	HeaderServer = "Server"

	// HeaderSetCookie sends cookies from the server to the user agent.
	HeaderSetCookie = "Set-Cookie"

	// HeaderTE indicates what transfer encodings the client is willing to accept.
	HeaderTE = "TE"

	// HeaderTrailer indicates which headers will be present in the trailer part of the message.
	HeaderTrailer = "Trailer"

	// HeaderTransferEncoding specifies the form of encoding used to safely transfer the entity to the user.
	HeaderTransferEncoding = "Transfer-Encoding"

	// HeaderUpgrade is used to switch protocols (e.g., from HTTP/1.1 to WebSockets).
	HeaderUpgrade = "Upgrade"

	// HeaderUserAgent contains information about the user agent originating the request.
	HeaderUserAgent = "User-Agent"

	// HeaderVary indicates which headers a cache should use to decide if a cached response is fresh.
	HeaderVary = "Vary"

	// HeaderVia shows intermediate protocols and recipients between the user agent and server.
	HeaderVia = "Via"

	// HeaderWarning carries additional information about the status or transformation of a message.
	HeaderWarning = "Warning"

	// HeaderWWWAuthenticate indicates the authentication method that should be used to access a resource.
	HeaderWWWAuthenticate = "WWW-Authenticate"

	// HeaderAIM is a Microsoft extension for incremental GETs.
	HeaderAIM = "A-IM"

	// HeaderAcceptDatetime is used to request responses based on modification date (used in some APIs).
	HeaderAcceptDatetime = "Accept-Datetime"

	// HeaderAccessControlAllowCredentials indicates whether the response to the request can be exposed when credentials are present.
	HeaderAccessControlAllowCredentials = "Access-Control-Allow-Credentials"

	// HeaderAccessControlRequestCredentials is a non-standard header for requesting with credentials.
	HeaderAccessControlRequestCredentials = "Access-Control-Request-Credentials"

	// HeaderContentSecurityPolicy defines security policies (e.g., scripts, styles, etc.).
	HeaderContentSecurityPolicy = "Content-Security-Policy"

	// HeaderContentMD5 is a base64-encoded 128-bit MD5 digest of the message body.
	HeaderContentMD5 = "Content-MD5"

	// HeaderDNT indicates the user’s tracking preference (Do Not Track).
	HeaderDNT = "DNT"

	// HeaderDigest provides a message digest for the resource.
	HeaderDigest = "Digest"

	// HeaderEarlyData indicates if early data (0-RTT) is accepted.
	HeaderEarlyData = "Early-Data"

	// HeaderExpectCT allows sites to opt in to reporting of Certificate Transparency violations.
	HeaderExpectCT = "Expect-CT"

	// HeaderForwardedFor indicates the original IP address of a client connecting through a proxy.
	HeaderForwardedFor = "X-Forwarded-For"

	// HeaderForwardedHost indicates the original host requested by the client in the Host HTTP request header.
	HeaderForwardedHost = "X-Forwarded-Host"

	// HeaderForwardedProto indicates the originating protocol (HTTP or HTTPS).
	HeaderForwardedProto = "X-Forwarded-Proto"

	// HeaderHTTP2Settings is used in HTTP/2 to carry connection-specific settings.
	HeaderHTTP2Settings = "HTTP2-Settings"

	// HeaderKeepAlive specifies parameters for a persistent connection.
	HeaderKeepAlive = "Keep-Alive"

	// HeaderNEL reports network errors to a reporting endpoint.
	HeaderNEL = "NEL"

	// HeaderOriginTrial is used by Chrome to enable experimental web platform features.
	HeaderOriginTrial = "Origin-Trial"

	// HeaderPermissionsPolicy allows a server to declare permissions for APIs and features.
	HeaderPermissionsPolicy = "Permissions-Policy"

	// HeaderProxyConnection is a non-standard header used by some proxies.
	HeaderProxyConnection = "Proxy-Connection"

	// HeaderPublicKeyPins was used for Public Key Pinning (now deprecated).
	HeaderPublicKeyPins = "Public-Key-Pins"

	// HeaderReferrerPolicy specifies the referrer information sent with requests.
	HeaderReferrerPolicy = "Referrer-Policy"

	// HeaderReportTo specifies where reports should be sent in Reporting API.
	HeaderReportTo = "Report-To"

	// HeaderRequestID is used for request tracing (custom header).
	HeaderRequestID = "X-Request-ID"

	// HeaderSaveData indicates user preference for reduced data usage.
	HeaderSaveData = "Save-Data"

	// HeaderSourceMap indicates where source maps are located for debugging.
	HeaderSourceMap = "SourceMap"

	// HeaderStrictTransportSecurity enforces HTTPS communication with the server.
	HeaderStrictTransportSecurity = "Strict-Transport-Security"

	// HeaderTimingAllowOrigin specifies origins that are allowed to see timing information.
	HeaderTimingAllowOrigin = "Timing-Allow-Origin"

	// HeaderUpgradeInsecureRequests indicates that the client prefers secure content.
	HeaderUpgradeInsecureRequests = "Upgrade-Insecure-Requests"

	// HeaderXContentTypeOptions prevents MIME-sniffing (e.g., nosniff).
	HeaderXContentTypeOptions = "X-Content-Type-Options"

	// HeaderXDNSPrefetchControl controls DNS prefetching.
	HeaderXDNSPrefetchControl = "X-DNS-Prefetch-Control"

	// HeaderXDownloadOptions prevents automatic file opening in older browsers.
	HeaderXDownloadOptions = "X-Download-Options"

	// HeaderXFrameOptions prevents clickjacking by controlling frame usage.
	HeaderXFrameOptions = "X-Frame-Options"

	// HeaderXPermittedCrossDomainPolicies controls Adobe Flash and Acrobat access.
	HeaderXPermittedCrossDomainPolicies = "X-Permitted-Cross-Domain-Policies"

	// HeaderXPoweredBy is used to indicate the technology used (e.g., Express, PHP).
	HeaderXPoweredBy = "X-Powered-By"

	// HeaderXRequestID is a duplicate of X-Request-ID, used in some tracing setups.
	HeaderXRequestID = "X-Request-ID"

	// HeaderXUACompatible specifies compatibility mode for IE/Edge.
	HeaderXUACompatible = "X-UA-Compatible"

	// HeaderXXSSProtection enables cross-site scripting (XSS) filters.
	HeaderXXSSProtection = "X-XSS-Protection"

	// HeaderXRequestedWith is a non-standard header used to identify AJAX (XHR) requests.
	// Commonly set to "XMLHttpRequest" by client-side libraries like jQuery.
	HeaderXRequestedWith = "X-Requested-With"
)
View Source
const (
	MethodGet     = "GET"     // RFC 7231, 4.3.1
	MethodHead    = "HEAD"    // RFC 7231, 4.3.2
	MethodPost    = "POST"    // RFC 7231, 4.3.3
	MethodPut     = "PUT"     // RFC 7231, 4.3.4
	MethodPatch   = "PATCH"   // RFC 5789
	MethodDelete  = "DELETE"  // RFC 7231, 4.3.5
	MethodConnect = "CONNECT" // RFC 7231, 4.3.6
	MethodOptions = "OPTIONS" // RFC 7231, 4.3.7
	MethodTrace   = "TRACE"   // RFC 7231, 4.3.8
)

HTTP methods were copied from net/http.

View Source
const (
	StatusContinue           = 100 // RFC 7231, 6.2.1
	StatusSwitchingProtocols = 101 // RFC 7231, 6.2.2
	StatusProcessing         = 102 // RFC 2518, 10.1
	StatusEarlyHints         = 103 // RFC 8297

	StatusOK                   = 200 // RFC 7231, 6.3.1
	StatusCreated              = 201 // RFC 7231, 6.3.2
	StatusAccepted             = 202 // RFC 7231, 6.3.3
	StatusNonAuthoritativeInfo = 203 // RFC 7231, 6.3.4
	StatusNoContent            = 204 // RFC 7231, 6.3.5
	StatusResetContent         = 205 // RFC 7231, 6.3.6
	StatusPartialContent       = 206 // RFC 7233, 4.1
	StatusMultiStatus          = 207 // RFC 4918, 11.1
	StatusAlreadyReported      = 208 // RFC 5842, 7.1
	StatusIMUsed               = 226 // RFC 3229, 10.4.1

	StatusMultipleChoices  = 300 // RFC 7231, 6.4.1
	StatusMovedPermanently = 301 // RFC 7231, 6.4.2
	StatusFound            = 302 // RFC 7231, 6.4.3
	StatusSeeOther         = 303 // RFC 7231, 6.4.4
	StatusNotModified      = 304 // RFC 7232, 4.1
	StatusUseProxy         = 305 // RFC 7231, 6.4.5

	StatusTemporaryRedirect = 307 // RFC 7231, 6.4.7
	StatusPermanentRedirect = 308 // RFC 7538, 3

	StatusBadRequest                   = 400 // RFC 7231, 6.5.1
	StatusUnauthorized                 = 401 // RFC 7235, 3.1
	StatusPaymentRequired              = 402 // RFC 7231, 6.5.2
	StatusForbidden                    = 403 // RFC 7231, 6.5.3
	StatusNotFound                     = 404 // RFC 7231, 6.5.4
	StatusMethodNotAllowed             = 405 // RFC 7231, 6.5.5
	StatusNotAcceptable                = 406 // RFC 7231, 6.5.6
	StatusProxyAuthRequired            = 407 // RFC 7235, 3.2
	StatusRequestTimeout               = 408 // RFC 7231, 6.5.7
	StatusConflict                     = 409 // RFC 7231, 6.5.8
	StatusGone                         = 410 // RFC 7231, 6.5.9
	StatusLengthRequired               = 411 // RFC 7231, 6.5.10
	StatusPreconditionFailed           = 412 // RFC 7232, 4.2
	StatusRequestEntityTooLarge        = 413 // RFC 7231, 6.5.11
	StatusRequestURITooLong            = 414 // RFC 7231, 6.5.12
	StatusUnsupportedMediaType         = 415 // RFC 7231, 6.5.13
	StatusRequestedRangeNotSatisfiable = 416 // RFC 7233, 4.4
	StatusExpectationFailed            = 417 // RFC 7231, 6.5.14
	StatusTeapot                       = 418 // RFC 7168, 2.3.3
	StatusMisdirectedRequest           = 421 // RFC 7540, 9.1.2
	StatusUnprocessableEntity          = 422 // RFC 4918, 11.2
	StatusLocked                       = 423 // RFC 4918, 11.3
	StatusFailedDependency             = 424 // RFC 4918, 11.4
	StatusUpgradeRequired              = 426 // RFC 7231, 6.5.15
	StatusPreconditionRequired         = 428 // RFC 6585, 3
	StatusTooManyRequests              = 429 // RFC 6585, 4
	StatusRequestHeaderFieldsTooLarge  = 431 // RFC 6585, 5
	StatusUnavailableForLegalReasons   = 451 // RFC 7725, 3

	StatusInternalServerError           = 500 // RFC 7231, 6.6.1
	StatusNotImplemented                = 501 // RFC 7231, 6.6.2
	StatusBadGateway                    = 502 // RFC 7231, 6.6.3
	StatusServiceUnavailable            = 503 // RFC 7231, 6.6.4
	StatusGatewayTimeout                = 504 // RFC 7231, 6.6.5
	StatusHTTPVersionNotSupported       = 505 // RFC 7231, 6.6.6
	StatusVariantAlsoNegotiates         = 506 // RFC 2295, 8.1
	StatusInsufficientStorage           = 507 // RFC 4918, 11.5
	StatusLoopDetected                  = 508 // RFC 5842, 7.2
	StatusNotExtended                   = 510 // RFC 2774, 7
	StatusNetworkAuthenticationRequired = 511 // RFC 6585, 6
)

HTTP status codes were stolen from net/http.

Variables

View Source
var (
	// 4xx
	ErrBadRequest                  = NewHTTPError(StatusBadRequest)
	ErrUnauthorized                = NewHTTPError(StatusUnauthorized)
	ErrPaymentRequired             = NewHTTPError(StatusPaymentRequired)
	ErrForbidden                   = NewHTTPError(StatusForbidden)
	ErrNotFound                    = NewHTTPError(StatusNotFound)
	ErrMethodNotAllowed            = NewHTTPError(StatusMethodNotAllowed)
	ErrNotAcceptable               = NewHTTPError(StatusNotAcceptable)
	ErrProxyAuthRequired           = NewHTTPError(StatusProxyAuthRequired)
	ErrRequestTimeout              = NewHTTPError(StatusRequestTimeout)
	ErrConflict                    = NewHTTPError(StatusConflict)
	ErrGone                        = NewHTTPError(StatusGone)
	ErrLengthRequired              = NewHTTPError(StatusLengthRequired)
	ErrPreconditionFailed          = NewHTTPError(StatusPreconditionFailed)
	ErrRequestEntityTooLarge       = NewHTTPError(StatusRequestEntityTooLarge)
	ErrRequestURITooLong           = NewHTTPError(StatusRequestURITooLong)
	ErrUnsupportedMediaType        = NewHTTPError(StatusUnsupportedMediaType)
	ErrRangeNotSatisfiable         = NewHTTPError(StatusRequestedRangeNotSatisfiable)
	ErrExpectationFailed           = NewHTTPError(StatusExpectationFailed)
	ErrTeapot                      = NewHTTPError(StatusTeapot)
	ErrTooManyRequests             = NewHTTPError(StatusTooManyRequests)
	ErrRequestHeaderFieldsTooLarge = NewHTTPError(StatusRequestHeaderFieldsTooLarge)
	ErrUnavailableForLegalReasons  = NewHTTPError(StatusUnavailableForLegalReasons)

	// 5xx
	ErrInternalServer                = NewHTTPError(StatusInternalServerError)
	ErrNotImplemented                = NewHTTPError(StatusNotImplemented)
	ErrBadGateway                    = NewHTTPError(StatusBadGateway)
	ErrServiceUnavailable            = NewHTTPError(StatusServiceUnavailable)
	ErrGatewayTimeout                = NewHTTPError(StatusGatewayTimeout)
	ErrHTTPVersionNotSupported       = NewHTTPError(StatusHTTPVersionNotSupported)
	ErrVariantAlsoNegotiates         = NewHTTPError(StatusVariantAlsoNegotiates)
	ErrInsufficientStorage           = NewHTTPError(StatusInsufficientStorage)
	ErrLoopDetected                  = NewHTTPError(StatusLoopDetected)
	ErrNotExtended                   = NewHTTPError(StatusNotExtended)
	ErrNetworkAuthenticationRequired = NewHTTPError(StatusNetworkAuthenticationRequired)
)

Functions

func IsHTTPError

func IsHTTPError(err error) bool

IsHTTPError reports whether err conforms to the HTTPError interface.

func MethodNotAllowedHandler

func MethodNotAllowedHandler(c *Context) error

MethodNotAllowedHandler builds and sets the "Allow" header when a route exists for the path but not for the method. If the request method is not OPTIONS, it returns 405 Method Not Allowed.

func NotFoundHandler

func NotFoundHandler(*Context) error

NotFoundHandler is the default fallback handler that returns 404.

func Param

func Param[T any](c *Context, name string, defaultValue ...T) T

Param returns the value of the route parameter *name* converted to type *T*.

It works like this:

  • If *name* exists in the current request’s path parameters, its raw string is passed to toType[T] for conversion.
  • If the parameter is missing or empty, and a *defaultValue* is provided, the first default value is returned instead.
  • If conversion fails, Param returns the zero value of T. (toType never panics and never returns an error.)

Example:

// Route: /users/{id}/{slug?}
id   := zeno.Param[int](ctx, "id")              // → 42
slug := zeno.Param[string](ctx, "slug", "anon") // → "anon" if slug is missing
page := zeno.Param[int](ctx, "page", 1)         // → 1 if page is missing

Param is a free function (not a Context method) because Go forbids generic methods on non-generic types. Keep it in the same package as *Context* so users can call it concisely:

import "zeno"

id := zeno.Param[int](ctx, "id")

func Query

func Query[T any](c *Context, name string, defaultValue ...T) T

Query returns the value of the query parameter *name* converted to type *T*.

It works like this:

  • If *name* exists in the current request’s query string, its raw string is passed to toType[T] for conversion.
  • If the parameter is missing or empty, and a *defaultValue* is provided, the first default value is returned instead.
  • If conversion fails, Query returns the zero value of T. (toType never panics and never returns an error.)

Example:

// Request: /search?q=books&page=2
q    := zeno.Query[string](ctx, "q")           // → "books"
page := zeno.Query[int](ctx, "page", 1)        // → 2
limit := zeno.Query[int](ctx, "limit", 10)     // → 10 if not set

Query is a free function (not a Context method) because Go forbids generic methods on non-generic types. Keep it in the same package as *Context* so users can call it concisely:

import "zeno"

page := zeno.Query[int](ctx, "page", 1)

func StatusMessage

func StatusMessage(statusCode int) string

StatusMessage returns HTTP status message for the given status code.

Types

type Context

type Context struct {
	// RequestCtx is the underlying fasthttp request context.
	RequestCtx *fasthttp.RequestCtx
	// contains filtered or unexported fields
}

Context represents the context of the current HTTP request. It holds request and response data, route parameters, and provides convenience methods for handling various aspects of the request lifecycle.

func (*Context) Abort

func (c *Context) Abort()

Abort stops the execution of any remaining middleware/handlers.

func (*Context) Accepts

func (c *Context) Accepts(offers ...string) string

Accepts returns the best match from the offers based on the Accept header.

func (*Context) AcceptsCharset

func (c *Context) AcceptsCharset(offers ...string) string

AcceptsCharset returns the best match from the offers based on Accept-Charset.

func (*Context) AcceptsEncoding

func (c *Context) AcceptsEncoding(offers ...string) string

AcceptsEncoding returns the best match from the offers based on Accept-Encoding.

func (*Context) AcceptsLanguage

func (c *Context) AcceptsLanguage(offers ...string) string

AcceptsLanguage returns the best match from the offers based on Accept-Language.

func (*Context) BindCBOR

func (c *Context) BindCBOR(out any) error

BindCBOR reads the request body, decodes it as CBOR, and stores the result in out.

The decoder is the CborDecoder configured on the parent *Zeno* instance. A 400 Bad Request error is returned if the body is empty or the data cannot be decoded.

Example:

var input map[string]any
if err := c.BindCBOR(&input); err != nil {
    return
}

func (*Context) BindJSON

func (c *Context) BindJSON(out any) error

BindJSON decodes the JSON request body into the provided destination structure. Returns an error if the body is empty or invalid.

Example:

var req UserInput
if err := c.BindJSON(&req); err != nil {
    return err
}

func (*Context) BindString

func (c *Context) BindString(out *string) error

BindString binds the raw request body to the given string pointer. It returns a 400 Bad Request error if the body is empty.

Example:

var msg string
err := ctx.BindString(&msg)
if err != nil {
    ctx.SendStatus(400)
    return
}
ctx.SendString("Got: " + msg)

func (*Context) BindTOML

func (c *Context) BindTOML(out any) error

BindTOML reads the request body, decodes it as TOML, and stores the result in out.

The decoder is the TomlDecoder configured on the parent *Zeno* instance. A 400 Bad Request error is returned if the body is empty or the data cannot be decoded.

Example:

type Config struct {
    Host string `toml:"host"`
    Port int    `toml:"port"`
}

var cfg Config
if err := c.BindTOML(&cfg); err != nil {
    c.Logger().Error(err)
    return
}

func (*Context) BindXML

func (c *Context) BindXML(out any) error

BindXML decodes the request body as XML into the provided destination object.

It returns a 400 error if the body is empty or if the XML is malformed.

Example:

var user User
if err := c.BindXML(&user); err != nil {
    return err
}

func (*Context) BindYAML

func (c *Context) BindYAML(out any) error

BindYAML reads the request body, decodes it as YAML, and stores the result in out.

The decoder is the YamlDecoder configured on the parent *Zeno* instance. A 400 Bad Request error is returned if the body is empty or the data cannot be decoded.

Example:

type User struct {
    Name string `yaml:"name"`
    Age  int    `yaml:"age"`
}

var u User
if err := c.BindYAML(&u); err != nil {
    c.Logger().Error(err)
    return
}

func (*Context) Body

func (c *Context) Body() []byte

Body returns the raw request body.

func (*Context) FormFile

func (c *Context) FormFile(key string) (*multipart.FileHeader, error)

FormFile returns the uploaded file header for the given form key.

func (*Context) FormValue

func (c *Context) FormValue(key string, defaultValue ...string) string

FormValue returns the value of a form field or a default if not present.

func (*Context) GetForwardedIPs

func (c *Context) GetForwardedIPs() []string

GetForwardedIPs returns a slice of IPs from the X-Forwarded-For header.

func (*Context) GetHeader

func (c *Context) GetHeader(key string) string

GetHeader returns the value of the specified request header.

func (*Context) HeaderMap

func (c *Context) HeaderMap() map[string]string

HeaderMap returns all request headers as a map.

func (*Context) Host

func (c *Context) Host() string

Host returns the host part of the request, from the Host header.

func (*Context) IP

func (c *Context) IP() string

IP returns the remote IP address of the client.

func (*Context) IsAJAX

func (c *Context) IsAJAX() bool

IsAJAX returns true if the request was made via AJAX.

func (*Context) IsSecure

func (c *Context) IsSecure() bool

IsSecure returns true if the request is over HTTPS.

func (*Context) Method

func (c *Context) Method() string

Method returns the HTTP method of the request.

func (*Context) MultipartForm

func (c *Context) MultipartForm() (*multipart.Form, error)

MultipartForm returns the parsed multipart form data.

func (*Context) Next

func (c *Context) Next() error

Next executes the next handler in the middleware chain. It returns early if any handler returns an error.

func (*Context) Param

func (c *Context) Param(name string, defaultValue ...string) string

Param returns the value of a route parameter by name.

If the parameter is not present and a defaultValue is provided, the first element of defaultValue is returned instead.

Example usage:

id := ctx.Param("id")              // returns "" if not found
id := ctx.Param("id", "default")   // returns "default" if not found

func (*Context) Params

func (c *Context) Params() map[string]string

Params returns a map of all route parameters.

func (*Context) Path

func (c *Context) Path() string

Path returns the request URL path.

func (*Context) Port

func (c *Context) Port() string

Port returns the remote port from the client's address.

func (*Context) PostBody

func (c *Context) PostBody() []byte

PostBody returns the POST request body.

func (*Context) Protocol

func (c *Context) Protocol() string

Protocol returns the request protocol version (e.g., HTTP/1.1).

func (*Context) Query

func (c *Context) Query(key string, defaultValue ...string) string

Query returns the query parameter value for the given key.

If the parameter is not present and a defaultValue is provided, the first element of defaultValue is returned instead.

Example usage:

name := ctx.Query("name")                   // returns "" if not found
name := ctx.Query("name", "default-name")   // returns "default-name" if not found

func (*Context) QueryArray

func (c *Context) QueryArray(key string) []string

QueryArray returns all query values for a given key.

func (*Context) QueryMap

func (c *Context) QueryMap() map[string]string

QueryMap returns all query parameters as a map.

func (*Context) Ranges

func (c *Context) Ranges(maxSize int64) (*Range, error)

Ranges parses the Range header and returns validated byte ranges.

func (*Context) RealIP

func (c *Context) RealIP() string

RealIP returns the client's real IP address, considering X-Forwarded-For.

func (*Context) Redirect

func (c *Context) Redirect(url string, code ...int) error

Redirect sends an HTTP redirect to the client with the specified status code. The default code is 302 (StatusFound) if none is provided.

Example:

return c.Redirect("/login")             // 302 Found
return c.Redirect("/dashboard", 301)    // 301 Moved Permanently

func (*Context) Scheme

func (c *Context) Scheme() string

Scheme returns the request scheme, "http" or "https".

func (*Context) SendBytes

func (c *Context) SendBytes(b []byte) error

SendBytes sets the response body to the given byte slice `b`. It overwrites any previously set body content.

This method is typically used when you already have the response body as a raw byte slice, such as when serving JSON, Yaml, or binary data.

Example:

err := ctx.SendBytes([]byte("Hello, World!"))
if err != nil {
    // handle error
}

func (*Context) SendCBOR

func (c *Context) SendCBOR(v any, ctype ...string) error

SendCBOR encodes v as CBOR and writes it to the response.

It sets the Content-Type to "application/cbor" unless a custom value is provided via ctype. A 500 Internal Server Error is returned if encoding fails.

Example:

output := map[string]any{
    "ok": true,
    "ts": time.Now().Unix(),
}
if err := c.SendCBOR(output); err != nil {
}

To override the default content type:

if err := c.SendCBOR(output, "application/x-cbor"); err != nil {
    ...
}

func (*Context) SendFile

func (c *Context) SendFile(path string) error

SendFile streams the file located at path to the client.

It uses fasthttp’s zero‑copy RequestCtx.SendFile under the hood, allowing the kernel to send the file directly from disk to the socket for maximal performance. The Content‑Type header is inferred from the file extension via fasthttp’s built‑in MIME database.

SendFile always returns nil because any I/O errors are already handled by fasthttp and reflected in the HTTP response it writes. If you need to inspect those errors programmatically, call ctx.RequestCtx.SendFile directly and check the returned error.

Example:

// Deliver a static asset.
_ = ctx.SendFile("./public/index.html")

func (*Context) SendHTML

func (c *Context) SendHTML(value string) error

SendHTML writes an HTML payload to the client.

The helper first sets the Content‑Type header to "text/html; charset=utf-8", then delegates to SendString to transmit the body. Useful for quick inline responses or template output.

Example:

if err := ctx.SendHTML("<h1>Hello, Zeno!</h1>"); err != nil {
    // handle error
}

func (*Context) SendHeader

func (c *Context) SendHeader(key, value string) error

SendHeader sets a response header with the given key and value. It returns nil for compatibility with middleware chains.

Example:

err := ctx.SendHeader("X-Custom-Header", "value")

func (*Context) SendJSON

func (c *Context) SendJSON(value any, ctype ...string) error

SendJSON encodes the given value as JSON and writes it to the response. It sets the Content-Type to "application/json" unless overridden with the optional ctype argument.

Example:

return c.SendJSON(data)
return c.SendJSON(data, "application/vnd.api+json")

func (*Context) SendJSONIndent

func (c *Context) SendJSONIndent(value any, prefix, indent string, ctype ...string) error

SendJSONIndent encodes the given value as indented (pretty-formatted) JSON using the specified prefix and indent strings. It writes the result to the response.

This is useful for debugging or generating human-readable JSON output with custom formatting.

It sets the Content-Type to "application/json" unless overridden by the optional ctype.

Example:

err := c.SendJSONIndent(data, "", "  ") // pretty JSON with 2-space indent

err := c.SendJSONIndent(data, "--", ">>", "application/vnd.api+json")

func (*Context) SendJSONP

func (c *Context) SendJSONP(value any, callback ...string) error

SendJSONP encodes the value as JSON and wraps it in a JavaScript function call for use with JSONP (JSON with Padding). It sets Content-Type to "application/javascript".

The optional callback name defaults to "callback".

Example:

return c.SendJSONP(data)               // callback(data)
return c.SendJSONP(data, "handleData") // handleData(data)

func (*Context) SendPrettyJSON

func (c *Context) SendPrettyJSON(value any, ctype ...string) error

SendPrettyJSON encodes the given value as pretty-formatted JSON (indented) and writes it to the response. Ideal for human-readable responses in development.

It sets the Content-Type to "application/json" unless overridden.

Example:

return c.SendPrettyJSON(data)

func (*Context) SendSecureJSON

func (c *Context) SendSecureJSON(value any, ctype ...string) error

SendSecureJSON encodes the value as JSON and adds a prefix to arrays to prevent JSON hijacking vulnerabilities in legacy browsers. The prefix (default: `while(1);`) is configured via Zeno().SecureJSONPrefix.

Example:

return c.SendSecureJSON(data)

func (*Context) SendStatusCode

func (c *Context) SendStatusCode(code int) error

SendStatusCode sets the HTTP response status code to the given `code`. It does not modify the response body unless the body is currently empty, in which case it sets the body to the default status text.

Example:

ctx.SendStatusCode(fasthttp.StatusNoContent) // sets 204 No Content

func (*Context) SendString

func (c *Context) SendString(value string) error

SendString writes a plain text response body.

func (*Context) SendTOML

func (c *Context) SendTOML(v any, ctype ...string) error

SendTOML encodes v as TOML and writes it to the response.

It sets the Content-Type to "application/toml; charset=utf-8" unless a custom value is provided via ctype. A 500 Internal Server Error is returned if encoding fails.

Example:

settings := map[string]any{
    "mode": "production",
    "port": 8080,
}
if err := c.SendTOML(settings); err != nil {
    c.Logger().Error(err)
}

To override the default content type:

if err := c.SendTOML(settings, "text/x-toml"); err != nil {
    ...
}

func (*Context) SendXML

func (c *Context) SendXML(value any, ctype ...string) error

SendXML encodes the given value as XML and writes it to the response.

It sets the Content-Type to "application/xml; charset=utf-8" unless overridden via an optional parameter.

Example:

type User struct {
    Name string `xml:"name"`
}

return c.SendXML(User{Name: "Alice"})

func (*Context) SendXMLIndent

func (c *Context) SendXMLIndent(value any, prefix, indent string, ctype ...string) error

SendXMLIndent encodes the given value as indented (pretty-formatted) XML and writes it to the response.

It sets the Content-Type to "application/xml; charset=utf-8" unless overridden. This is useful for development or human-readable output.

Example:

type User struct {
    Name string `xml:"name"`
}

return c.SendXMLIndent(User{Name: "Alice"}, "", "  ")

func (*Context) SendYAML

func (c *Context) SendYAML(v any, ctype ...string) error

SendYAML encodes v as YAML and writes it to the response.

It sets the Content‑Type to "application/yaml; charset=utf‑8" unless a custom value is provided via ctype. A 500 Internal Server Error is returned if encoding fails.

Example:

data := map[string]any{
    "status": "ok",
    "count":  42,
}
if err := c.SendYAML(data); err != nil {
    c.Logger().Error(err)
}

To override the default content type:

if err := c.SendYAML(data, "text/x-yaml"); err != nil {
    ...
}

func (*Context) SetContentType

func (c *Context) SetContentType(value string)

SetContentType sets the “Content‑Type” response header.

The supplied value must be a valid MIME type string, e.g. "application/json" or "text/html; charset=utf-8". It is typically called by higher‑level helpers so callers do not need to set the header manually.

func (*Context) SetHeader

func (c *Context) SetHeader(key, value string)

SetHeader sets the HTTP response header with the given key and value.

func (*Context) Status

func (c *Context) Status(code int) *Context

Status sets the HTTP status code for the response.

func (*Context) URL

func (c *Context) URL(route string, pairs ...any) string

URL returns a URL for a named route with optional path parameters.

func (*Context) Zeno

func (c *Context) Zeno() *Zeno

Zeno returns the underlying Zeno engine instance.

type DecoderFunc

type DecoderFunc func(data []byte, v any) error

DecoderFunc defines a function signature used for decoding a byte slice (such as an HTTP request body) into a given Go struct. It takes the raw data and a pointer to the target value and returns an error if decoding fails.

Common usage includes binding request bodies to structs during JSON, XML, or form parsing.

Example:

jsonDecoder := func(data []byte, v any) error {
    return json.Unmarshal(data, v)
}

type EncoderFunc

type EncoderFunc func(v any) ([]byte, error)

EncoderFunc defines a function signature used for encoding a Go value into a specific format, such as JSON, XML, or other content types. It takes a value of any type and returns the encoded byte slice or an error if encoding fails.

Common usage includes setting a default encoder for the response payload.

Example:

jsonEncoder := func(v any) ([]byte, error) {
    return json.Marshal(v)
}

type HTTPError

type HTTPError interface {
	error
	StatusCode() int
}

HTTPError is returned by handlers and middleware to indicate an HTTP failure. Implementations carry both the underlying error message and the HTTP status code that should be sent to the client.

func NewHTTPError

func NewHTTPError(status int, msg ...string) HTTPError

NewHTTPError returns an HTTPError with the supplied status code and optional message. When msg is empty, the description returned by StatusText is used.

example := NewHTTPError(StatusBadRequest)                     // “Bad Request”
custom  := NewHTTPError(StatusBadRequest, "invalid payload")  // custom text

func ToHTTPError

func ToHTTPError(err error) HTTPError

ToHTTPError converts any error to an HTTPError. If err already implements HTTPError it is returned unmodified. Otherwise a new HTTPError with StatusInternalServerError is created whose message is err.Error().

type HTTPRange

type HTTPRange struct {
	Start, End int64
}

HTTPRange represents a parsed byte range from the Range header.

type Handler

type Handler func(*Context) error

type IndentFunc

type IndentFunc func(v any, prefix, indent string) ([]byte, error)

IndentFunc defines a function signature used for applying indentation settings to a value, typically for pretty-printing purposes. It accepts a value, a prefix string, and an indent string, and is expected to modify or output a formatted version accordingly.

This is often used in logging, debugging, or pretty-printing JSON/XML for readability. Note: This function signature suggests side-effect usage or wrapping purposes.

Example:

jsonIndent := func(v any, prefix, indent string) {
    return json.MarshalIndent(v, prefix, indent)
}

type Map

type Map map[string]any

type Range

type Range struct {
	Type   string
	Ranges []HTTPRange
}

Range represents a collection of HTTP byte ranges with unit type.

type Route

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

Route represents a route definition, including its path, name, associated handlers, and belonging group.

func (*Route) Connect

func (r *Route) Connect(handlers ...Handler) *Route

Connect registers handlers for the CONNECT HTTP method.

func (*Route) Delete

func (r *Route) Delete(handlers ...Handler) *Route

Delete registers handlers for the DELETE HTTP method.

func (*Route) Get

func (r *Route) Get(handlers ...Handler) *Route

Get registers handlers for the GET HTTP method.

func (*Route) Head

func (r *Route) Head(handlers ...Handler) *Route

Head registers handlers for the HEAD HTTP method.

func (*Route) Name

func (r *Route) Name(name string) *Route

Name sets a custom name for the route and registers it using that name.

Example:

r := newRoute("/user/{id}", group).Name("user.show")

func (*Route) Options

func (r *Route) Options(handlers ...Handler) *Route

Options registers handlers for the OPTIONS HTTP method.

func (*Route) Patch

func (r *Route) Patch(handlers ...Handler) *Route

Patch registers handlers for the PATCH HTTP method.

func (*Route) Post

func (r *Route) Post(handlers ...Handler) *Route

Post registers handlers for the POST HTTP method.

func (*Route) Put

func (r *Route) Put(handlers ...Handler) *Route

Put registers handlers for the PUT HTTP method.

func (*Route) To

func (r *Route) To(methods string, handlers ...Handler) *Route

To registers the same handlers for multiple comma-separated HTTP methods.

Example:

r.To("GET,POST", handler)

func (*Route) Trace

func (r *Route) Trace(handlers ...Handler) *Route

Trace registers handlers for the TRACE HTTP method.

func (*Route) URL

func (r *Route) URL(pairs ...interface{}) (s string)

URL generates a URL path from the route template and provided parameters.

Example:

r := newRoute("/users/{id}", group).Name("user.show")
url := r.URL("id", 42) // => "/users/42"

type RouteGroup

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

RouteGroup represents a collection of routes with a common prefix and shared middleware handlers. It allows organizing routes into subgroups for modular design.

func NewRouteGroup

func NewRouteGroup(prefix string, zeno *Zeno, handlers []Handler) *RouteGroup

NewRouteGroup creates and returns a new route group with the given path prefix, associated Zeno instance, and optional middleware handlers.

Example:

api := NewRouteGroup("/api", app, []Handler{authMiddleware})

func (*RouteGroup) Connect

func (r *RouteGroup) Connect(path string, handlers ...Handler) *Route

Connect registers a new route in the group for the CONNECT HTTP method.

func (*RouteGroup) Delete

func (r *RouteGroup) Delete(path string, handlers ...Handler) *Route

Delete registers a new route in the group for the DELETE HTTP method.

func (*RouteGroup) Get

func (r *RouteGroup) Get(path string, handlers ...Handler) *Route

Get registers a new route in the group for the GET HTTP method.

Example:

g.Get("/ping", pingHandler)

func (*RouteGroup) Group

func (r *RouteGroup) Group(prefix string, handlers ...Handler) *RouteGroup

RouteGroup returns a new RouteRouteGroup whose path prefix is the current group’s prefix followed by prefix. Any handlers passed to RouteGroup are appended to the new group; if none are provided, the new group inherits the current group’s handlers.

Example:

api := router.RouteGroup("/api", auth)
v1  := api.RouteGroup("/v1")           // -> prefix “/api/v1”, handlers {auth}

prefix should begin with “/”; RouteGroup does not add a leading slash automatically.

func (*RouteGroup) Head

func (r *RouteGroup) Head(path string, handlers ...Handler) *Route

Head registers a new route in the group for the HEAD HTTP method.

func (*RouteGroup) Options

func (r *RouteGroup) Options(path string, handlers ...Handler) *Route

Options registers a new route in the group for the OPTIONS HTTP method.

func (*RouteGroup) Patch

func (r *RouteGroup) Patch(path string, handlers ...Handler) *Route

Patch registers a new route in the group for the PATCH HTTP method.

func (*RouteGroup) Post

func (r *RouteGroup) Post(path string, handlers ...Handler) *Route

Post registers a new route in the group for the POST HTTP method.

Example:

g.Post("/submit", submitHandler)

func (*RouteGroup) Put

func (r *RouteGroup) Put(path string, handlers ...Handler) *Route

Put registers a new route in the group for the PUT HTTP method.

func (*RouteGroup) Route

func (r *RouteGroup) Route(prefix string, fn func(*RouteGroup), handlers ...Handler)

Route creates a new sub-route group with the given path prefix and optional handlers. It then executes the provided function with the new group.

This enables nesting of routes in a structured way, similar to Chi:

r.Route("/api", func(r *RouteGroup) {
    r.Get("/users", listUsers)
})

func (*RouteGroup) To

func (r *RouteGroup) To(methods, path string, handlers ...Handler) *Route

To registers a new route in the group for multiple HTTP methods, specified as a comma-separated string (e.g. "GET,POST").

Example:

g.To("GET,POST", "/users", usersHandler)

func (*RouteGroup) Trace

func (r *RouteGroup) Trace(path string, handlers ...Handler) *Route

Trace registers a new route in the group for the TRACE HTTP method.

func (*RouteGroup) Use

func (r *RouteGroup) Use(handlers ...Handler)

Use registers one or multiple handlers to the current route group. These handlers will be shared by all routes belong to this group and its subgroups.

type Zeno

type Zeno struct {
	RouteGroup // Root group for registering routes directly

	// Custom error handler
	ErrorHandler func(*Context, error) error

	// JsonDecoder is the default function used to decode a JSON payload
	// from the request body. It should unmarshal the byte slice into
	// the target Go value. A typical implementation uses json.Unmarshal
	// or a high-performance alternative such as sonic or jsoniter.
	JsonDecoder DecoderFunc

	// JsonEncoder is the default function used to encode a Go value into
	// JSON format. It should return the marshaled byte slice that can be
	// directly written to the response. Set the "Content-Type" to
	// "application/json" before sending the bytes.
	JsonEncoder EncoderFunc

	// JsonIndent is an optional function used to pretty-print JSON output.
	// It takes a Go value, prefix, and indent string to format the output
	// for better readability. Typically wraps json.MarshalIndent or similar.
	JsonIndent IndentFunc

	// SecureJSONPrefix is a string prepended to all JSON responses
	// to prevent JSON Hijacking attacks. Common value: "while(1);"
	// If set, all JSON responses will begin with this prefix.
	SecureJSONPrefix string

	// XmlDecoder is the default function used to decode an XML payload
	// from the request body. It should unmarshal the byte slice into
	// the target Go value. Typically wraps encoding/xml.Unmarshal or
	// a faster XML decoder.
	XmlDecoder DecoderFunc

	// XmlEncoder is the default function used to encode a Go value into
	// XML format. It should return the marshaled byte slice that can be
	// written directly to the response. You should set the
	// "Content-Type" to "application/xml" or "text/xml" before writing.
	XmlEncoder EncoderFunc

	// XmlIndent is an optional function used to pretty-print XML output.
	// It takes a Go value, prefix, and indent string to format the output.
	// Usually wraps xml.MarshalIndent or any compatible alternative.
	XmlIndent IndentFunc

	// YamlDecoder is the default function used to decode a YAML payload
	// from the request body. It should unmarshal the byte slice into the
	// target Go value.
	YamlDecoder DecoderFunc

	// YamlEncoder is the default function used to encode a Go value into
	// YAML format. It should return the marshaled byte slice that can be
	// written directly to the response. You should set the "Content-Type"
	// to "application/x-yaml" or "text/yaml" before writing the response.
	YamlEncoder EncoderFunc

	// TomlDecoder is the default function used to decode a TOML payload
	// from the request body. It should unmarshal the byte slice into the
	// target Go value.
	TomlDecoder DecoderFunc

	// TomlEncoder is the default function used to encode a Go value into
	// TOML format. It should return the marshaled byte slice that can be
	// written directly to the response. You should set the "Content-Type"
	// to "application/toml" or "text/x-toml" before writing the response.
	TomlEncoder EncoderFunc

	// CborDecoder is the default function used to decode a CBOR payload
	// from the request body. It should unmarshal the byte slice into the
	// target Go value. CBOR is a binary JSON-like format used in constrained
	// environments like IoT.
	CborDecoder DecoderFunc

	// CborEncoder is the default function used to encode a Go value into
	// CBOR format. It should return the marshaled byte slice that can be
	// written directly to the response. You should set the "Content-Type"
	// to "application/cbor" before writing the response.
	CborEncoder EncoderFunc
	// contains filtered or unexported fields
}

Zeno is the main application struct for the framework. It stores routing trees, middleware, error handling logic, and manages request context pooling and execution.

func New

func New() *Zeno

New creates and returns a new Zeno instance with default settings, initializes route trees, not found handlers, and context pooling.

func (*Zeno) GetRoute

func (z *Zeno) GetRoute(name string) *Route

Route returns a named route by name.

func (*Zeno) HandleRequest

func (z *Zeno) HandleRequest(ctx *fasthttp.RequestCtx)

HandleRequest is the main request entry point for fasthttp. It acquires a context from the pool, performs route matching, executes the handler chain, and handles any returned errors.

func (*Zeno) NotFound

func (r *Zeno) NotFound(handlers ...Handler)

NotFound sets the handler(s) to be used when no route is matched. The final notFound handler chain includes global middleware.

func (*Zeno) Run

func (z *Zeno) Run(addr string) error

Run starts the HTTP server on the given address using fasthttp. If useReusePort is true, it uses SO_REUSEPORT for load balancing across processes.

func (*Zeno) Use

func (r *Zeno) Use(handlers ...Handler)

Use appends the specified handlers to the router and shares them with all routes.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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