zinc

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Aug 4, 2026 License: MIT Imports: 33 Imported by: 0

README

Zinc

Release Go Reference Go Report Card License

A high-performance application layer for net/http.

Zinc adds fast routing, request binding, structured errors, response helpers, and production middleware to Go's standard HTTP stack. It does not replace that stack: a Zinc app is an http.Handler, and handlers always have access to the original request and response writer.

Documentation · Quick start · Middleware · API reference

Install

go get github.com/0mjs/zinc

Zinc requires Go 1.25 or newer.

Start a server

package main

import (
	"log"

	"github.com/0mjs/zinc"
)

func main() {
	app := zinc.New()

	app.Get("/", func(c *zinc.Context) error {
		return c.String("Hello from Zinc!")
	})

	log.Fatal(app.Listen(":8080"))
}

Run it, then make a request:

curl http://localhost:8080
Hello from Zinc!

Why Zinc?

The standard library has excellent HTTP contracts. Building an application directly on top of them still leaves a fair amount of repetitive work.

Zinc fills that gap without introducing another HTTP engine:

  • concise handlers with central error handling
  • fast routing, route groups, and middleware chains
  • binding and validation for request data
  • helpers for JSON, files, streams, templates, and redirects
  • direct access to http.Request, http.ResponseWriter, http.Handler, and http.Server

The aim is simple application code that still behaves like ordinary Go.

Still net/http

App implements http.Handler, so you can use it with a server you own:

server := &http.Server{
	Addr:              ":8080",
	Handler:           app,
	ReadHeaderTimeout: 5 * time.Second,
}

log.Fatal(server.ListenAndServe())

Standard handlers can own individual routes:

app.HandleHTTP("GET /metrics", promhttp.Handler())

app.HandleHTTP("GET /users/{id}", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, r.PathValue("id"))
}))

Standard middleware can wrap the entire application:

app.UseHTTP(requestTracing, authenticateRequest)

Handlers that own a whole subtree can be mounted:

app.Mount("/debug", http.DefaultServeMux)

Inside a Zinc handler, the standard request and writer are available when you need them:

app.Get("/request", func(c *zinc.Context) error {
	r := c.Request()
	w := c.Writer()

	w.Header().Set("X-Method", r.Method)
	return c.String("ok")
})

This keeps standard middleware, observability tools, test helpers, server configuration, cancellation, and request-scoped values usable.

Routing and middleware

Routes can be grouped and middleware can be applied to the whole app or one part of it:

Every route method accepts typed zinc.HandlerFunc handlers. Zinc does not use untyped response shorthands.

app.Use(middleware.RequestID())
app.Use(middleware.Recover())

api := app.Group("/api", requireAuth)

api.Get("/health", func(c *zinc.Context) error {
	return c.JSON(zinc.Map{"status": "ok"})
})

Routes declared in source fail fast if a pattern is invalid or conflicts with another route. Use app.TryHandle(spec) when route definitions come from configuration or plugins and need ordinary error handling.

Zinc includes middleware for common concerns such as recovery, request IDs, logging, CORS, compression, authentication, rate limiting, security headers, metrics, and tracing. See the middleware documentation for configuration and examples.

Binding and errors

Handlers return errors. Zinc sends successful responses through the context and passes failures to one central error handler.

type CreateUser struct {
	Name  string `json:"name"`
	Email string `json:"email"`
}

app.Post("/users", func(c *zinc.Context) error {
	var input CreateUser
	if err := c.Bind().JSON(&input); err != nil {
		return zinc.ErrBadRequest.WithMessage("invalid request").WithCause(err)
	}

	return c.Status(http.StatusCreated).JSON(input)
})

*zinc.Context is pooled and lives only for the active request. Extract values before starting background work; use c.Request().Context() when that work should share request cancellation, or deliberately use context.WithoutCancel when it must not.

Binding supports path, query, header, JSON, XML, YAML, TOML, form, and multipart input. The binder, validator, JSON codec, renderer, and error handler can all be replaced through zinc.Config.

Performance

Zinc keeps benchmarks in the repository so performance claims can be checked against the code that produced them.

In the latest Apple M1 Pro comparison, Zinc recorded the lowest latency in 62 of 77 comparable rows against Gin, Echo, and Chi. It was fastest or within 2% of the fastest result in 63 rows. Primary static, parameter, and not-found dispatch paths retained zero request-time allocations.

Results vary by workload and machine. See the full benchmark report for the environment, command, scorecard, and complete results.

Packages

Package Purpose
github.com/0mjs/zinc Application, router, context, binding, responses, rendering, and static files
github.com/0mjs/zinc/middleware First-party HTTP middleware
github.com/0mjs/zinc/jobs Optional in-memory jobs, retries, delayed work, and schedules

The jobs package is independent of the HTTP application. Applications that do not import it do not use it.

Project status

Zinc is pre-1.0. Pin a release and read the Zinc 0.2 migration guide and release notes when upgrading.

Bug reports and focused proposals are welcome in GitHub Issues. See CONTRIBUTING.md before opening a pull request.

License

MIT

Documentation

Index

Constants

View Source
const (
	HeaderAuthorization                   = "Authorization"
	HeaderProxyAuthenticate               = "Proxy-Authenticate"
	HeaderProxyAuthorization              = "Proxy-Authorization"
	HeaderWWWAuthenticate                 = "WWW-Authenticate"
	HeaderAge                             = "Age"
	HeaderCacheControl                    = "Cache-Control"
	HeaderClearSiteData                   = "Clear-Site-Data"
	HeaderExpires                         = "Expires"
	HeaderPragma                          = "Pragma"
	HeaderWarning                         = "Warning"
	HeaderAcceptCH                        = "Accept-CH"
	HeaderAcceptCHLifetime                = "Accept-CH-Lifetime"
	HeaderContentDPR                      = "Content-DPR"
	HeaderDPR                             = "DPR"
	HeaderEarlyData                       = "Early-Data"
	HeaderSaveData                        = "Save-Data"
	HeaderViewportWidth                   = "Viewport-Width"
	HeaderWidth                           = "Width"
	HeaderETag                            = "ETag"
	HeaderIfMatch                         = "If-Match"
	HeaderIfModifiedSince                 = "If-Modified-Since"
	HeaderIfNoneMatch                     = "If-None-Match"
	HeaderIfUnmodifiedSince               = "If-Unmodified-Since"
	HeaderLastModified                    = "Last-Modified"
	HeaderVary                            = "Vary"
	HeaderConnection                      = "Connection"
	HeaderKeepAlive                       = "Keep-Alive"
	HeaderAccept                          = "Accept"
	HeaderAcceptCharset                   = "Accept-Charset"
	HeaderAcceptEncoding                  = "Accept-Encoding"
	HeaderAcceptLanguage                  = "Accept-Language"
	HeaderCookie                          = "Cookie"
	HeaderExpect                          = "Expect"
	HeaderMaxForwards                     = "Max-Forwards"
	HeaderSetCookie                       = "Set-Cookie"
	HeaderSecFetchSite                    = "Sec-Fetch-Site"
	HeaderAccessControlAllowCredentials   = "Access-Control-Allow-Credentials"
	HeaderAccessControlAllowHeaders       = "Access-Control-Allow-Headers"
	HeaderAccessControlAllowMethods       = "Access-Control-Allow-Methods"
	HeaderAccessControlAllowOrigin        = "Access-Control-Allow-Origin"
	HeaderAccessControlExposeHeaders      = "Access-Control-Expose-Headers"
	HeaderAccessControlMaxAge             = "Access-Control-Max-Age"
	HeaderAccessControlRequestHeaders     = "Access-Control-Request-Headers"
	HeaderAccessControlRequestMethod      = "Access-Control-Request-Method"
	HeaderOrigin                          = "Origin"
	HeaderTimingAllowOrigin               = "Timing-Allow-Origin"
	HeaderXPermittedCrossDomainPolicies   = "X-Permitted-Cross-Domain-Policies"
	HeaderDNT                             = "DNT"
	HeaderTk                              = "Tk"
	HeaderContentDisposition              = "Content-Disposition"
	HeaderContentEncoding                 = "Content-Encoding"
	HeaderContentLanguage                 = "Content-Language"
	HeaderContentLength                   = "Content-Length"
	HeaderContentLocation                 = "Content-Location"
	HeaderContentType                     = "Content-Type"
	HeaderForwarded                       = "Forwarded"
	HeaderVia                             = "Via"
	HeaderXForwardedFor                   = "X-Forwarded-For"
	HeaderXForwardedHost                  = "X-Forwarded-Host"
	HeaderXForwardedProto                 = "X-Forwarded-Proto"
	HeaderXForwardedProtocol              = "X-Forwarded-Protocol"
	HeaderXForwardedSsl                   = "X-Forwarded-Ssl"
	HeaderXUrlScheme                      = "X-Url-Scheme"
	HeaderLocation                        = "Location"
	HeaderFrom                            = "From"
	HeaderHost                            = "Host"
	HeaderReferer                         = "Referer"
	HeaderReferrerPolicy                  = "Referrer-Policy"
	HeaderUserAgent                       = "User-Agent"
	HeaderAllow                           = "Allow"
	HeaderServer                          = "Server"
	HeaderAcceptRanges                    = "Accept-Ranges"
	HeaderContentRange                    = "Content-Range"
	HeaderIfRange                         = "If-Range"
	HeaderRange                           = "Range"
	HeaderContentSecurityPolicy           = "Content-Security-Policy"
	HeaderContentSecurityPolicyReportOnly = "Content-Security-Policy-Report-Only"
	HeaderCrossOriginResourcePolicy       = "Cross-Origin-Resource-Policy"
	HeaderExpectCT                        = "Expect-CT"
	HeaderFeaturePolicy                   = "Feature-Policy"
	HeaderPublicKeyPins                   = "Public-Key-Pins"
	HeaderPublicKeyPinsReportOnly         = "Public-Key-Pins-Report-Only"
	HeaderStrictTransportSecurity         = "Strict-Transport-Security"
	HeaderUpgradeInsecureRequests         = "Upgrade-Insecure-Requests"
	HeaderXContentTypeOptions             = "X-Content-Type-Options"
	HeaderXDownloadOptions                = "X-Download-Options"
	HeaderXFrameOptions                   = "X-Frame-Options"
	HeaderXPoweredBy                      = "X-Powered-By"
	HeaderXCSRFToken                      = "X-CSRF-Token"
	HeaderXXSSProtection                  = "X-XSS-Protection"
	HeaderLastEventID                     = "Last-Event-ID"
	HeaderNEL                             = "NEL"
	HeaderPingFrom                        = "Ping-From"
	HeaderPingTo                          = "Ping-To"
	HeaderReportTo                        = "Report-To"
	HeaderTE                              = "TE"
	HeaderTrailer                         = "Trailer"
	HeaderTransferEncoding                = "Transfer-Encoding"
	HeaderSecWebSocketAccept              = "Sec-WebSocket-Accept"
	HeaderSecWebSocketExtensions          = "Sec-WebSocket-Extensions"
	HeaderSecWebSocketKey                 = "Sec-WebSocket-Key"
	HeaderSecWebSocketProtocol            = "Sec-WebSocket-Protocol"
	HeaderSecWebSocketVersion             = "Sec-WebSocket-Version"
	HeaderAcceptPatch                     = "Accept-Patch"
	HeaderAcceptPushPolicy                = "Accept-Push-Policy"
	HeaderAcceptSignature                 = "Accept-Signature"
	HeaderAltSvc                          = "Alt-Svc"
	HeaderDate                            = "Date"
	HeaderIndex                           = "Index"
	HeaderLargeAllocation                 = "Large-Allocation"
	HeaderLink                            = "Link"
	HeaderPushPolicy                      = "Push-Policy"
	HeaderRetryAfter                      = "Retry-After"
	HeaderServerTiming                    = "Server-Timing"
	HeaderSignature                       = "Signature"
	HeaderSignedHeaders                   = "Signed-Headers"
	HeaderSourceMap                       = "SourceMap"
	HeaderUpgrade                         = "Upgrade"
	HeaderXDNSPrefetchControl             = "X-DNS-Prefetch-Control"
	HeaderXPingback                       = "X-Pingback"
	HeaderXRequestID                      = "X-Request-ID"
	HeaderXRequestedWith                  = "X-Requested-With"
	HeaderXRobotsTag                      = "X-Robots-Tag"
	HeaderXUACompatible                   = "X-UA-Compatible"
)
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

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
	StatusNonAuthoritativeInformation   = 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
	StatusTooEarly                      = 425 // RFC 8470, 5.2.
	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

View Source
const DefaultListenAddr = ":8080"
View Source
const Version = "0.2.1"

Version is the current version of Zinc. This should be updated for each release.

Variables

View Source
var (
	ErrBadRequest                    = NewError(StatusBadRequest)
	ErrUnauthorized                  = NewError(StatusUnauthorized)
	ErrPaymentRequired               = NewError(StatusPaymentRequired)
	ErrForbidden                     = NewError(StatusForbidden)
	ErrNotFound                      = NewError(StatusNotFound)
	ErrMethodNotAllowed              = NewError(StatusMethodNotAllowed)
	ErrNotAcceptable                 = NewError(StatusNotAcceptable)
	ErrProxyAuthRequired             = NewError(StatusProxyAuthRequired)
	ErrRequestTimeout                = NewError(StatusRequestTimeout)
	ErrConflict                      = NewError(StatusConflict)
	ErrGone                          = NewError(StatusGone)
	ErrLengthRequired                = NewError(StatusLengthRequired)
	ErrPreconditionFailed            = NewError(StatusPreconditionFailed)
	ErrRequestEntityTooLarge         = NewError(StatusRequestEntityTooLarge)
	ErrRequestURITooLong             = NewError(StatusRequestURITooLong)
	ErrUnsupportedMediaType          = NewError(StatusUnsupportedMediaType)
	ErrRequestedRangeNotSatisfiable  = NewError(StatusRequestedRangeNotSatisfiable)
	ErrExpectationFailed             = NewError(StatusExpectationFailed)
	ErrTeapot                        = NewError(StatusTeapot)
	ErrMisdirectedRequest            = NewError(StatusMisdirectedRequest)
	ErrUnprocessableEntity           = NewError(StatusUnprocessableEntity)
	ErrLocked                        = NewError(StatusLocked)
	ErrFailedDependency              = NewError(StatusFailedDependency)
	ErrTooEarly                      = NewError(StatusTooEarly)
	ErrUpgradeRequired               = NewError(StatusUpgradeRequired)
	ErrPreconditionRequired          = NewError(StatusPreconditionRequired)
	ErrTooManyRequests               = NewError(StatusTooManyRequests)
	ErrRequestHeaderFieldsTooLarge   = NewError(StatusRequestHeaderFieldsTooLarge)
	ErrUnavailableForLegalReasons    = NewError(StatusUnavailableForLegalReasons)
	ErrInternalServerError           = NewError(StatusInternalServerError)
	ErrNotImplemented                = NewError(StatusNotImplemented)
	ErrBadGateway                    = NewError(StatusBadGateway)
	ErrServiceUnavailable            = NewError(StatusServiceUnavailable)
	ErrGatewayTimeout                = NewError(StatusGatewayTimeout)
	ErrHTTPVersionNotSupported       = NewError(StatusHTTPVersionNotSupported)
	ErrVariantAlsoNegotiates         = NewError(StatusVariantAlsoNegotiates)
	ErrInsufficientStorage           = NewError(StatusInsufficientStorage)
	ErrLoopDetected                  = NewError(StatusLoopDetected)
	ErrNotExtended                   = NewError(StatusNotExtended)
	ErrNetworkAuthenticationRequired = NewError(StatusNetworkAuthenticationRequired)
)
View Source
var (
	ErrTemplateEngineNotConfigured = errors.New("template engine is not configured")
	ErrTemplateNameRequired        = errors.New("template name is required")
	ErrTemplateNotFound            = errors.New("template not found")
)
View Source
var DefaultConfig = Config{
	ServerHeader:           "",
	CaseSensitive:          false,
	StrictRouting:          false,
	AutoHead:               true,
	AutoOptions:            true,
	HandleMethodNotAllowed: true,
	BodyLimit:              4 << 20,
	ReadTimeout:            5 * time.Second,
	WriteTimeout:           10 * time.Second,
	IdleTimeout:            120 * time.Second,
	ProxyHeader:            "X-Forwarded-For",
	TrustedProxies:         nil,
	RouteCacheSize:         1000,
}

DefaultConfig is the baseline Zinc configuration.

View Source
var ErrResponseAlreadySent = errors.New("response already sent")

Functions

func GetVersion

func GetVersion() string

GetVersion returns the current version of Zinc.

func GetVersionHeader

func GetVersionHeader() string

GetVersionHeader returns the full version string for HTTP headers.

Types

type App

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

func New

func New() *App

func NewWithConfig

func NewWithConfig(cfg Config) *App

func (*App) AcquireContext added in v0.1.0

func (a *App) AcquireContext(w http.ResponseWriter, r *http.Request) *Context

func (*App) Add

func (a *App) Add(method, path string, handlers ...HandlerFunc)

func (*App) All

func (a *App) All(path string, handlers ...HandlerFunc)

func (*App) Any

func (a *App) Any(path string, handlers ...HandlerFunc)

func (*App) Connect

func (a *App) Connect(path string, handlers ...HandlerFunc)

func (*App) Delete

func (a *App) Delete(path string, handlers ...HandlerFunc)

func (*App) File

func (a *App) File(path, file string) error

func (*App) FileFS

func (a *App) FileFS(path, file string, filesystem fs.FS) error

func (*App) FindRoute added in v0.1.0

func (a *App) FindRoute(method, path string) (RouteInfo, bool)

func (*App) Get

func (a *App) Get(path string, handlers ...HandlerFunc)

func (*App) Group

func (a *App) Group(prefix string, handlers ...HandlerFunc) *Group

func (*App) Handle added in v0.1.0

func (a *App) Handle(spec RouteSpec)

Handle registers a source-defined route and panics when its declaration is invalid.

func (*App) HandleHTTP added in v0.2.0

func (a *App) HandleHTTP(pattern string, handler http.Handler)

HandleHTTP registers a standard net/http handler using a "METHOD /path" pattern, such as "GET /metrics". Matched parameters are available through http.Request.PathValue inside the standard handler.

func (*App) Handler

func (a *App) Handler() http.Handler

func (*App) Head

func (a *App) Head(path string, handlers ...HandlerFunc)

func (*App) Listen

func (a *App) Listen(addr ...string) error

Listen starts the app on addr, defaulting to :8080 when addr is omitted.

func (*App) ListenTLS

func (a *App) ListenTLS(addr, certFile, keyFile string) error

func (*App) Match

func (a *App) Match(methods []string, path string, handlers ...HandlerFunc)

func (*App) MethodNotAllowed

func (a *App) MethodNotAllowed(handler HandlerFunc)

func (*App) Mount

func (a *App) Mount(prefix string, h http.Handler)

func (*App) NotFound

func (a *App) NotFound(handler HandlerFunc)

func (*App) Options

func (a *App) Options(path string, handlers ...HandlerFunc)

func (*App) Patch

func (a *App) Patch(path string, handlers ...HandlerFunc)

func (*App) Post

func (a *App) Post(path string, handlers ...HandlerFunc)

func (*App) Put

func (a *App) Put(path string, handlers ...HandlerFunc)

func (*App) ReleaseContext added in v0.1.0

func (a *App) ReleaseContext(c *Context)

func (*App) Route

func (a *App) Route(prefix string, fn func(*Group), handlers ...HandlerFunc) *Group

func (*App) RouteByName added in v0.1.0

func (a *App) RouteByName(name string) (RouteInfo, bool)

func (*App) RouteNotFound added in v0.1.0

func (a *App) RouteNotFound(path string, handlers ...HandlerFunc)

func (*App) Routes

func (a *App) Routes() []RouteInfo

func (*App) RoutesByMethod added in v0.1.0

func (a *App) RoutesByMethod(method string) []RouteInfo

func (*App) RoutesByPrefix added in v0.1.0

func (a *App) RoutesByPrefix(prefix string) []RouteInfo

func (*App) Serve

func (a *App) Serve(ln net.Listener) error

func (*App) ServeHTTP

func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (*App) Shutdown

func (a *App) Shutdown(ctx context.Context) error

func (*App) Static

func (a *App) Static(prefix, root string, opts ...StaticOption) error

func (*App) StaticFS

func (a *App) StaticFS(prefix string, filesystem fs.FS, opts ...StaticOption) error

func (*App) Trace

func (a *App) Trace(path string, handlers ...HandlerFunc)

func (*App) TryHandle added in v0.2.0

func (a *App) TryHandle(spec RouteSpec) error

TryHandle registers a route whose declaration came from dynamic input.

func (*App) URL added in v0.1.0

func (a *App) URL(name string, params ...string) (string, error)

func (*App) Use

func (a *App) Use(handlers ...HandlerFunc)

func (*App) UseHTTP added in v0.2.0

func (a *App) UseHTTP(middleware ...HTTPMiddleware)

UseHTTP wraps the whole application in standard net/http middleware. Middleware runs in registration order, with the first middleware outermost.

func (*App) UsePrefix

func (a *App) UsePrefix(prefix string, handlers ...HandlerFunc)

type Bind added in v0.1.1

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

func (*Bind) All added in v0.1.1

func (b *Bind) All(v any) error

func (*Bind) Body added in v0.1.1

func (b *Bind) Body(v any) error

func (*Bind) Form added in v0.1.1

func (b *Bind) Form(v any) error

func (*Bind) Header added in v0.1.1

func (b *Bind) Header(v any) error

func (*Bind) JSON added in v0.1.1

func (b *Bind) JSON(v any) error

func (*Bind) Path added in v0.1.1

func (b *Bind) Path(v any) error

func (*Bind) Query added in v0.1.1

func (b *Bind) Query(v any) error

func (*Bind) TOML added in v0.1.1

func (b *Bind) TOML(v any) error

func (*Bind) Text added in v0.1.1

func (b *Bind) Text(v any) error

func (*Bind) XML added in v0.1.1

func (b *Bind) XML(v any) error

func (*Bind) YAML added in v0.1.1

func (b *Bind) YAML(v any) error

type BindError added in v0.1.0

type BindError struct {
	Source string
	Field  string
	Err    error
}

func (*BindError) Error added in v0.1.0

func (e *BindError) Error() string

func (*BindError) Unwrap added in v0.1.0

func (e *BindError) Unwrap() error

type Config

type Config struct {
	ServerHeader string

	CaseSensitive          bool
	StrictRouting          bool
	AutoHead               bool
	AutoOptions            bool
	HandleMethodNotAllowed bool

	BodyLimit    int64
	ReadTimeout  time.Duration
	WriteTimeout time.Duration
	IdleTimeout  time.Duration

	ProxyHeader    string
	TrustedProxies []string

	RequestBinder RequestBinder
	Validator     Validator
	Renderer      Renderer
	JSONCodec     JSONCodec
	ErrorHandler  ErrorHandler

	RouteCacheSize int
}

Config holds the application and server configuration.

type Context

type Context struct {
	PathParams params
	// contains filtered or unexported fields
}

func NewContext

func NewContext(w http.ResponseWriter, r *http.Request) *Context

func (*Context) AbortWithJSON added in v0.1.0

func (c *Context) AbortWithJSON(code int, v any) error

func (*Context) AbortWithStatus added in v0.1.0

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

func (*Context) Accepts added in v0.1.2

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

func (*Context) AppendHeader

func (c *Context) AppendHeader(key string, values ...string) *Context

func (*Context) Attachment

func (c *Context) Attachment(filePath string, name ...string) error

func (*Context) Bind

func (c *Context) Bind() *Bind

func (*Context) Blob added in v0.1.2

func (c *Context) Blob(status int, contentType string, b []byte) error

func (*Context) BodyBytes

func (c *Context) BodyBytes() ([]byte, error)

func (*Context) BodyString

func (c *Context) BodyString() (string, error)

func (*Context) ClearCookie

func (c *Context) ClearCookie(names ...string)

func (*Context) ContentType added in v0.1.2

func (c *Context) ContentType() string

func (*Context) Context

func (c *Context) Context() stdctx.Context

func (*Context) Cookie

func (c *Context) Cookie(name string) (*http.Cookie, error)

func (*Context) Cookies

func (c *Context) Cookies() []*http.Cookie

func (*Context) Data

func (c *Context) Data(contentType string, b []byte) error

func (*Context) Download

func (c *Context) Download(filePath string, name ...string) error

func (*Context) Error added in v0.0.73

func (c *Context) Error(err error)

func (*Context) Fail added in v0.1.0

func (c *Context) Fail(err error) error

func (*Context) File

func (c *Context) File(filePath string) error

func (*Context) FileFS

func (c *Context) FileFS(filePath string, filesystem fs.FS) error

func (*Context) FormFile

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

func (*Context) FormFiles

func (c *Context) FormFiles(name string) ([]*multipart.FileHeader, error)

func (*Context) FormValue

func (c *Context) FormValue(name string) string

func (*Context) FullPath

func (c *Context) FullPath() string

func (*Context) Get

func (c *Context) Get(key any) (any, bool)

func (*Context) GetBool added in v0.1.2

func (c *Context) GetBool(key any) bool

func (*Context) GetFloat64 added in v0.1.2

func (c *Context) GetFloat64(key any) float64

func (*Context) GetHeader

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

func (*Context) GetInt added in v0.1.2

func (c *Context) GetInt(key any) int

func (*Context) GetInt64 added in v0.1.2

func (c *Context) GetInt64(key any) int64

func (*Context) GetString added in v0.1.2

func (c *Context) GetString(key any) string

func (*Context) GetStringMap added in v0.1.2

func (c *Context) GetStringMap(key any) map[string]any

func (*Context) GetStringMapString added in v0.1.2

func (c *Context) GetStringMapString(key any) map[string]string

func (*Context) GetStringMapStringSlice added in v0.1.2

func (c *Context) GetStringMapStringSlice(key any) map[string][]string

func (*Context) GetStringSlice added in v0.1.2

func (c *Context) GetStringSlice(key any) []string

func (*Context) HTML

func (c *Context) HTML(data string) error

func (*Context) HTMLBlob added in v0.1.2

func (c *Context) HTMLBlob(status int, b []byte) error

func (*Context) IP

func (c *Context) IP() string

func (*Context) IPs

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

func (*Context) Inline added in v0.1.2

func (c *Context) Inline(filePath string, name ...string) error

func (*Context) IsPreflight

func (c *Context) IsPreflight() bool

func (*Context) IsWebSocket

func (c *Context) IsWebSocket() bool

func (*Context) JSON

func (c *Context) JSON(v any) error

func (*Context) JSONBlob added in v0.1.2

func (c *Context) JSONBlob(status int, b []byte) error

func (*Context) JSONPretty

func (c *Context) JSONPretty(v any, indent string) error

func (*Context) LastError added in v0.0.73

func (c *Context) LastError() error

func (*Context) Location

func (c *Context) Location(location string) *Context

func (*Context) Method

func (c *Context) Method() string

func (*Context) MultipartForm

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

func (*Context) MustGet

func (c *Context) MustGet(key any) any

func (*Context) Negotiate added in v0.1.2

func (c *Context) Negotiate(status int, offers map[string]any) error

func (*Context) Next

func (c *Context) Next() error

func (*Context) NoContent

func (c *Context) NoContent() error

func (*Context) OriginalURL

func (c *Context) OriginalURL() string

func (*Context) Param

func (c *Context) Param(name string) string

func (*Context) ParamOr

func (c *Context) ParamOr(name, fallback string) string

func (*Context) Path

func (c *Context) Path() string

func (*Context) PostForm added in v0.1.2

func (c *Context) PostForm(name string) string

func (*Context) PostFormArray added in v0.1.2

func (c *Context) PostFormArray(name string) []string

func (*Context) PostFormMap added in v0.1.2

func (c *Context) PostFormMap(name string) map[string]string

func (*Context) PostFormOr added in v0.1.2

func (c *Context) PostFormOr(name, fallback string) string

func (*Context) Query

func (c *Context) Query(name string) string

func (*Context) QueryArray added in v0.1.2

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

func (*Context) QueryMap added in v0.1.2

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

func (*Context) QueryOr

func (c *Context) QueryOr(name, fallback string) string

func (*Context) QueryValues

func (c *Context) QueryValues() url.Values

func (*Context) Redirect

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

func (*Context) RemoteIP

func (c *Context) RemoteIP() string

func (*Context) Render

func (c *Context) Render(name string, data any) error

func (*Context) Request

func (c *Context) Request() *http.Request

func (*Context) RequestID

func (c *Context) RequestID() string

func (*Context) Route

func (c *Context) Route() RouteInfo

func (*Context) SSE added in v0.0.71

func (c *Context) SSE(event SSEvent) error

func (*Context) SaveFile

func (c *Context) SaveFile(file *multipart.FileHeader, dst string) error

func (*Context) Scheme

func (c *Context) Scheme() string

func (*Context) Secure

func (c *Context) Secure() bool

func (*Context) Send

func (c *Context) Send(data any) error

func (*Context) Set

func (c *Context) Set(key any, value any)

func (*Context) SetContext

func (c *Context) SetContext(ctx stdctx.Context)

func (*Context) SetCookie

func (c *Context) SetCookie(cookie *http.Cookie)

func (*Context) SetHeader

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

func (*Context) SetPath

func (c *Context) SetPath(path string)

func (*Context) SetRequest

func (c *Context) SetRequest(r *http.Request)

func (*Context) SetSameSite added in v0.1.2

func (c *Context) SetSameSite(mode http.SameSite) *Context

func (*Context) SetWriter

func (c *Context) SetWriter(w http.ResponseWriter)

func (*Context) Status

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

func (*Context) Stream

func (c *Context) Stream(contentType string, r io.Reader) error

func (*Context) String

func (c *Context) String(data string) error

func (*Context) TOML added in v0.1.0

func (c *Context) TOML(v any) error

func (*Context) Type

func (c *Context) Type(ext string) *Context

func (*Context) Validate

func (c *Context) Validate(v any) error

func (*Context) Vary

func (c *Context) Vary(fields ...string) *Context

func (*Context) Writer

func (c *Context) Writer() http.ResponseWriter

func (*Context) XML

func (c *Context) XML(v any) error

func (*Context) XMLBlob added in v0.1.2

func (c *Context) XMLBlob(status int, b []byte) error

func (*Context) YAML added in v0.1.0

func (c *Context) YAML(v any) error

type ErrorHandler

type ErrorHandler func(*Context, error)

ErrorHandler handles an error returned from a Zinc handler.

type Group

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

func NewGroup

func NewGroup(app *App, prefix string, handlers ...HandlerFunc) *Group

func (*Group) Add

func (g *Group) Add(method, routePath string, handlers ...HandlerFunc)

func (*Group) All

func (g *Group) All(path string, handlers ...HandlerFunc)

func (*Group) Any

func (g *Group) Any(path string, handlers ...HandlerFunc)

func (*Group) Connect

func (g *Group) Connect(path string, handlers ...HandlerFunc)

func (*Group) Delete

func (g *Group) Delete(path string, handlers ...HandlerFunc)

func (*Group) File

func (g *Group) File(routePath, file string) error

func (*Group) FileFS

func (g *Group) FileFS(routePath, file string, filesystem fs.FS) error

func (*Group) Get

func (g *Group) Get(path string, handlers ...HandlerFunc)

func (*Group) Group

func (g *Group) Group(prefix string, handlers ...HandlerFunc) *Group

func (*Group) Handle added in v0.1.0

func (g *Group) Handle(spec RouteSpec)

Handle registers a source-defined route below the group prefix and panics when its declaration is invalid.

func (*Group) HandleHTTP added in v0.2.0

func (g *Group) HandleHTTP(pattern string, handler http.Handler)

HandleHTTP registers a standard net/http handler below the group prefix.

func (*Group) Head

func (g *Group) Head(path string, handlers ...HandlerFunc)

func (*Group) Match

func (g *Group) Match(methods []string, routePath string, handlers ...HandlerFunc)

func (*Group) Mount

func (g *Group) Mount(prefix string, h http.Handler)

func (*Group) Options

func (g *Group) Options(path string, handlers ...HandlerFunc)

func (*Group) Patch

func (g *Group) Patch(path string, handlers ...HandlerFunc)

func (*Group) Post

func (g *Group) Post(path string, handlers ...HandlerFunc)

func (*Group) Put

func (g *Group) Put(path string, handlers ...HandlerFunc)

func (*Group) Route

func (g *Group) Route(prefix string, fn func(*Group), handlers ...HandlerFunc) *Group

func (*Group) RouteNotFound added in v0.1.0

func (g *Group) RouteNotFound(routePath string, handlers ...HandlerFunc)

func (*Group) Static

func (g *Group) Static(prefix, root string, opts ...StaticOption) error

func (*Group) StaticFS

func (g *Group) StaticFS(prefix string, filesystem fs.FS, opts ...StaticOption) error

func (*Group) Trace

func (g *Group) Trace(path string, handlers ...HandlerFunc)

func (*Group) TryHandle added in v0.2.0

func (g *Group) TryHandle(spec RouteSpec) error

TryHandle registers a dynamically defined route below the group prefix.

func (*Group) Use

func (g *Group) Use(handlers ...HandlerFunc) *Group

type HTTPError

type HTTPError struct {
	Code    int
	Message string
	Cause   error
	Meta    Map
	Headers http.Header
}

HTTPError represents an HTTP error with a status code and optional message.

func NewError

func NewError(code int) *HTTPError

func (*HTTPError) Error

func (e *HTTPError) Error() string

func (*HTTPError) Unwrap added in v0.1.0

func (e *HTTPError) Unwrap() error

func (*HTTPError) WithCause added in v0.1.0

func (e *HTTPError) WithCause(cause error) *HTTPError

func (*HTTPError) WithHeader added in v0.1.0

func (e *HTTPError) WithHeader(key, value string) *HTTPError

func (*HTTPError) WithMessage

func (e *HTTPError) WithMessage(message string) *HTTPError

func (*HTTPError) WithMeta added in v0.1.0

func (e *HTTPError) WithMeta(key string, value any) *HTTPError

type HTTPMiddleware added in v0.2.0

type HTTPMiddleware func(http.Handler) http.Handler

HTTPMiddleware is the standard net/http middleware shape.

type HandlerFunc

type HandlerFunc func(*Context) error

func Wrap

func Wrap(h http.Handler) HandlerFunc

Wrap adapts a standard net/http handler to HandlerFunc. Matched parameters are populated into http.Request.PathValue immediately before it runs.

func WrapFunc

func WrapFunc(fn http.HandlerFunc) HandlerFunc

type JSONCodec

type JSONCodec interface {
	Encode(w io.Writer, v any, indent string) error
	Decode(r io.Reader, v any) error
}

type Map

type Map map[string]any

type Middleware

type Middleware = HandlerFunc

type Renderer

type Renderer interface {
	Render(w io.Writer, name string, data any, c *Context) error
}

type RequestBinder added in v0.1.1

type RequestBinder interface {
	Bind(*Context, any) error
	BindBody(*Context, any) error
	BindQuery(*Context, any) error
	BindForm(*Context, any) error
	BindHeader(*Context, any) error
	BindPath(*Context, any) error
}

type ResponseWriter added in v0.1.2

type ResponseWriter interface {
	http.ResponseWriter
	Status() int
	BytesWritten() int
	Written() bool
}

func WrapResponseWriter added in v0.1.2

func WrapResponseWriter(w http.ResponseWriter) ResponseWriter

type Route

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

type RouteCache

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

func NewRouteCache

func NewRouteCache(size int) *RouteCache

type RouteHandler

type RouteHandler = HandlerFunc

type RouteHandlerMap

type RouteHandlerMap map[string]HandlerFunc

type RouteInfo

type RouteInfo struct {
	Name    string
	Method  string
	Path    string
	Params  []string
	Mounted bool
	Handler string
}

type RouteMap

type RouteMap map[string]map[string]*Route

type RouteSpec added in v0.1.0

type RouteSpec struct {
	Name    string
	Method  string
	Path    string
	Handler HandlerFunc
}

type Router

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

func (*Router) Add

func (r *Router) Add(method, path string, handlers ...HandlerFunc) error

func (*Router) AddNamed added in v0.1.0

func (r *Router) AddNamed(method, path, name string, handlers ...HandlerFunc) error

func (*Router) Find

func (r *Router) Find(method, path string) (HandlerFunc, *Context)

func (*Router) Routes

func (r *Router) Routes() []RouteInfo

type SSEvent added in v0.1.2

type SSEvent struct {
	Event string
	ID    string
	Retry time.Duration
	Data  any
}

type StaticConfig

type StaticConfig struct {
	Browse bool
	Index  string
}

type StaticOption

type StaticOption func(*StaticConfig)

func WithStaticBrowse

func WithStaticBrowse(browse bool) StaticOption

func WithStaticIndex

func WithStaticIndex(index string) StaticOption

type TemplateExecutor added in v0.0.76

type TemplateExecutor interface {
	ExecuteTemplate(w io.Writer, name string, data any) error
}

type TemplateRenderer added in v0.0.76

type TemplateRenderer struct {
	Engine TemplateExecutor
	// contains filtered or unexported fields
}

func NewHTMLTemplateRenderer added in v0.0.76

func NewHTMLTemplateRenderer(engine *htmltemplate.Template, opts ...TemplateRendererOption) *TemplateRenderer

func NewTemplateRenderer added in v0.0.76

func NewTemplateRenderer(engine TemplateExecutor, opts ...TemplateRendererOption) *TemplateRenderer

func NewTextTemplateRenderer added in v0.0.76

func NewTextTemplateRenderer(engine *texttemplate.Template, opts ...TemplateRendererOption) *TemplateRenderer

func (*TemplateRenderer) Render added in v0.0.76

func (r *TemplateRenderer) Render(w io.Writer, name string, data any, _ *Context) error

type TemplateRendererOption added in v0.0.76

type TemplateRendererOption func(*TemplateRenderer)

func WithTemplateSuffixes added in v0.0.76

func WithTemplateSuffixes(suffixes ...string) TemplateRendererOption

type Validator

type Validator interface {
	Validate(any) error
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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