keratin

package module
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: 18 Imported by: 0

README

Keratin

Go Reference Go Report Card codecov License

Overview

Keratin is a thin, idiomatic Go wrapper around http.ServeMux that provides a clean, composable API for building HTTP servers with route grouping, middleware support, and error handling—all while maintaining zero dependencies beyond the Go standard library and minimal external packages for testing and UUID generation.

Key Features
  • Route Grouping: Organize routes into logical groups with shared prefixes and middleware
  • Flexible Middleware: Apply middleware at router, group, or route level with priority-based execution
  • Pre-Middleware: Register middleware that executes before route matching
  • Error Handling: Centralized error handling with custom error handlers
  • Type-Safe: Built-in types for handlers, middleware, and error handlers
  • Method Shorthands: Convenience methods for all HTTP verbs (GET, POST, PUT, DELETE, PATCH, etc.)
  • Zero Abstraction Leak: Leverages http.ServeMux pattern matching without re-implementing routing logic
  • Minimal Dependencies: Only uses github.com/google/uuid for middleware IDs and github.com/stretchr/testify for testing
Why Keratin?

Just as keratin provides the essential structure that makes wool strong, flexible, and resilient, Keratin provides the essential structure for building robust HTTP services in the Gowool ecosystem. While Go's http.ServeMux is powerful, it lacks built-in support for route grouping and middleware at the router level. Keratin fills this gap by providing a thin, composable wrapper that:

  • Maintains the simplicity and performance of the standard library
  • Adds essential features for building production-grade HTTP services
  • Follows idiomatic Go patterns and conventions
  • Provides a clean, fluent API for route definition

Installation

go get github.com/gowool/keratin

Quick Start

package main

import (
	"log/slog"
    "net/http"

    "github.com/gowool/keratin"
)

func main() {
    router := keratin.NewRouter()

    router.GET("/health", func(w http.ResponseWriter, _ *http.Request) error {
		w.WriteHeader(http.StatusOK)
        _, err := w.Write([]byte("OK"))
        return err
    })

    api := router.Group("/api")
    api.UseFunc(loggingMiddleware)

    v1 := api.Group("/v1")
    v1.Route(http.MethodGet, "/users", listUsers())
    v1.Route(http.MethodPost, "/users", createUser())

    _ = http.ListenAndServe(":8080", router.Build())
}

func loggingMiddleware(next keratin.Handler) keratin.Handler {
    return keratin.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
		defer slog.Info("request",
			slog.String("method", r.Method),
			slog.String("protocol", r.Proto),
			slog.String("host", r.Host),
			slog.String("pattern", r.Pattern),
			slog.String("uri", r.RequestURI),
			slog.String("path", r.URL.Path),
			slog.String("referer", r.Referer()),
			slog.String("user_agent", r.UserAgent()),
        )
		
        return next.ServeHTTP(w, r)
    })
}

func listUsers() keratin.Handler {
	return keratin.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) error {
		w.WriteHeader(http.StatusOK)
		_, err := w.Write([]byte("users"))
		return err
	})
}

func createUser() keratin.Handler {
	return keratin.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) error {
		w.WriteHeader(http.StatusCreated)
		return nil
	})
}

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Index

Constants

View Source
const (
	CharsetUTF8    = "charset=UTF-8"
	XMLHTTPRequest = "XMLHttpRequest"
	IndexPage      = "index.html"
)
View Source
const (
	// MIMEApplicationJSON JavaScript Object Notation (JSON) https://www.rfc-editor.org/rfc/rfc8259
	MIMEApplicationJSON                  = "application/json"
	MIMEApplicationJavaScript            = "application/javascript"
	MIMEApplicationJavaScriptCharsetUTF8 = MIMEApplicationJavaScript + "; " + CharsetUTF8
	MIMEApplicationXML                   = "application/xml"
	MIMEApplicationXMLCharsetUTF8        = MIMEApplicationXML + "; " + CharsetUTF8
	MIMETextXML                          = "text/xml"
	MIMETextXMLCharsetUTF8               = MIMETextXML + "; " + CharsetUTF8
	MIMEApplicationForm                  = "application/x-www-form-urlencoded"
	MIMEApplicationProtobuf              = "application/protobuf"
	MIMEApplicationMsgpack               = "application/msgpack"
	MIMETextHTML                         = "text/html"
	MIMETextHTMLCharsetUTF8              = MIMETextHTML + "; " + CharsetUTF8
	MIMETextPlain                        = "text/plain"
	MIMETextPlainCharsetUTF8             = MIMETextPlain + "; " + CharsetUTF8
	MIMEMultipartForm                    = "multipart/form-data"
	MIMEOctetStream                      = "application/octet-stream"
	MIMEEventStream                      = "text/event-stream"
	MIMEApplicationZip                   = "application/zip"
)

MIME types

View Source
const (
	HeaderAccept         = "Accept"
	HeaderAcceptEncoding = "Accept-Encoding"
	HeaderAcceptLanguage = "Accept-Language"
	// HeaderAllow is the name of the "Allow" header field used to list the set of methods
	// advertised as supported by the target resource. Returning an Allow header is mandatory
	// for Status 405 (method not found) and useful for the OPTIONS method in responses.
	// See RFC 7231: https://datatracker.ietf.org/doc/html/rfc7231#section-7.4.1
	HeaderAllow               = "Allow"
	HeaderAuthorization       = "Authorization"
	HeaderContentDisposition  = "Content-Disposition"
	HeaderContentEncoding     = "Content-Encoding"
	HeaderContentLength       = "Content-Length"
	HeaderContentType         = "Content-Type"
	HeaderCookie              = "Cookie"
	HeaderSetCookie           = "Set-Cookie"
	HeaderIfModifiedSince     = "If-Modified-Since"
	HeaderLastModified        = "Last-Modified"
	HeaderLocation            = "Location"
	HeaderRetryAfter          = "Retry-After"
	HeaderUpgrade             = "Upgrade"
	HeaderVary                = "Vary"
	HeaderWWWAuthenticate     = "WWW-Authenticate"
	HeaderXForwardedFor       = "X-Forwarded-For"
	HeaderXForwardedProto     = "X-Forwarded-Proto"
	HeaderXForwardedProtocol  = "X-Forwarded-Protocol"
	HeaderXForwardedSsl       = "X-Forwarded-Ssl"
	HeaderXUrlScheme          = "X-Url-Scheme"
	HeaderXHTTPMethodOverride = "X-HTTP-Method-Override"
	HeaderXRealIP             = "X-Real-Ip"
	HeaderXRequestID          = "X-Request-Id"
	HeaderXCorrelationID      = "X-Correlation-Id"
	HeaderXRequestedWith      = "X-Requested-With"
	HeaderServer              = "Server"
	HeaderOrigin              = "Origin"
	HeaderCacheControl        = "Cache-Control"
	HeaderConnection          = "Connection"
	HeaderXRobotsTag          = "X-Robots-Tag"
	HeaderXRateLimitLimit     = "X-RateLimit-Limit"
	HeaderXRateLimitRemaining = "X-RateLimit-Remaining"
	HeaderXRateLimitReset     = "X-RateLimit-Reset"

	// Access control
	HeaderAccessControlRequestMethod    = "Access-Control-Request-Method"
	HeaderAccessControlRequestHeaders   = "Access-Control-Request-Headers"
	HeaderAccessControlAllowOrigin      = "Access-Control-Allow-Origin"
	HeaderAccessControlAllowMethods     = "Access-Control-Allow-Methods"
	HeaderAccessControlAllowHeaders     = "Access-Control-Allow-Headers"
	HeaderAccessControlAllowCredentials = "Access-Control-Allow-Credentials"
	HeaderAccessControlExposeHeaders    = "Access-Control-Expose-Headers"
	HeaderAccessControlMaxAge           = "Access-Control-Max-Age"

	// Security
	HeaderStrictTransportSecurity         = "Strict-Transport-Security"
	HeaderXContentTypeOptions             = "X-Content-Type-Options"
	HeaderXXSSProtection                  = "X-XSS-Protection"
	HeaderXFrameOptions                   = "X-Frame-Options"
	HeaderContentSecurityPolicy           = "Content-Security-Policy"
	HeaderContentSecurityPolicyReportOnly = "Content-Security-Policy-Report-Only"
	HeaderXCSRFToken                      = "X-CSRF-Token"
	HeaderReferrerPolicy                  = "Referrer-Policy"

	// HeaderCFIPCountry cloudflare country code
	// https://developers.cloudflare.com/fundamentals/reference/http-headers/#cf-ipcountry
	HeaderCFIPCountry = "CF-IPCountry"

	// HeaderSecFetchSite fetch metadata request header indicates the relationship between a request initiator's
	// origin and the origin of the requested resource.
	// See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-Fetch-Site
	HeaderSecFetchSite = "Sec-Fetch-Site"
)

Headers

Variables

View Source
var (
	ErrBadRequest                    = &httpError{http.StatusBadRequest}                    // HTTP 400 Bad Request
	ErrUnauthorized                  = &httpError{http.StatusUnauthorized}                  // HTTP 401 Unauthorized
	ErrPaymentRequired               = &httpError{http.StatusPaymentRequired}               // HTTP 402 Payment Required
	ErrForbidden                     = &httpError{http.StatusForbidden}                     // HTTP 403 Forbidden
	ErrNotFound                      = &httpError{http.StatusNotFound}                      // HTTP 404 Not Found
	ErrMethodNotAllowed              = &httpError{http.StatusMethodNotAllowed}              // HTTP 405 Method Not Allowed
	ErrNotAcceptable                 = &httpError{http.StatusNotAcceptable}                 // HTTP 406 Not Acceptable
	ErrProxyAuthRequired             = &httpError{http.StatusProxyAuthRequired}             // HTTP 407 Proxy AuthRequired
	ErrRequestTimeout                = &httpError{http.StatusRequestTimeout}                // HTTP 408 Request Timeout
	ErrConflict                      = &httpError{http.StatusConflict}                      // HTTP 409 Conflict
	ErrGone                          = &httpError{http.StatusGone}                          // HTTP 410 Gone
	ErrLengthRequired                = &httpError{http.StatusLengthRequired}                // HTTP 411 Length Required
	ErrPreconditionFailed            = &httpError{http.StatusPreconditionFailed}            // HTTP 412 Precondition Failed
	ErrRequestEntityTooLarge         = &httpError{http.StatusRequestEntityTooLarge}         // HTTP 413 Payload Too Large
	ErrRequestURITooLong             = &httpError{http.StatusRequestURITooLong}             // HTTP 414 URI Too Long
	ErrUnsupportedMediaType          = &httpError{http.StatusUnsupportedMediaType}          // HTTP 415 Unsupported Media Type
	ErrRequestedRangeNotSatisfiable  = &httpError{http.StatusRequestedRangeNotSatisfiable}  // HTTP 416 Range Not Satisfiable
	ErrExpectationFailed             = &httpError{http.StatusExpectationFailed}             // HTTP 417 Expectation Failed
	ErrTeapot                        = &httpError{http.StatusTeapot}                        // HTTP 418 I'm a teapot
	ErrMisdirectedRequest            = &httpError{http.StatusMisdirectedRequest}            // HTTP 421 Misdirected Request
	ErrUnprocessableEntity           = &httpError{http.StatusUnprocessableEntity}           // HTTP 422 Unprocessable Entity
	ErrLocked                        = &httpError{http.StatusLocked}                        // HTTP 423 Locked
	ErrFailedDependency              = &httpError{http.StatusFailedDependency}              // HTTP 424 Failed Dependency
	ErrTooEarly                      = &httpError{http.StatusTooEarly}                      // HTTP 425 Too Early
	ErrUpgradeRequired               = &httpError{http.StatusUpgradeRequired}               // HTTP 426 Upgrade Required
	ErrPreconditionRequired          = &httpError{http.StatusPreconditionRequired}          // HTTP 428 Precondition Required
	ErrTooManyRequests               = &httpError{http.StatusTooManyRequests}               // HTTP 429 Too Many Requests
	ErrRequestHeaderFieldsTooLarge   = &httpError{http.StatusRequestHeaderFieldsTooLarge}   // HTTP 431 Request Header Fields Too Large
	ErrUnavailableForLegalReasons    = &httpError{http.StatusUnavailableForLegalReasons}    // HTTP 451 Unavailable For Legal Reasons
	ErrInternalServerError           = &httpError{http.StatusInternalServerError}           // HTTP 500 Internal Server Error
	ErrNotImplemented                = &httpError{http.StatusNotImplemented}                // HTTP 501 Not Implemented
	ErrBadGateway                    = &httpError{http.StatusBadGateway}                    // HTTP 502 Bad Gateway
	ErrServiceUnavailable            = &httpError{http.StatusServiceUnavailable}            // HTTP 503 Service Unavailable
	ErrGatewayTimeout                = &httpError{http.StatusGatewayTimeout}                // HTTP 504 Gateway Timeout
	ErrHTTPVersionNotSupported       = &httpError{http.StatusHTTPVersionNotSupported}       // HTTP 505 HTTP Version Not Supported
	ErrVariantAlsoNegotiates         = &httpError{http.StatusVariantAlsoNegotiates}         // HTTP 506 Variant Also Negotiates
	ErrInsufficientStorage           = &httpError{http.StatusInsufficientStorage}           // HTTP 507 Insufficient Storage
	ErrLoopDetected                  = &httpError{http.StatusLoopDetected}                  // HTTP 508 Loop Detected
	ErrNotExtended                   = &httpError{http.StatusNotExtended}                   // HTTP 510 Not Extended
	ErrNetworkAuthenticationRequired = &httpError{http.StatusNetworkAuthenticationRequired} // HTTP 511 Network Authentication Required
)

Following errors can produce HTTP status code by implementing HTTPStatusCoder interface

View Source
var ErrFileNotFound = ErrNotFound.Wrap(errors.New("file not found"))
View Source
var MultipartMaxMemory int64 = 8 * 1024

MultipartMaxMemory is the maximum memory to use when parsing multipart form data.

Functions

func Blob

func Blob(w http.ResponseWriter, status int, contentType string, b []byte) error

Blob writes a blob (bytes slice) response.

func DefaultErrorHandler

func DefaultErrorHandler(w http.ResponseWriter, r *http.Request, err error)

func ErrorStatusCode

func ErrorStatusCode(err error) int

func HTML

func HTML(w http.ResponseWriter, status int, data string) error

HTML writes an HTML response.

func HTMLBlob

func HTMLBlob(w http.ResponseWriter, status int, b []byte) error

HTMLBlob sends an HTTP blob response with status code.

func HTTPErrorStatusCode

func HTTPErrorStatusCode(err error) int

func JSON

func JSON(w http.ResponseWriter, status int, i any) error

JSON sends a JSON response with status code.

func JSONBlob

func JSONBlob(w http.ResponseWriter, status int, b []byte) error

func JSONPretty

func JSONPretty(w http.ResponseWriter, status int, i any, indent string) error

JSONPretty sends a pretty-print JSON with status code.

func NegotiateFormat

func NegotiateFormat(acceptHeader string, offered ...string) string

NegotiateFormat returns an acceptable Accept format.

func ParseAcceptLanguage

func ParseAcceptLanguage(acceptLanguageHeader string) []string

ParseAcceptLanguage parses the 'Accept-Language' HTTP header into a slice of language codes sorted by their order of appearance.

func Pattern

func Pattern(r *http.Request) string

func RemoteIP

func RemoteIP(r *http.Request) string

RemoteIP returns the IP address of the client that sent the request.

IPv6 addresses are returned expanded. For example, "2001:db8::1" becomes "2001:0db8:0000:0000:0000:0000:0000:0001".

Note that if you are behind reverse proxy(ies), this method returns the IP of the last connecting proxy.

func ResponseCommitted

func ResponseCommitted(w http.ResponseWriter) bool

func ResponseReaderFrom

func ResponseReaderFrom(w http.ResponseWriter) io.ReaderFrom

func ResponseSize

func ResponseSize(w http.ResponseWriter) int64

func ResponseStatusCode

func ResponseStatusCode(w http.ResponseWriter) int

func Scheme

func Scheme(r *http.Request) string

Scheme returns the HTTP protocol scheme, `http` or `https`.

func Stream

func Stream(w http.ResponseWriter, status int, contentType string, reader io.Reader) error

Stream streams the specified reader into the response.

func TextPlain

func TextPlain(w http.ResponseWriter, status int, data string) error

TextPlain writes a plain string response.

func XML

func XML(w http.ResponseWriter, status int, i any) error

XML writes an XML response. It automatically prepends the generic xml.Header string to the response.

func XMLBlob

func XMLBlob(w http.ResponseWriter, status int, b []byte) error

XMLBlob sends an XML blob response with status code.

func XMLPretty

func XMLPretty(w http.ResponseWriter, status int, i any, indent string) error

XMLPretty sends a pretty-print XML with status code. It automatically prepends the generic xml.Header string to the response.

Types

type BeforeServeFunc

type BeforeServeFunc func(http.ResponseWriter, *http.Request, fs.File, fs.FileInfo)

func Attachment

func Attachment(name string) BeforeServeFunc

Attachment set header to send a response as attachment, prompting client to save the file.

func CacheControl

func CacheControl(data ...string) BeforeServeFunc

func ContentSecurityPolicy

func ContentSecurityPolicy(data ...string) BeforeServeFunc

func Inline

func Inline(name string) BeforeServeFunc

Inline set header to send a response as inline, opening the file in the browser.

type Committer

type Committer interface {
	Committed() bool
}

func ResponseCommitter

func ResponseCommitter(w http.ResponseWriter) Committer

type Context

type Context interface {
	Scheme() string
	RealIP() string
	Pattern() string
	Methods() string
	AnyMethods() bool
}

func FromContext

func FromContext(ctx context.Context) Context

type ErrorHandlerFunc

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

type HTTPError

type HTTPError struct {
	Code    int    `json:"-"`
	Message string `json:"message"`
	// contains filtered or unexported fields
}

func NewHTTPError

func NewHTTPError(code int, message string) *HTTPError

NewHTTPError creates a new instance of HTTPError

func (*HTTPError) Error

func (he *HTTPError) Error() string

Error makes it compatible with an `error` interface.

func (*HTTPError) StatusCode

func (he *HTTPError) StatusCode() int

StatusCode returns status code for HTTP response

func (*HTTPError) Unwrap

func (he *HTTPError) Unwrap() error

func (*HTTPError) Wrap

func (he *HTTPError) Wrap(err error) error

Wrap returns a new HTTPError with given errors wrapped inside

type Handler

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

type HandlerFunc

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

func FileFS

func FileFS(fsys fs.FS, filename string, beforeServe ...BeforeServeFunc) HandlerFunc

FileFS serves the specified filename from fsys.

func StaticFS

func StaticFS(fsys fs.FS, param string, indexFallback bool, beforeServe ...BeforeServeFunc) HandlerFunc

StaticFS serve static directory content from fsys.

If a file resource is missing and indexFallback is set, the request will be forwarded to the base index.html (useful for SPA with pretty urls).

Special redirects:

  • if "path" is a file that ends in index.html, it is redirected to its non-index.html version (eg. /test/index.html -> /test/)
  • if "path" is a directory that has index.html, the index.html file is rendered, otherwise if missing - returns ErrFileNotFound or fallback to the root index.html if indexFallback is set

Example:

fsys := os.DirFS("./public")
router.GET("/files/{path...}", StaticFS(fsys, "path", false))

func (HandlerFunc) ServeHTTP

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

type IPExtractor

type IPExtractor func(r *http.Request) string

func RealIP

func RealIP(fn func(ctx context.Context) (*TrustedProxy, error)) IPExtractor

type Middleware

type Middleware[H any] struct {
	ID       string
	Priority int
	Func     func(H) H
}

type Middlewares

type Middlewares[H any] []*Middleware[H]

type Option

type Option func(*Router)

func WithErrorHandler

func WithErrorHandler(errorHandler ErrorHandlerFunc) Option

func WithIPExtractor

func WithIPExtractor(ipExtractor IPExtractor) Option

func WithRequestInterceptor

func WithRequestInterceptor(interceptor func(r *http.Request) (*http.Request, func())) Option

func WithResponseInterceptor

func WithResponseInterceptor(interceptor func(w http.ResponseWriter) (http.ResponseWriter, func())) Option

type RWUnwrapper

type RWUnwrapper interface {
	Unwrap() http.ResponseWriter
}

RWUnwrapper specifies that http.ResponseWriter could be "unwrapped" (usually used with http.ResponseController).

type Route

type Route struct {
	Method      string
	Path        string
	Handler     Handler
	Middlewares Middlewares[Handler]
}

func (*Route) Use

func (route *Route) Use(middlewares ...*Middleware[Handler]) *Route

Use registers one or multiple middleware handlers to the current route.

func (*Route) UseFunc

func (route *Route) UseFunc(middlewareFuncs ...func(Handler) Handler) *Route

UseFunc registers one or multiple middleware functions to the current route.

The registered middleware functions are "anonymous" and with default priority, aka. executes in the order they were registered.

If you need to specify a named middleware or middleware with custom exec prirority, use the Route.Use method.

type Router

type Router struct {
	*RouterGroup

	PreMiddlewares  Middlewares[Handler]
	HTTPMiddlewares Middlewares[http.Handler]
	// contains filtered or unexported fields
}

func NewRouter

func NewRouter(options ...Option) *Router

func (*Router) Build

func (r *Router) Build() http.Handler

func (*Router) BuildWithMux

func (r *Router) BuildWithMux(mux *http.ServeMux) http.Handler

func (*Router) Patterns

func (r *Router) Patterns() iter.Seq[string]

Patterns returns a sequence of all route patterns currently registered in the router as strings.

func (*Router) Pre

func (r *Router) Pre(middlewares ...*Middleware[Handler])

Pre registers one or multiple middleware handlers which are run before router tries to find matching route.

func (*Router) PreFunc

func (r *Router) PreFunc(middlewareFuncs ...func(Handler) Handler)

PreFunc registers one or multiple middleware functions which are run before router tries to find matching route.

The registered middleware functions are "anonymous" and with default priority, aka. executes in the order they were registered.

If you need to specify a named middleware or middleware with custom exec priority, use Router.Pre method.

func (*Router) PreHTTP

func (r *Router) PreHTTP(middlewares ...*Middleware[http.Handler])

PreHTTP registers one or multiple HTTP middleware to be executed before all middlewares.

func (*Router) PreHTTPFunc

func (r *Router) PreHTTPFunc(middlewareFuncs ...func(next http.Handler) http.Handler)

PreHTTPFunc registers one or multiple HTTP middleware to be executed before all middlewares.

type RouterGroup

type RouterGroup struct {
	Middlewares Middlewares[Handler]
	// contains filtered or unexported fields
}

func (*RouterGroup) Any

func (group *RouterGroup) Any(path string, handler func(http.ResponseWriter, *http.Request) error) *Route

Any is a shorthand for RouterGroup.RouteFunc with "" as route method (aka. matches any method).

func (*RouterGroup) CONNECT

func (group *RouterGroup) CONNECT(path string, handler func(http.ResponseWriter, *http.Request) error) *Route

CONNECT is a shorthand for RouterGroup.RouteFunc with CONNECT as route method.

func (*RouterGroup) DELETE

func (group *RouterGroup) DELETE(path string, handler func(http.ResponseWriter, *http.Request) error) *Route

DELETE is a shorthand for RouterGroup.RouteFunc with DELETE as route method.

func (*RouterGroup) GET

func (group *RouterGroup) GET(path string, handler func(http.ResponseWriter, *http.Request) error) *Route

GET is a shorthand for RouterGroup.RouteFunc with GET as route method.

func (*RouterGroup) Group

func (group *RouterGroup) Group(prefix string) *RouterGroup

Group creates and register a new child RouterGroup into the current one with the specified prefix.

The prefix follows the standard Go net/http http.ServeMux pattern format ("[HOST]/[PATH]") and will be concatenated recursively into the final route path, meaning that only the root level group could have HOST as part of the prefix.

Returns the newly created group to allow chaining and registering sub-routes and group specific Middlewares.

func (*RouterGroup) HEAD

func (group *RouterGroup) HEAD(path string, handler func(http.ResponseWriter, *http.Request) error) *Route

HEAD is a shorthand for RouterGroup.RouteFunc with HEAD as route method.

func (*RouterGroup) OPTIONS

func (group *RouterGroup) OPTIONS(path string, handler func(http.ResponseWriter, *http.Request) error) *Route

OPTIONS is a shorthand for RouterGroup.RouteFunc with OPTIONS as route method.

func (*RouterGroup) PATCH

func (group *RouterGroup) PATCH(path string, handler func(http.ResponseWriter, *http.Request) error) *Route

PATCH is a shorthand for RouterGroup.RouteFunc with PATCH as route method.

func (*RouterGroup) POST

func (group *RouterGroup) POST(path string, handler func(http.ResponseWriter, *http.Request) error) *Route

POST is a shorthand for RouterGroup.RouteFunc with POST as route method.

func (*RouterGroup) PUT

func (group *RouterGroup) PUT(path string, handler func(http.ResponseWriter, *http.Request) error) *Route

PUT is a shorthand for RouterGroup.RouteFunc with PUT as route method.

func (*RouterGroup) Route

func (group *RouterGroup) Route(method string, path string, handler Handler) *Route

Route registers a single route into the current group.

Note that the final route path will be the concatenation of all parent groups prefixes + the route path. The path follows the standard Go net/http http.ServeMux format ("[HOST]/[PATH]"), meaning that only a top level group route could have HOST as part of the prefix.

Returns the newly created route to allow attaching route-only Middlewares.

func (*RouterGroup) RouteFunc

func (group *RouterGroup) RouteFunc(method string, path string, handler func(http.ResponseWriter, *http.Request) error) *Route

RouteFunc registers a route in the current group using a function matching the http.HandlerFunc signature.

func (*RouterGroup) SEARCH

func (group *RouterGroup) SEARCH(path string, handler func(http.ResponseWriter, *http.Request) error) *Route

SEARCH is a shorthand for RouterGroup.RouteFunc with SEARCH as route method.

func (*RouterGroup) TRACE

func (group *RouterGroup) TRACE(path string, handler func(http.ResponseWriter, *http.Request) error) *Route

TRACE is a shorthand for RouterGroup.RouteFunc with TRACE as route method.

func (*RouterGroup) Use

func (group *RouterGroup) Use(middlewares ...*Middleware[Handler]) *RouterGroup

Use registers one or multiple middleware handlers to the current group.

func (*RouterGroup) UseFunc

func (group *RouterGroup) UseFunc(middlewareFuncs ...func(Handler) Handler) *RouterGroup

UseFunc registers one or multiple middleware functions to the current group.

The registered middleware functions are "anonymous" and with default priority, aka. executes in the order they were registered.

If you need to specify a named middleware or middleware with custom exec priority, use RouterGroup.Use method.

type Sizer

type Sizer interface {
	Size() int64
}

func ResponseSizer

func ResponseSizer(w http.ResponseWriter) Sizer

type StatusCoder

type StatusCoder interface {
	StatusCode() int
}

func ResponseStatusCoder

func ResponseStatusCoder(w http.ResponseWriter) StatusCoder

type TrustedProxy

type TrustedProxy struct {
	// Headers is a list of explicit trusted header(s) to check.
	Headers []string `env:"HEADERS" json:"headers,omitempty" yaml:"headers,omitempty"`

	// UseLeftmostIP specifies to use the left-mostish IP from the trusted headers.
	//
	// Note that this could be insecure when used with X-Forwarded-For header
	// because some proxies like AWS ELB allow users to prepend their own header value
	// before appending the trusted ones.
	UseLeftmostIP bool `env:"USE_LEFTMOST_IP" json:"useLeftmostIP,omitempty" yaml:"useLeftmostIP,omitempty"`
}

TrustedProxy defines the trusted proxy settings. https://developers.cloudflare.com/fundamentals/reference/http-headers/#x-forwarded-for

Directories

Path Synopsis
adapter module
server module
session module

Jump to

Keyboard shortcuts

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