Documentation
¶
Overview ¶
Example ¶
A route returns an error or writes a response. Zinc is an http.Handler, so app.Listen(":8080") serves it, or any net/http server can.
package main
import (
"fmt"
"net/http/httptest"
"strings"
"github.com/0mjs/zinc"
)
// do sends a request to app and prints the status and body, as a client
// would see them.
func do(app *zinc.App, method, target, body string) {
r := httptest.NewRequest(method, target, strings.NewReader(body))
if body != "" {
r.Header.Set("Content-Type", "application/json")
}
w := httptest.NewRecorder()
app.ServeHTTP(w, r)
fmt.Println(w.Code, strings.TrimSpace(w.Body.String()))
}
func main() {
app := zinc.New()
app.Get("/hello/{name}", func(c *zinc.Context) error {
return c.JSON(zinc.Map{"message": "Hello, " + c.Param("name") + "!"})
})
do(app, "GET", "/hello/ada", "")
}
Output: 200 {"message":"Hello, ada!"}
Index ¶
- Constants
- Variables
- func BuiltinRules() []string
- func DefaultErrorHandler(c *Context, err error)
- func Form[T any](c *Context, name string) (T, error)
- func FormOr[T any](c *Context, name string, fallback T) T
- func MustValue[T any](c *Context, key any) T
- func Param[T any](c *Context, name string) (T, error)
- func ProblemErrors(c *Context, err error)
- func Query[T any](c *Context, name string) (T, error)
- func QueryOr[T any](c *Context, name string, fallback T) T
- func StatusCode(err error) int
- func TextErrors(c *Context, err error)
- func Value[T any](c *Context, key any) (T, bool)
- type App
- func (a *App) AcquireContext(w http.ResponseWriter, r *http.Request) *Context
- func (a *App) Add(method, path string, handlers ...HandlerFunc) Route
- func (a *App) All(path string, handlers ...HandlerFunc)
- func (a *App) Close() error
- func (a *App) Connect(path string, handlers ...HandlerFunc) Route
- func (a *App) Delete(path string, handlers ...HandlerFunc) Route
- func (a *App) Document(docs ...MiddlewareDoc)
- func (a *App) File(path, file string) Route
- func (a *App) FileFS(path, file string, filesystem fs.FS) Route
- func (a *App) FindRoute(method, path string) (RouteInfo, bool)
- func (a *App) Get(path string, handlers ...HandlerFunc) Route
- func (a *App) Group(prefix string, handlers ...HandlerFunc) *Group
- func (a *App) HandleHTTP(pattern string, handler http.Handler) Route
- func (a *App) Handler() http.Handler
- func (a *App) Head(path string, handlers ...HandlerFunc) Route
- func (a *App) Listen(addr ...string) error
- func (a *App) ListenContext(ctx context.Context, addr string) error
- func (a *App) ListenTLS(addr, certFile, keyFile string) error
- func (a *App) Match(methods []string, path string, handlers ...HandlerFunc)
- func (a *App) MethodNotAllowed(handler HandlerFunc)
- func (a *App) Mount(prefix string, h http.Handler)
- func (a *App) NotFound(handler HandlerFunc)
- func (a *App) OpenAPI(path string, cfg OpenAPIConfig, middleware ...HandlerFunc) Route
- func (a *App) OpenAPISpec(cfg OpenAPIConfig) ([]byte, error)
- func (a *App) Options(path string, handlers ...HandlerFunc) Route
- func (a *App) Patch(path string, handlers ...HandlerFunc) Route
- func (a *App) Post(path string, handlers ...HandlerFunc) Route
- func (a *App) Put(path string, handlers ...HandlerFunc) Route
- func (a *App) ReleaseContext(c *Context)
- func (a *App) Route(prefix string, fn func(*Group), handlers ...HandlerFunc) *Group
- func (a *App) RouteByName(name string) (RouteInfo, bool)
- func (a *App) RouteNotFound(path string, handlers ...HandlerFunc)
- func (a *App) Routes() []RouteInfo
- func (a *App) Serve(ln net.Listener) error
- func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (a *App) Shutdown(ctx context.Context) error
- func (a *App) Static(prefix, root string, opts ...StaticOption)
- func (a *App) StaticFS(prefix string, filesystem fs.FS, opts ...StaticOption)
- func (a *App) Trace(path string, handlers ...HandlerFunc) Route
- func (a *App) TryHandle(spec RouteSpec) error
- func (a *App) URL(name string, params ...string) (string, error)
- func (a *App) Use(handlers ...HandlerFunc)
- func (a *App) UseHTTP(middleware ...HTTPMiddleware)
- func (a *App) UsePrefix(prefix string, handlers ...HandlerFunc)
- func (a *App) Validate() error
- type Bind
- func (b *Bind) All(v any) error
- func (b *Bind) Body(v any) error
- func (b *Bind) Cookie(v any) error
- func (b *Bind) Form(v any) error
- func (b *Bind) Header(v any) error
- func (b *Bind) JSON(v any) error
- func (b *Bind) Path(v any) error
- func (b *Bind) Query(v any) error
- func (b *Bind) Text(v any) error
- func (b *Bind) XML(v any) error
- type BindError
- type Bytes
- type Config
- type Context
- func (c *Context) Accepts(types ...string) string
- func (c *Context) AppendHeader(key string, values ...string) *Context
- func (c *Context) Attachment(filePath string, name ...string) error
- func (c *Context) Bind() *Bind
- func (c *Context) BodyBytes() ([]byte, error)
- func (c *Context) BodyLimit() int64
- func (c *Context) BodyString() (string, error)
- func (c *Context) ClearCookie(cookie *http.Cookie)
- func (c *Context) ContentType() string
- func (c *Context) Context() stdctx.Context
- func (c *Context) Cookie(name string) (*http.Cookie, error)
- func (c *Context) Cookies() []*http.Cookie
- func (c *Context) Data(contentType string, b []byte) error
- func (c *Context) Encode(mediaType string, v any) error
- func (c *Context) File(filePath string) error
- func (c *Context) FileFS(filePath string, filesystem fs.FS) error
- func (c *Context) FormFile(name string) (*multipart.FileHeader, error)
- func (c *Context) FormFiles(name string) ([]*multipart.FileHeader, error)
- func (c *Context) FormValue(name string) string
- func (c *Context) FullPath() string
- func (c *Context) Get(key any) (any, bool)
- func (c *Context) HTML(data string) error
- func (c *Context) HandleError(err error)
- func (c *Context) Header(key string) string
- func (c *Context) IP() string
- func (c *Context) IPs() []string
- func (c *Context) Inline(filePath string, name ...string) error
- func (c *Context) IsPreflight() bool
- func (c *Context) IsWebSocket() bool
- func (c *Context) JSON(v any) error
- func (c *Context) JSONPretty(v any, indent string) error
- func (c *Context) LastError() error
- func (c *Context) Location(location string) *Context
- func (c *Context) Method() string
- func (c *Context) MultipartForm() (*multipart.Form, error)
- func (c *Context) Negotiate(offers map[string]any) error
- func (c *Context) Next() error
- func (c *Context) NoContent() error
- func (c *Context) OriginalURL() string
- func (c *Context) Param(name string) string
- func (c *Context) Path() string
- func (c *Context) Query(name string) string
- func (c *Context) QueryArray(name string) []string
- func (c *Context) QueryMap(name string) map[string]string
- func (c *Context) QueryValues() url.Values
- func (c *Context) Redirect(location string) error
- func (c *Context) RemoteIP() string
- func (c *Context) Render(name string, data any) error
- func (c *Context) Request() *http.Request
- func (c *Context) Route() RouteInfo
- func (c *Context) SSE(event Event) error
- func (c *Context) SaveFile(file *multipart.FileHeader, dst string) error
- func (c *Context) Scheme() string
- func (c *Context) Secure() bool
- func (c *Context) Send(data any) error
- func (c *Context) Set(key any, value any)
- func (c *Context) SetContext(ctx stdctx.Context)
- func (c *Context) SetCookie(cookie *http.Cookie)
- func (c *Context) SetHeader(key, value string) *Context
- func (c *Context) SetPath(path string)
- func (c *Context) SetRequest(r *http.Request)
- func (c *Context) SetWriter(w http.ResponseWriter)
- func (c *Context) Status(code int) *Context
- func (c *Context) Stream(contentType string, r io.Reader) error
- func (c *Context) String(data string) error
- func (c *Context) Type(ext string) *Context
- func (c *Context) Validate(v any) error
- func (c *Context) Vary(fields ...string) *Context
- func (c *Context) Writer() http.ResponseWriter
- func (c *Context) XML(v any) error
- type Decoder
- type Encoder
- type EnumProvider
- type ErrorHandler
- type Event
- type File
- type Group
- func (g *Group) Add(method, routePath string, handlers ...HandlerFunc) Route
- func (g *Group) All(path string, handlers ...HandlerFunc)
- func (g *Group) Connect(path string, handlers ...HandlerFunc) Route
- func (g *Group) Delete(path string, handlers ...HandlerFunc) Route
- func (g *Group) Document(docs ...MiddlewareDoc) *Group
- func (g *Group) File(routePath, file string) Route
- func (g *Group) FileFS(routePath, file string, filesystem fs.FS) Route
- func (g *Group) Get(path string, handlers ...HandlerFunc) Route
- func (g *Group) Group(prefix string, handlers ...HandlerFunc) *Group
- func (g *Group) HandleHTTP(pattern string, handler http.Handler) Route
- func (g *Group) Head(path string, handlers ...HandlerFunc) Route
- func (g *Group) Hidden() *Group
- func (g *Group) Match(methods []string, routePath string, handlers ...HandlerFunc)
- func (g *Group) Mount(prefix string, h http.Handler)
- func (g *Group) Options(path string, handlers ...HandlerFunc) Route
- func (g *Group) Patch(path string, handlers ...HandlerFunc) Route
- func (g *Group) Post(path string, handlers ...HandlerFunc) Route
- func (g *Group) Put(path string, handlers ...HandlerFunc) Route
- func (g *Group) Route(prefix string, fn func(*Group), handlers ...HandlerFunc) *Group
- func (g *Group) RouteNotFound(routePath string, handlers ...HandlerFunc)
- func (g *Group) Security(schemes ...string) *Group
- func (g *Group) SecurityAll(schemes ...string) *Group
- func (g *Group) Static(prefix, root string, opts ...StaticOption)
- func (g *Group) StaticFS(prefix string, filesystem fs.FS, opts ...StaticOption)
- func (g *Group) Tags(tags ...string) *Group
- func (g *Group) Trace(path string, handlers ...HandlerFunc) Route
- func (g *Group) TryHandle(spec RouteSpec) error
- func (g *Group) Use(handlers ...HandlerFunc) *Group
- func (g *Group) UseHTTP(middleware ...HTTPMiddleware) *Group
- type HTML
- type HTTPError
- func BadRequest(message string) *HTTPError
- func Conflict(message string) *HTTPError
- func Forbidden(message string) *HTTPError
- func Gone(message string) *HTTPError
- func InternalServerError(message string) *HTTPError
- func NewError(code int, message ...string) *HTTPError
- func NotFound(message string) *HTTPError
- func ServiceUnavailable(message string) *HTTPError
- func TooManyRequests(message string) *HTTPError
- func Unauthorized(message string) *HTTPError
- func UnprocessableEntity(message string) *HTTPError
- func (e *HTTPError) Error() string
- func (e *HTTPError) Is(target error) bool
- func (e *HTTPError) StatusCode() int
- func (e *HTTPError) Unwrap() error
- func (e *HTTPError) WithDetail(key string, value any) *HTTPError
- func (e *HTTPError) WithHeader(key, value string) *HTTPError
- func (e *HTTPError) Wrap(cause error) *HTTPError
- type HTTPMiddleware
- type HandlerFunc
- type HeaderDoc
- type Map
- type Middleware
- type MiddlewareDoc
- type NoContent
- type OpenAPIConfig
- type OpenAPIContact
- type OpenAPIExternalDocs
- type OpenAPILicense
- type OpenAPIOAuthFlow
- type OpenAPIOAuthFlows
- type OpenAPISecurityScheme
- type OpenAPIServer
- type OpenAPITag
- type Redirect
- type Renderer
- type ResponseWriter
- type Route
- func (r Route) Consumes(mediaTypes ...string) Route
- func (r Route) Deprecated() Route
- func (r Route) Description(description string) Route
- func (r Route) Document(docs ...MiddlewareDoc) Route
- func (r Route) Errors(statuses ...int) Route
- func (r Route) Example(status int, name string, value any) Route
- func (r Route) Hidden() Route
- func (r Route) Input(v any) Route
- func (r Route) Name(name string) Route
- func (r Route) Operation(hook func(op map[string]any)) Route
- func (r Route) Output(v any) Route
- func (r Route) Produces(status int, mediaTypes ...string) Route
- func (r Route) RequestExample(name string, value any) Route
- func (r Route) Response(status int, v any) Route
- func (r Route) Security(schemes ...string) Route
- func (r Route) SecurityAll(schemes ...string) Route
- func (r Route) Status(code int) Route
- func (r Route) Summary(summary string) Route
- func (r Route) Tags(tags ...string) Route
- type RouteInfo
- type RouteSpec
- type RuleSetValidator
- type SchemaNamer
- type SchemaProvider
- type StaticConfig
- type StaticOption
- type StatusCoder
- type Stream
- type TemplateExecutor
- type TemplateRenderer
- func NewHTMLTemplateRenderer(engine *htmltemplate.Template, opts ...TemplateRendererOption) *TemplateRenderer
- func NewTemplateRenderer(engine TemplateExecutor, opts ...TemplateRendererOption) *TemplateRenderer
- func NewTextTemplateRenderer(engine *texttemplate.Template, opts ...TemplateRendererOption) *TemplateRenderer
- type TemplateRendererOption
- type Text
- type ValidationError
- type Validator
Examples ¶
Constants ¶
const ( DefaultBodyLimit int64 = 4 << 20 DefaultReadTimeout = 5 * time.Second DefaultWriteTimeout = 10 * time.Second DefaultIdleTimeout = 120 * time.Second DefaultShutdownTimeout = 10 * time.Second DefaultProxyHeader = "X-Forwarded-For" // Deprecated: Zinc has no route cache since 0.5. Kept so code that // names it still compiles. DefaultRouteCacheSize = 0 )
Defaults applied to zero-valued Config fields.
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" )
Common HTTP header names used by Zinc and its middleware.
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 )
Standard HTTP method names supported by the dedicated router fast paths.
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 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 StatusInternalServerError = 500 // RFC 7231, 6.6.1 StatusNotImplemented = 501 // RFC 7231, 6.6.2 StatusBadGateway = 502 // RFC 7231, 6.6.3 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, including commonly used WebDAV and extension statuses.
const ( MIMEJSON = "application/json; charset=utf-8" MIMEXML = "application/xml; charset=utf-8" MIMEHTML = "text/html; charset=utf-8" MIMEText = "text/plain; charset=utf-8" MIMEEventStream = "text/event-stream" MIMEOctetStream = "application/octet-stream" )
MIME types for Context.Data and response headers. The text types include the UTF-8 charset.
const DefaultDocsPath = "/docs"
DefaultDocsPath is where an app serves its API reference page unless Config.DocsPath says otherwise.
const DefaultListenAddr = ":8080"
DefaultListenAddr is used when Listen receives no address or an empty one.
const DefaultOpenAPIPath = "/openapi.json"
DefaultOpenAPIPath is where an app serves its OpenAPI spec unless Config.OpenAPIPath says otherwise.
const Version = "0.7.3"
Version is the current version of Zinc. This should be updated for each release.
Variables ¶
var ( ErrBadRequest = NewError(StatusBadRequest) 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) ErrInternalServerError = NewError(StatusInternalServerError) ErrNotImplemented = NewError(StatusNotImplemented) ErrBadGateway = NewError(StatusBadGateway) ErrGatewayTimeout = NewError(StatusGatewayTimeout) ErrHTTPVersionNotSupported = NewError(StatusHTTPVersionNotSupported) ErrVariantAlsoNegotiates = NewError(StatusVariantAlsoNegotiates) ErrInsufficientStorage = NewError(StatusInsufficientStorage) ErrLoopDetected = NewError(StatusLoopDetected) ErrNotExtended = NewError(StatusNotExtended) ErrNetworkAuthenticationRequired = NewError(StatusNetworkAuthenticationRequired) )
Reusable HTTP errors. Modifier methods return independent copies and never mutate these package-level values.
var ( ErrTemplateEngineNotConfigured = errors.New("template engine is not configured") ErrTemplateNameRequired = errors.New("template name is required") ErrTemplateNotFound = errors.New("template not found") )
Template renderer configuration and lookup errors.
var ErrResponseAlreadySent = errors.New("response already sent")
ErrResponseAlreadySent is returned when a handler attempts a second terminal response write. SSE is the deliberate exception and supports multiple events.
Functions ¶
func BuiltinRules ¶ added in v0.7.0
func BuiltinRules() []string
BuiltinRules are the validate-tag rules Zinc enforces itself when Config.Validator is nil. They mean what they mean to go-playground/validator, so a struct's tags work with either:
required, omitempty, min, max, len, gt, gte, lt, lte, oneof, email, uuid, uuid4, url, uri, http_url
min, max, len, gt, gte, lt and lte count the characters of a string and the elements of a slice or map, and compare a number's value exactly, as the field's own type. A pointer that isn't nil counts as set, and omitempty skips only the rules after it. Nested structs are validated too, including those in slices and maps and those of a recursive type, as deep as the value goes, as the spec describes them; go-playground/validator needs dive for that.
func DefaultErrorHandler ¶ added in v0.4.0
DefaultErrorHandler writes err as a JSON error body, newline-terminated like every Context.JSON response:
{"error":{"status":404,"message":"user not found"}}
It adds "fields" for binding and validation errors and "details" for HTTPError details. Messages from HTTPError and from 4xx StatusCoders are sent as written; any other error is reported only by its status text, so internal error text never reaches the client.
func Form ¶ added in v0.4.0
Form returns the named form value parsed as T, with the semantics of FormValue. A missing or unparsable value is a *BindError, answered with 400. A body over the limit is ErrRequestEntityTooLarge, and a form that can't be parsed is a *BindError carrying the parse error.
func FormOr ¶ added in v0.4.0
FormOr returns the named form value parsed as T, or fallback when the value is missing or does not parse.
func MustValue ¶ added in v0.4.0
MustValue returns the request-scoped value stored under key, and panics when it is missing or has another type. Use it for values an earlier middleware always sets.
func Param ¶ added in v0.4.0
Param returns the named route parameter parsed as T. A value that does not parse is a *BindError, which the default error handler answers with 400 and the parameter's name:
id, err := zinc.Param[int64](c, "id")
if err != nil {
return err
}
T may be a string, bool, integer, or float type, a type implementing encoding.TextUnmarshaler, or a pointer to one of those.
func ProblemErrors ¶ added in v0.6.4
ProblemErrors is an ErrorHandler that writes RFC 9457 problem details, as application/problem+json:
{"type":"about:blank","title":"Not Found","status":404,"detail":"pet not found"}
Invalid fields from binding or validation are listed under "errors", and an HTTPError's Details become members of the object. Status resolution and message safety match DefaultErrorHandler, and the OpenAPI spec describes error responses as problem details when it's the app's ErrorHandler.
func Query ¶ added in v0.4.0
Query returns the first query value for name parsed as T. A missing or unparsable value is a *BindError, answered with 400. Use QueryOr for an optional value.
func QueryOr ¶ added in v0.4.0
QueryOr returns the first query value for name parsed as T, or fallback when the value is missing or does not parse. T is inferred from fallback:
page := zinc.QueryOr(c, "page", 1)
func StatusCode ¶ added in v0.4.0
StatusCode reports the HTTP status the default error handler sends for err: the code of an HTTPError anywhere in its chain, otherwise the status of the first StatusCoder, otherwise 500. It returns 0 for a nil error.
func TextErrors ¶ added in v0.4.0
TextErrors is an ErrorHandler that writes plain-text error bodies, as Zinc 0.3 did. Status resolution and message safety match DefaultErrorHandler.
Types ¶
type App ¶
type App struct {
// contains filtered or unexported fields
}
App is Zinc's application, router, middleware registry, and http.Handler. Configure routes and middleware before serving; registration is not safe concurrently with requests.
func New ¶
New creates an App. With no Config, or with a zero-valued field, Zinc's defaults apply; see Config.
func (*App) AcquireContext ¶ added in v0.1.0
AcquireContext creates an application-bound Context for advanced integrations. The caller must eventually pass it to ReleaseContext.
func (*App) Add ¶
func (a *App) Add(method, path string, handlers ...HandlerFunc) Route
Add registers handlers and panics when the route declaration is invalid.
func (*App) All ¶
func (a *App) All(path string, handlers ...HandlerFunc)
All registers handlers for Zinc's standard method set.
func (*App) Close ¶ added in v0.3.0
Close stops the active server and releases confined static roots. Call it after externally managed servers have stopped serving this App.
func (*App) Connect ¶
func (a *App) Connect(path string, handlers ...HandlerFunc) Route
Connect registers a CONNECT route.
func (*App) Delete ¶
func (a *App) Delete(path string, handlers ...HandlerFunc) Route
Delete registers a DELETE route.
func (*App) Document ¶ added in v0.7.1
func (a *App) Document(docs ...MiddlewareDoc)
Document adds descriptions of the app's middleware, which runs on every route, to every route in the spec. See MiddlewareDoc.
func (*App) FindRoute ¶ added in v0.1.0
FindRoute resolves metadata without invoking the route handler. It finds the route a request would run: a HEAD request with no HEAD route finds the GET route, unless automatic HEAD is off.
func (*App) Get ¶
func (a *App) Get(path string, handlers ...HandlerFunc) Route
Get registers a GET route.
func (*App) Group ¶
func (a *App) Group(prefix string, handlers ...HandlerFunc) *Group
Group creates a route group rooted at prefix.
Example ¶
A group shares a prefix and middleware with every route registered in it.
package main
import (
"fmt"
"net/http/httptest"
"strings"
"github.com/0mjs/zinc"
)
// do sends a request to app and prints the status and body, as a client
// would see them.
func do(app *zinc.App, method, target, body string) {
r := httptest.NewRequest(method, target, strings.NewReader(body))
if body != "" {
r.Header.Set("Content-Type", "application/json")
}
w := httptest.NewRecorder()
app.ServeHTTP(w, r)
fmt.Println(w.Code, strings.TrimSpace(w.Body.String()))
}
func main() {
app := zinc.New()
requireKey := func(c *zinc.Context) error {
if c.Header("X-API-Key") != "secret" {
return zinc.Unauthorized("missing or wrong API key")
}
return c.Next()
}
api := app.Group("/api", requireKey)
api.Get("/status", func(c *zinc.Context) error { return c.JSON(zinc.Map{"ok": true}) })
do(app, "GET", "/api/status", "")
}
Output: 401 {"error":{"status":401,"message":"missing or wrong API key"}}
func (*App) HandleHTTP ¶ added in v0.2.0
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, and the route's pattern through http.Request.Pattern, as Wrap describes.
func (*App) Head ¶
func (a *App) Head(path string, handlers ...HandlerFunc) Route
Head registers a HEAD route.
func (*App) ListenContext ¶ added in v0.4.0
ListenContext serves on addr until ctx ends, then shuts down gracefully: it stops accepting connections and waits up to Config.ShutdownTimeout for in-flight requests. It returns nil after a clean shutdown. Pair it with signal.NotifyContext to stop on SIGINT or SIGTERM; Zinc installs no signal handlers itself.
func (*App) Match ¶
func (a *App) Match(methods []string, path string, handlers ...HandlerFunc)
Match registers the same handler chain for each method.
func (*App) MethodNotAllowed ¶
func (a *App) MethodNotAllowed(handler HandlerFunc)
MethodNotAllowed replaces the application-wide 405 handler.
func (*App) NotFound ¶
func (a *App) NotFound(handler HandlerFunc)
NotFound replaces the application-wide 404 handler.
func (*App) OpenAPI ¶ added in v0.6.0
func (a *App) OpenAPI(path string, cfg OpenAPIConfig, middleware ...HandlerFunc) Route
OpenAPI serves the app's OpenAPI 3.1 spec as JSON at path, with GET, and returns the route, in place of the spec an app serves at Config.OpenAPIPath. Use it to protect the spec with middleware, or to serve several specs.
app.OpenAPI("/openapi.json", zinc.OpenAPIConfig{Title: "Shop", Version: "1.4.0"})
The spec is built on the first request and sent as pre-encoded bytes after that. Routes registered later are picked up on the next request. The spec route itself is hidden from the spec. It panics when a security scheme is missing a field its type needs, or cfg.Security names a scheme cfg.SecuritySchemes doesn't define; a route naming an unknown scheme makes the request fail with a 500 and the error.
Hiding the spec isn't access control: protect it, and the API, with auth middleware if the API is private.
func (*App) OpenAPISpec ¶ added in v0.6.0
func (a *App) OpenAPISpec(cfg OpenAPIConfig) ([]byte, error)
OpenAPISpec returns the app's OpenAPI 3.1 spec as JSON. Every registered route is in it, except hidden ones, mounts and static files, and methods OpenAPI 3.1 can't express, such as PURGE. Typed handlers are described fully; other handlers add detail with Route.Input, Route.Output and the other Route methods. The output is the same for the same routes.
Example ¶
Every app serves its OpenAPI 3.1 spec at /openapi.json. OpenAPISpec builds it in code, for tests or to write it to a file.
package main
import (
"encoding/json"
"fmt"
"net/http"
"github.com/0mjs/zinc"
)
type CreateUser struct {
Org string `path:"org"`
Email string `json:"email" validate:"required,email"`
}
type User struct {
ID int `json:"id"`
Org string `json:"org"`
Email string `json:"email"`
}
func main() {
app := zinc.New()
app.Post("/orgs/{org}/users", zinc.Typed(func(c *zinc.Context, in CreateUser) (User, error) {
return User{}, nil
})).Status(http.StatusCreated)
spec, err := app.OpenAPISpec(zinc.OpenAPIConfig{Title: "Users", Version: "1.0.0"})
if err != nil {
panic(err)
}
var doc struct {
OpenAPI string `json:"openapi"`
Paths map[string]map[string]json.RawMessage `json:"paths"`
}
_ = json.Unmarshal(spec, &doc)
fmt.Println(doc.OpenAPI)
for path, ops := range doc.Paths {
for method := range ops {
fmt.Println(method, path)
}
}
}
Output: 3.1.0 post /orgs/{org}/users
func (*App) Options ¶
func (a *App) Options(path string, handlers ...HandlerFunc) Route
Options registers an OPTIONS route.
func (*App) Patch ¶
func (a *App) Patch(path string, handlers ...HandlerFunc) Route
Patch registers a PATCH route.
func (*App) Post ¶
func (a *App) Post(path string, handlers ...HandlerFunc) Route
Post registers a POST route.
func (*App) Put ¶
func (a *App) Put(path string, handlers ...HandlerFunc) Route
Put registers a PUT route.
func (*App) ReleaseContext ¶ added in v0.1.0
ReleaseContext returns a manually acquired Context to its pool.
func (*App) Route ¶
func (a *App) Route(prefix string, fn func(*Group), handlers ...HandlerFunc) *Group
Route configures and returns a group through fn.
func (*App) RouteByName ¶ added in v0.1.0
RouteByName finds route metadata by its unique name.
func (*App) RouteNotFound ¶ added in v0.1.0
func (a *App) RouteNotFound(path string, handlers ...HandlerFunc)
RouteNotFound registers a path-specific handler used when no method matches.
func (*App) ServeHTTP ¶
func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler. Standard HTTP middleware wraps the application here; Zinc middleware and routing continue through serveHTTP.
func (*App) Shutdown ¶
Shutdown gracefully stops the active server and releases confined static roots after requests drain. It is a no-op before serving.
func (*App) Static ¶
func (a *App) Static(prefix, root string, opts ...StaticOption)
Static serves root from the operating-system filesystem below prefix. The confined directory handle is retained after its first use and released by Shutdown or Close.
func (*App) StaticFS ¶
func (a *App) StaticFS(prefix string, filesystem fs.FS, opts ...StaticOption)
StaticFS serves filesystem below prefix. It panics if filesystem is nil.
func (*App) Trace ¶
func (a *App) Trace(path string, handlers ...HandlerFunc) Route
Trace registers a TRACE route.
func (*App) TryHandle ¶ added in v0.2.0
TryHandle registers a route whose declaration came from dynamic input.
func (*App) URL ¶ added in v0.1.0
URL builds a named route URL. Segment parameters are escaped and must be non-empty without slashes; catch-all values keep their slashes and escape '?', '#', and '%'. The URL routes back to the same route and values, or URL returns an error: for example, beside GET /users/me, the value "me" for GET /users/{id} has no URL, and under default routing neither has an empty catch-all value for GET /files/{path...} beside GET /files.
func (*App) Use ¶
func (a *App) Use(handlers ...HandlerFunc)
Use appends Zinc middleware in registration order.
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)
UsePrefix applies Zinc middleware only to requests below a segment boundary.
func (*App) Validate ¶ added in v0.0.63
Validate checks the app's routes and spec without serving a request, so a mistake fails a test or a deploy rather than the first request that reaches it. Call it after registering routes:
if err := app.Validate(); err != nil {
log.Fatal(err)
}
It builds every spec the app serves, which fails on routes OpenAPI can't tell apart, unknown security schemes and examples that don't match their types, and it reports what registration can't panic over:
- a header-tagged output field that's still in the JSON body, which sends no header, unless the type is also the route's input;
- an openapi tag word other than readonly, writeonly and deprecated;
- a validate rule the validator doesn't enforce, on a type given to Route.Input or Route.Output.
The error lists every problem, one per line; nil means none.
type Bind ¶ added in v0.1.1
type Bind struct {
// contains filtered or unexported fields
}
Bind exposes source-specific binding for a Context.
func (*Bind) All ¶ added in v0.1.1
All binds the body, then query values, then path parameters, and validates v. Later sources win, so a path or query value is never replaced by a body key that matches the same field.
func (*Bind) Cookie ¶ added in v0.6.0
Cookie binds request cookies into fields tagged cookie, then validates v.
func (*Bind) Form ¶ added in v0.1.1
Form binds URL-encoded or multipart form values, then validates v.
type BindError ¶ added in v0.1.0
type BindError struct {
// Source is "path", "query", "header", "cookie", "form", or "body".
Source string
// Field is the Go struct field, for logs.
Field string
// Name is the request-facing name: the tag value, or the JSON field path.
Name string
// Reason is a client-safe description of what the value must be, such as
// "must be an integer". It is empty when there is nothing safe to say.
Reason string
Err error
}
BindError identifies the request source and struct field that failed.
func (*BindError) Error ¶ added in v0.1.0
Error formats the binding source, field, and underlying error.
func (*BindError) StatusCode ¶ added in v0.4.0
StatusCode implements StatusCoder: a binding failure is the client's error.
type Bytes ¶ added in v0.6.3
Bytes is sent with media type Type, or application/octet-stream when Type is empty.
type Config ¶
type Config struct {
// ServerHeader is written to every response when non-empty.
ServerHeader string
// CaseSensitive makes literal route segments case-sensitive.
CaseSensitive bool
// StrictRouting treats a trailing slash as part of the route identity.
StrictRouting bool
// DisableAutoHead stops HEAD requests from being served by a matching GET
// route when no HEAD route exists.
DisableAutoHead bool
// DisableAutoOptions stops OPTIONS requests from being answered with the
// methods registered for a path.
DisableAutoOptions bool
// DisableMethodNotAllowed answers a method mismatch with 404 instead of
// 405 and an Allow header.
DisableMethodNotAllowed bool
// BodyLimit is the maximum request body size accepted by binding helpers
// and form parsing. 0 means DefaultBodyLimit; negative means no limit.
BodyLimit int64
// ReadTimeout bounds reading the request, including its body.
// 0 means DefaultReadTimeout; negative means no timeout.
ReadTimeout time.Duration
// WriteTimeout bounds writing a response, or one event of a stream.
// 0 means DefaultWriteTimeout; negative means no timeout.
WriteTimeout time.Duration
// IdleTimeout controls keep-alive connection lifetime.
// 0 means DefaultIdleTimeout; negative means no timeout.
IdleTimeout time.Duration
// ShutdownTimeout bounds how long ListenContext waits for in-flight
// requests after its context ends. 0 means DefaultShutdownTimeout;
// negative means wait until they finish.
ShutdownTimeout time.Duration
// CookieSameSite is applied to cookies written by SetCookie and
// ClearCookie that don't set SameSite themselves. Zero leaves them unset.
CookieSameSite http.SameSite
// ProxyHeader identifies the forwarding header used by Context.IP.
// Empty means DefaultProxyHeader.
ProxyHeader string
// TrustedProxies contains IPs/CIDRs trusted in the forwarded chain.
// Entries are copied and validated at construction.
TrustedProxies []string
// Decoders read request bodies in other media types, keyed by media
// type, such as "application/yaml": yaml.Unmarshal. Binding picks one by
// the request's Content-Type. An entry for "application/json" or
// "application/xml" replaces the built-in decoder.
Decoders map[string]Decoder
// Encoders write responses in other media types, for Context.Encode and
// Context.Negotiate. An entry for "application/json" or
// "application/xml" replaces the built-in encoder, including for
// Context.JSON and Context.XML.
Encoders map[string]Encoder
// Validator checks bound input, after binding and through
// Context.Validate. Nil means Zinc checks validate tags itself, with
// BuiltinRules. A RuleSetValidator declares the rules it enforces, the
// only ones the OpenAPI spec claims.
Validator Validator
// ValidateResponses checks each typed handler's output with the same
// rules before it's sent, and answers 500 when it fails, so a response
// that breaks the spec's contract shows up in development and tests.
// It costs a check per response; leave it off in production.
ValidateResponses bool
// Renderer provides named template rendering.
Renderer Renderer
// ErrorHandler receives errors returned by handlers and middleware.
// Nil means DefaultErrorHandler.
ErrorHandler ErrorHandler
// OpenAPIPath is where the app serves its OpenAPI spec, for GET and HEAD
// requests that no route or mount answers. Empty means
// DefaultOpenAPIPath; "-" serves no spec, as does calling App.OpenAPI.
// The spec lists every route that isn't hidden, so for a private API,
// protect it with middleware or turn it off.
OpenAPIPath string
// OpenAPI describes the API in the served spec: its title, version,
// security schemes and more.
OpenAPI OpenAPIConfig
// DocsPath is where the app serves a browsable reference page for its
// spec, for GET and HEAD requests no route or mount answers. Empty means
// DefaultDocsPath; "-" serves none, and neither does an app that serves
// no spec. The page loads Scalar from a CDN; middleware/apidocs serves
// it elsewhere, with another renderer, or from your own files.
DocsPath string
// Deprecated: RouteCacheSize is ignored. Zinc 0.5 removed the route
// cache: the route tree matches faster than the cache could look a path
// up on realistic traffic, and the cache slowed parallel requests.
RouteCacheSize int
}
Config holds the application and server configuration. The zero value of every field is the default, so a literal only needs the fields it changes:
app := zinc.New(zinc.Config{BodyLimit: 64 << 20})
For limits and timeouts, 0 selects the default and a negative value turns the limit off.
type Context ¶
type Context struct {
// contains filtered or unexported fields
}
Context carries request-scoped state through Zinc handlers. Contexts are pooled and must not be retained or used after the handler returns.
func (*Context) Accepts ¶ added in v0.1.2
Accepts returns the best offered type allowed by the request Accept header.
func (*Context) AppendHeader ¶
AppendHeader adds response header values without replacing existing ones.
func (*Context) Attachment ¶
Attachment serves a file with an attachment Content-Disposition.
func (*Context) BodyBytes ¶
BodyBytes reads and caches the request body, returning a copy owned by the caller. The configured application body limit is enforced.
func (*Context) BodyLimit ¶ added in v0.3.0
BodyLimit returns the configured binding budget, or zero without an app. Middleware can use it for limits on transformed request bodies.
func (*Context) BodyString ¶
BodyString reads and caches the request body as a string.
func (*Context) ClearCookie ¶
ClearCookie tells the client to delete cookie. Name, Path, and Domain must match the cookie being removed; Path defaults to "/".
c.ClearCookie(&http.Cookie{Name: "session"})
func (*Context) ContentType ¶ added in v0.1.2
ContentType returns the normalized media type without parameters.
func (*Context) Encode ¶ added in v0.4.0
Encode writes v as mediaType, using the Encoder configured for it, or the built-in JSON or XML encoding. It returns an error for a media type the app has no encoder for.
func (*Context) FormFile ¶
func (c *Context) FormFile(name string) (*multipart.FileHeader, error)
FormFile returns the first uploaded file header and closes the opened part.
func (*Context) FormFiles ¶
func (c *Context) FormFiles(name string) ([]*multipart.FileHeader, error)
FormFiles returns all uploaded file headers for name.
func (*Context) FormValue ¶
FormValue returns the first form value using net/http form parsing semantics.
func (*Context) HandleError ¶ added in v0.4.0
HandleError sends err to the application's error handler now instead of returning it. Middleware that must observe the final response, such as a logger, uses it; a handler normally just returns the error. The error handler runs once per request, so a later return of the same failure is ignored.
func (*Context) IPs ¶
IPs returns the verified suffix of the forwarded address chain for trusted peers; otherwise it returns the direct remote address.
func (*Context) IsPreflight ¶
IsPreflight reports whether the request is a CORS preflight.
func (*Context) IsWebSocket ¶
IsWebSocket reports whether the request asks to upgrade to WebSocket.
func (*Context) JSONPretty ¶
JSONPretty writes v as JSON indented by indent.
func (*Context) LastError ¶ added in v0.0.73
LastError returns the most recent error passed to HandleError.
func (*Context) MultipartForm ¶
MultipartForm parses multipart input with net/http's 32 MiB in-memory threshold; larger file parts may be stored in temporary files.
func (*Context) Negotiate ¶ added in v0.1.2
Negotiate writes the offered representation that best matches the Accept header, using the status set by Status, or returns ErrNotAcceptable. The response depends on Accept, so Negotiate adds Accept to Vary, keeping the Vary entries already set.
func (*Context) Next ¶
Next advances the middleware chain by one handler. Middleware may perform work before and after the call to wrap downstream execution.
func (*Context) OriginalURL ¶
OriginalURL returns the request URI as received, before any SetPath or rewrite middleware changed it. Use c.Request().URL for the current target.
func (*Context) Param ¶
Param returns a named route parameter. Values remain slices of the request path until accessed so routing itself does not allocate parameter strings.
func (*Context) QueryArray ¶ added in v0.1.2
QueryArray returns a copy of all query values for name.
func (*Context) QueryMap ¶ added in v0.1.2
QueryMap collects bracketed query keys such as filter[name].
func (*Context) QueryValues ¶
QueryValues parses and caches the request query values.
func (*Context) Redirect ¶
Redirect sends location with 302 Found, or with the redirect status chosen by Status, such as c.Status(http.StatusMovedPermanently).Redirect("/new").
func (*Context) SSE ¶ added in v0.0.71
SSE writes and flushes one event, keeping the event-stream response open for more calls. Config.WriteTimeout bounds each event rather than the whole stream, so a stream may run for as long as the handler keeps sending.
func (*Context) SaveFile ¶
func (c *Context) SaveFile(file *multipart.FileHeader, dst string) error
SaveFile copies an uploaded file to dst, creating parent directories.
func (*Context) Scheme ¶
Scheme returns http or https. Forwarded protocol headers are trusted only when the direct peer matches Config.TrustedProxies.
func (*Context) SetContext ¶
SetContext replaces the standard-library context carried by the request.
func (*Context) SetRequest ¶
SetRequest replaces the request and invalidates request-derived caches.
func (*Context) SetWriter ¶
func (c *Context) SetWriter(w http.ResponseWriter)
SetWriter replaces the response writer used by subsequent handlers.
func (*Context) Validate ¶
Validate checks v, a pointer to a struct, as binding does. Enum values, from an enum tag or an EnumProvider type, are always checked. Then the configured Validator runs, or, when there's none, Zinc checks v's validate tags with BuiltinRules. A failure is a *ValidationError, which the default error handler answers with 422, unless the validator's error already carries a status.
func (*Context) Writer ¶
func (c *Context) Writer() http.ResponseWriter
Writer returns the current response writer, including any middleware wrapper.
type Decoder ¶ added in v0.4.0
Decoder reads a request body into v. It has the shape of json.Unmarshal, so any library's Unmarshal function can be used directly:
zinc.Config{Decoders: map[string]zinc.Decoder{"application/yaml": yaml.Unmarshal}}
type Encoder ¶ added in v0.4.0
Encoder turns v into a response body. It has the shape of json.Marshal, so any library's Marshal function can be used directly.
type EnumProvider ¶ added in v0.6.0
type EnumProvider interface {
Enum() []any
}
EnumProvider lets a named type list the values it can take. The type becomes a component with an enum, shared by every field of the type:
type Kind string
func (Kind) Enum() []any { return []any{"cat", "dog"} }
Zinc checks the values on input, whatever the validator.
type ErrorHandler ¶
ErrorHandler handles an error returned from a Zinc handler.
type File ¶ added in v0.6.3
File serves a file from Path on disk, or from FS when FS is set, with the semantics of Context.File and Context.FileFS: ranges, conditional requests and a Content-Type from the extension. A non-empty Name makes it a download with that file name, as Context.Attachment does.
type Group ¶
type Group struct {
// contains filtered or unexported fields
}
Group applies a shared path prefix and middleware chain to related routes.
func (*Group) Add ¶
func (g *Group) Add(method, routePath string, handlers ...HandlerFunc) Route
Add registers handlers and panics when the route declaration is invalid.
func (*Group) All ¶
func (g *Group) All(path string, handlers ...HandlerFunc)
All registers handlers for Zinc's standard method set.
func (*Group) Connect ¶
func (g *Group) Connect(path string, handlers ...HandlerFunc) Route
Connect registers a CONNECT route.
func (*Group) Delete ¶
func (g *Group) Delete(path string, handlers ...HandlerFunc) Route
Delete registers a DELETE route.
func (*Group) Document ¶ added in v0.7.1
func (g *Group) Document(docs ...MiddlewareDoc) *Group
Document adds descriptions of the group's middleware to every route registered in the group from now on, and its child groups' routes. Like Use, it panics once the group has routes.
func (*Group) Get ¶
func (g *Group) Get(path string, handlers ...HandlerFunc) Route
Get registers a GET route.
func (*Group) Group ¶
func (g *Group) Group(prefix string, handlers ...HandlerFunc) *Group
Group creates a child that inherits the parent's middleware in order.
func (*Group) HandleHTTP ¶ added in v0.2.0
HandleHTTP registers a standard net/http handler below the group prefix.
func (*Group) Head ¶
func (g *Group) Head(path string, handlers ...HandlerFunc) Route
Head registers a HEAD route.
func (*Group) Hidden ¶ added in v0.6.0
Hidden leaves every route registered in the group from now on, and its child groups' routes, out of the spec. Like Use, it panics once the group has routes.
func (*Group) Match ¶
func (g *Group) Match(methods []string, routePath string, handlers ...HandlerFunc)
Match registers the same handler chain for each method.
func (*Group) Options ¶
func (g *Group) Options(path string, handlers ...HandlerFunc) Route
Options registers an OPTIONS route.
func (*Group) Patch ¶
func (g *Group) Patch(path string, handlers ...HandlerFunc) Route
Patch registers a PATCH route.
func (*Group) Post ¶
func (g *Group) Post(path string, handlers ...HandlerFunc) Route
Post registers a POST route.
func (*Group) Put ¶
func (g *Group) Put(path string, handlers ...HandlerFunc) Route
Put registers a PUT route.
func (*Group) Route ¶
func (g *Group) Route(prefix string, fn func(*Group), handlers ...HandlerFunc) *Group
Route configures and returns a child group through fn.
func (*Group) RouteNotFound ¶ added in v0.1.0
func (g *Group) RouteNotFound(routePath string, handlers ...HandlerFunc)
RouteNotFound registers a path-specific 404 handler below the group.
func (*Group) Security ¶ added in v0.6.0
Security names the security schemes that protect every route registered in the group from now on, and its child groups. A route can replace them with Route.Security. Like Use, it panics once the group has routes.
func (*Group) SecurityAll ¶ added in v0.6.0
SecurityAll is Security for schemes that must all pass together.
func (*Group) Static ¶
func (g *Group) Static(prefix, root string, opts ...StaticOption)
Static serves a filesystem directory below the group.
func (*Group) StaticFS ¶
func (g *Group) StaticFS(prefix string, filesystem fs.FS, opts ...StaticOption)
StaticFS serves an fs.FS below the group. It panics if filesystem is nil.
func (*Group) Tags ¶ added in v0.6.0
Tags adds tags to every route registered in the group from now on, and to its child groups. Like Use, it panics once the group has routes or child groups, so the order of calls can't silently change the spec.
func (*Group) Trace ¶
func (g *Group) Trace(path string, handlers ...HandlerFunc) Route
Trace registers a TRACE route.
func (*Group) TryHandle ¶ added in v0.2.0
TryHandle registers a dynamically defined route below the group prefix.
func (*Group) Use ¶
func (g *Group) Use(handlers ...HandlerFunc) *Group
Use appends middleware to the group. It panics once the group has routes, mounts, static files, or child groups, because those have already captured the chain and would silently run without the new middleware.
func (*Group) UseHTTP ¶ added in v0.4.0
func (g *Group) UseHTTP(middleware ...HTTPMiddleware) *Group
UseHTTP appends standard net/http middleware to the group. Each runs inside the group's earlier middleware, as FromHTTP describes.
type HTTPError ¶
type HTTPError struct {
Code int
Message string
Cause error
// Details are written to the response body by the default error handler.
Details Map
Headers http.Header
}
HTTPError represents an HTTP error with a status code and optional message.
func BadRequest ¶ added in v0.4.0
BadRequest returns a 400 error with a client-facing message.
func InternalServerError ¶ added in v0.4.0
InternalServerError returns a 500 error with a client-facing message.
func NewError ¶
NewError creates an HTTPError for code, with an optional client-facing message. Without one, the status text is used.
func NotFound ¶ added in v0.4.0
NotFound returns a 404 error with a client-facing message.
Example ¶
A handler returns an error, and one error handler writes every failure.
package main
import (
"fmt"
"net/http/httptest"
"strings"
"github.com/0mjs/zinc"
)
// do sends a request to app and prints the status and body, as a client
// would see them.
func do(app *zinc.App, method, target, body string) {
r := httptest.NewRequest(method, target, strings.NewReader(body))
if body != "" {
r.Header.Set("Content-Type", "application/json")
}
w := httptest.NewRecorder()
app.ServeHTTP(w, r)
fmt.Println(w.Code, strings.TrimSpace(w.Body.String()))
}
func main() {
app := zinc.New()
app.Get("/users/{id}", func(c *zinc.Context) error {
return zinc.NotFound("user not found")
})
do(app, "GET", "/users/42", "")
}
Output: 404 {"error":{"status":404,"message":"user not found"}}
func ServiceUnavailable ¶ added in v0.4.0
ServiceUnavailable returns a 503 error with a client-facing message.
func TooManyRequests ¶ added in v0.4.0
TooManyRequests returns a 429 error with a client-facing message.
func Unauthorized ¶ added in v0.4.0
Unauthorized returns a 401 error with a client-facing message.
func UnprocessableEntity ¶ added in v0.4.0
UnprocessableEntity returns a 422 error with a client-facing message.
func (*HTTPError) Is ¶ added in v0.4.0
Is matches HTTP errors by status, so errors.Is(err, ErrNotFound) holds for any 404, including copies made by the With methods. A target that carries a message matches only errors with the same status and message.
func (*HTTPError) StatusCode ¶ added in v0.4.0
StatusCode implements StatusCoder.
func (*HTTPError) Unwrap ¶ added in v0.1.0
Unwrap exposes the underlying cause for errors.Is and errors.As.
func (*HTTPError) WithDetail ¶ added in v0.4.0
WithDetail returns a copy with one detail, written to the response body by the default error handler.
func (*HTTPError) WithHeader ¶ added in v0.1.0
WithHeader returns a copy that adds a response header.
type HTTPMiddleware ¶ added in v0.2.0
HTTPMiddleware is the standard net/http middleware shape.
type HandlerFunc ¶
HandlerFunc handles one request and returns failures to the App error handler.
func Typed ¶ added in v0.4.0
func Typed[In, Out any](fn func(*Context, In) (Out, error)) HandlerFunc
Typed adapts a function whose signature is the request contract into a handler. The input is bound from the request, validated, and passed in; the output is written as JSON:
type CreateUser struct {
OrgID string `path:"org"`
DryRun bool `query:"dry_run"`
Email string `json:"email" validate:"required,email"`
}
api.Post("/orgs/{org}/users", zinc.Typed(func(c *zinc.Context, in CreateUser) (User, error) {
return users.Create(c.Context(), in)
})).Status(http.StatusCreated)
In must be a struct; use struct{} for a handler without input. Its fields bind like Bind().All, from the body and then tagged header, query, and path fields, so a value from the URL or a header is never replaced by a body key. A failure is a *BindError (400). The configured Validator then runs, and a failure is a *ValidationError (422). An error returned by fn goes to the error handler like any other.
The response status is the one fn or middleware sets with c.Status, or else the one declared with Route.Status, or else 200, 204 for NoContent and 302 for Redirect. The spec documents the same status. A status of 200 set with c.Status counts as unset on a route without a declared status. Out is written as JSON, except for Zinc's output types: NoContent, Text, HTML, Bytes, File, Stream and Redirect, each written and documented as what it is. Use NoContent as Out for a response without a body. If fn writes the response itself, its output is ignored.
A field of Out tagged header is sent as that response header, and needs json:"-" so it isn't also in the body:
type Created struct {
Location string `header:"Location" json:"-"`
ID string `json:"id"`
}
An empty string, nil pointer or slice, or zero time.Time sends nothing; a slice sends a value per element. A *http.Cookie or []*http.Cookie field tagged header:"Set-Cookie" sets cookies.
Example ¶
A typed handler's input binds from the request and is validated before the function runs; its output is the response. Both describe the route in the OpenAPI spec.
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"strings"
"github.com/0mjs/zinc"
)
// do sends a request to app and prints the status and body, as a client
// would see them.
func do(app *zinc.App, method, target, body string) {
r := httptest.NewRequest(method, target, strings.NewReader(body))
if body != "" {
r.Header.Set("Content-Type", "application/json")
}
w := httptest.NewRecorder()
app.ServeHTTP(w, r)
fmt.Println(w.Code, strings.TrimSpace(w.Body.String()))
}
type CreateUser struct {
Org string `path:"org"`
Email string `json:"email" validate:"required,email"`
}
type User struct {
ID int `json:"id"`
Org string `json:"org"`
Email string `json:"email"`
}
func main() {
app := zinc.New()
app.Post("/orgs/{org}/users", zinc.Typed(func(c *zinc.Context, in CreateUser) (User, error) {
return User{ID: 1, Org: in.Org, Email: in.Email}, nil
})).Status(http.StatusCreated)
do(app, "POST", "/orgs/acme/users", `{"email":"ada@example.com"}`)
do(app, "POST", "/orgs/acme/users", `{"email":"nope"}`)
}
Output: 201 {"id":1,"org":"acme","email":"ada@example.com"} 422 {"error":{"status":422,"message":"validation failed","fields":{"email":"must be an email address"}}}
func Wrap ¶
func Wrap(h http.Handler) HandlerFunc
Wrap adapts a standard net/http handler to HandlerFunc. Immediately before it runs, the matched route is published on the request as http.ServeMux would: http.Request.PathValue returns each parameter, and http.Request.Pattern is the route's method and full path, such as "GET /users/{id}" (a GET route's pattern also for a HEAD request it answers).
func WrapFunc ¶
func WrapFunc(fn http.HandlerFunc) HandlerFunc
WrapFunc adapts a standard http.HandlerFunc to HandlerFunc.
type HeaderDoc ¶ added in v0.7.1
type HeaderDoc struct {
// Name is the header's name, spelled as the spec should show it.
Name string
Description string
// Required says requests the middleware runs on must send it.
Required bool
}
HeaderDoc is a request header a middleware reads.
type Middleware ¶
type Middleware = HandlerFunc
Middleware is a HandlerFunc that calls Context.Next to continue the chain.
func FromHTTP ¶ added in v0.4.0
func FromHTTP(middleware HTTPMiddleware) Middleware
FromHTTP adapts standard net/http middleware to Zinc middleware, so it can run on a group or a single route instead of the whole app:
admin := app.Group("/admin", zinc.FromHTTP(basicAuth))
The middleware is built once. If it replaces the request or wraps the response writer before calling next, the rest of the Zinc chain uses the replacements. An error from that chain is written by the error handler before the standard middleware returns, so middleware that observes the response, such as a logger, sees its status; the error is still returned to outer Zinc middleware.
A middleware that wraps the ResponseWriter must expose the writer it wraps through an Unwrap() http.ResponseWriter method, the convention http.ResponseController relies on. Zinc uses it to find the request's Context without allocating.
On a group or route, the route has matched before the middleware runs, so the request carries it as http.ServeMux would set it: http.Request.PathValue returns each parameter and http.Request.Pattern is the route's "METHOD /path". On the app, through App.Use, the middleware runs before routing and sees neither.
func Skip ¶ added in v0.4.0
func Skip(skip func(*Context) bool, mw Middleware) Middleware
Skip runs mw except when skip reports true for the request, in which case the chain continues without it. It replaces the Skipper option each middleware used to carry:
app.Use(zinc.Skip(isHealthCheck, logger.New()))
type MiddlewareDoc ¶ added in v0.7.1
type MiddlewareDoc struct {
// Methods limits the description to requests with these methods, such
// as the unsafe ones CSRF protection checks. Empty means every method.
Methods []string
// Security holds credentials the middleware checks on every request it
// covers, such as a CSRF token, by scheme name. Each is added to the
// spec's security schemes and required together with the route's own
// security, so a generated client sets it once rather than on every
// call. A scheme of the same name in OpenAPIConfig.SecuritySchemes must
// be the same. Unlike a route's security, it adds no 401 or 403; list
// what the middleware answers in Errors.
Security map[string]OpenAPISecurityScheme
// Headers are request headers the middleware reads, other than
// credentials: each is a parameter callers pass.
Headers []HeaderDoc
// Errors are statuses it answers by returning an error, described with
// the body the error handler writes, as Route.Errors does.
Errors []int
}
MiddlewareDoc describes, for the OpenAPI spec, what a middleware adds to the routes it runs on: the credentials and request headers it reads and the errors it can answer. A middleware is a plain function, so Zinc can't see this for itself. Pass it to App.Document, Group.Document or Route.Document beside the middleware:
api.Use(csrf.New()) api.Document(csrf.Doc())
type NoContent ¶ added in v0.4.0
type NoContent struct{}
NoContent is the output type of a typed handler that sends no body. The route answers 204 No Content, or the status declared with Route.Status, even 200.
type OpenAPIConfig ¶ added in v0.6.0
type OpenAPIConfig struct {
// Title names the API. It defaults to the last element of the main
// module's path, or "API".
Title string
// Version is the API's version, not Zinc's. It defaults to the main
// module's version, or "0.0.0" for a development build.
Version string
// Description may use Markdown.
Description string
// TermsOfService is a URL.
TermsOfService string
Contact *OpenAPIContact
License *OpenAPILicense
// ExternalDocs links to documentation beyond the spec.
ExternalDocs *OpenAPIExternalDocs
// Servers lists base URLs the API is served from.
Servers []OpenAPIServer
// Tags describes tags, in the order docs pages list them. Tags that
// routes use but Tags leaves out follow, in the order routes use them.
Tags []OpenAPITag
// SecuritySchemes defines the schemes Route.Security, Group.Security and
// Security refer to, by name.
SecuritySchemes map[string]OpenAPISecurityScheme
// Security names the schemes that protect every route that doesn't set
// its own with Route.Security or Group.Security. Any one of them is
// enough. A name can carry a scope: "oauth:pets:read".
Security []string
// NoAuthResponses leaves out the 401, and the 403 for a route that needs
// scopes, that Zinc adds to every secured route.
NoAuthResponses bool
// Schemas gives a schema to a type Zinc can't describe and you can't add
// a SchemaProvider to, such as a type from another module:
//
// Schemas: map[reflect.Type]map[string]any{
// reflect.TypeFor[decimal.Decimal](): {"type": "string", "format": "decimal"},
// }
Schemas map[reflect.Type]map[string]any
// Extensions adds specification extensions to the spec's root, such as
// "x-logo". Each key must start with "x-".
Extensions map[string]any
// Mutate edits the finished spec, as decoded JSON, for what Zinc has no
// option for. It runs after Extensions and every Route.Operation hook.
// The result is checked again: it must still be OpenAPI 3.1 with a title
// and version, and every local $ref must resolve.
Mutate func(spec map[string]any) error
}
OpenAPIConfig describes the API as a whole in the OpenAPI spec. Every field is optional.
type OpenAPIContact ¶ added in v0.6.0
type OpenAPIContact struct {
Name string `json:"name,omitempty"`
URL string `json:"url,omitempty"`
Email string `json:"email,omitempty"`
}
OpenAPIContact is who to contact about the API.
type OpenAPIExternalDocs ¶ added in v0.6.0
type OpenAPIExternalDocs struct {
Description string `json:"description,omitempty"`
URL string `json:"url"`
}
OpenAPIExternalDocs links to documentation outside the spec.
type OpenAPILicense ¶ added in v0.6.0
type OpenAPILicense struct {
Name string `json:"name"`
Identifier string `json:"identifier,omitempty"`
URL string `json:"url,omitempty"`
}
OpenAPILicense is the API's license. Name is required; set Identifier, an SPDX expression such as "MIT", or URL, not both.
type OpenAPIOAuthFlow ¶ added in v0.6.0
type OpenAPIOAuthFlow struct {
AuthorizationURL string `json:"authorizationUrl,omitempty"`
TokenURL string `json:"tokenUrl,omitempty"`
RefreshURL string `json:"refreshUrl,omitempty"`
// Scopes maps each scope the flow grants to a short description.
Scopes map[string]string `json:"scopes"`
}
OpenAPIOAuthFlow is one OAuth 2 flow.
type OpenAPIOAuthFlows ¶ added in v0.6.0
type OpenAPIOAuthFlows struct {
// AuthorizationCode needs AuthorizationURL and TokenURL.
AuthorizationCode *OpenAPIOAuthFlow `json:"authorizationCode,omitempty"`
// ClientCredentials needs TokenURL.
ClientCredentials *OpenAPIOAuthFlow `json:"clientCredentials,omitempty"`
// Password needs TokenURL.
Password *OpenAPIOAuthFlow `json:"password,omitempty"`
// Implicit needs AuthorizationURL.
Implicit *OpenAPIOAuthFlow `json:"implicit,omitempty"`
}
OpenAPIOAuthFlows lists the OAuth 2 flows a scheme supports. Set at least one.
type OpenAPISecurityScheme ¶ added in v0.6.0
type OpenAPISecurityScheme struct {
// Type is "http", "apiKey", "oauth2", "openIdConnect" or "mutualTLS".
Type string `json:"type"`
// Scheme is the HTTP authentication scheme for type "http", such as
// "bearer" or "basic".
Scheme string `json:"scheme,omitempty"`
// BearerFormat hints at the token format for scheme "bearer", such as "JWT".
BearerFormat string `json:"bearerFormat,omitempty"`
// In is where an "apiKey" is sent: "header", "query" or "cookie".
In string `json:"in,omitempty"`
// Name is the header, query parameter or cookie that carries an "apiKey".
Name string `json:"name,omitempty"`
// Flows lists the flows an "oauth2" scheme supports; it needs at least
// one.
Flows *OpenAPIOAuthFlows `json:"flows,omitempty"`
// OpenIDConnectURL is the discovery URL for type "openIdConnect".
OpenIDConnectURL string `json:"openIdConnectUrl,omitempty"`
Description string `json:"description,omitempty"`
}
OpenAPISecurityScheme describes one way a client authenticates.
zinc.OpenAPISecurityScheme{Type: "http", Scheme: "bearer", BearerFormat: "JWT"}
zinc.OpenAPISecurityScheme{Type: "apiKey", In: "header", Name: "X-API-Key"}
zinc.OpenAPISecurityScheme{Type: "oauth2", Flows: &zinc.OpenAPIOAuthFlows{
ClientCredentials: &zinc.OpenAPIOAuthFlow{TokenURL: "https://id.example.com/token"},
}}
A scheme missing a field its type needs, such as an "oauth2" scheme without flows, makes the spec fail to build.
type OpenAPIServer ¶ added in v0.6.0
type OpenAPIServer struct {
URL string `json:"url"`
Description string `json:"description,omitempty"`
}
OpenAPIServer is a base URL the API is served from.
type OpenAPITag ¶ added in v0.6.0
type OpenAPITag struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
ExternalDocs *OpenAPIExternalDocs `json:"externalDocs,omitempty"`
}
OpenAPITag describes a tag routes use.
type Redirect ¶ added in v0.6.3
type Redirect string
Redirect sends the client to its URL with the route's status, set with Route.Status, or 302 Found.
type ResponseWriter ¶ added in v0.1.2
type ResponseWriter interface {
http.ResponseWriter
Status() int
BytesWritten() int
Written() bool
}
ResponseWriter records status and body size while retaining http.ResponseWriter.
func WrapResponseWriter ¶ added in v0.1.2
func WrapResponseWriter(w http.ResponseWriter) ResponseWriter
WrapResponseWriter wraps w or returns it unchanged when already instrumented.
type Route ¶
type Route struct {
// contains filtered or unexported fields
}
Route is a registered route. Registration methods return it so the route can be named for URL building:
app.Get("/users/{id}", showUser).Name("users.show")
func (Route) Consumes ¶ added in v0.6.3
Consumes declares the media types the route accepts as a request body, such as .Consumes("text/csv"), in place of the ones Zinc infers from the input type.
func (Route) Deprecated ¶ added in v0.6.0
Deprecated marks the route as deprecated in the OpenAPI spec. The route still serves requests.
func (Route) Description ¶ added in v0.6.0
Description sets the route's longer description in the OpenAPI spec. It may use Markdown.
func (Route) Document ¶ added in v0.7.1
func (r Route) Document(docs ...MiddlewareDoc) Route
Document adds descriptions of the route's own middleware, the handlers before its last, to the spec.
func (Route) Errors ¶ added in v0.6.0
Errors declares error statuses the route can answer by returning an error, such as zinc.NewError(http.StatusConflict, ...). The spec describes each with the body the error handler writes: Zinc's error envelope with the default handler, or the status alone with a custom one. Use Response for a status the handler writes itself.
func (Route) Example ¶ added in v0.6.4
Example adds a named example of the response sent with status, shown in the spec beside its schema:
app.Get("/pets/{id}", zinc.Typed(getPet)).
Example(200, "a cat", Pet{ID: "7", Name: "Tom"}).
Errors(404).
Example(404, "unknown id", zinc.NewError(404, "pet not found"))
value is what the route sends for it, as a Go value: the output type for the success status, the type given to Response for a declared status, or an *HTTPError for an error status, shown as the app's ErrorHandler writes it. The spec fails to build when value doesn't match the response it's for. An example with the same status and name replaces the earlier one.
func (Route) Hidden ¶ added in v0.6.0
Hidden leaves the route out of the OpenAPI spec. The route still serves requests.
func (Route) Input ¶ added in v0.6.0
Input declares the request type of a route whose handler isn't Typed, so the OpenAPI spec can describe its parameters and body. Pass a value of the type, such as CreateUser{}. It panics on a Typed route, whose input is already known.
func (Route) Name ¶ added in v0.4.0
Name gives the route a unique name, used by App.URL, App.RouteByName, and RouteInfo.Name. Like other registration mistakes, a duplicate name panics; routes from configuration should use TryHandle, which returns the error.
func (Route) Operation ¶ added in v0.7.0
Operation adds a hook that edits the route's operation in the spec, as decoded JSON, for what no Route method sets, such as an extension:
app.Get("/pets", listPets).Operation(func(op map[string]any) {
op["x-rate-limit"] = 100
})
Hooks run in the order added, before OpenAPIConfig.Mutate, and the spec is checked again after them.
func (Route) Output ¶ added in v0.6.0
Output declares the success-response type of a route whose handler isn't Typed, such as User{}. It panics on a Typed route, whose output is already known.
func (Route) Produces ¶ added in v0.6.3
Produces declares the media types the route sends with status, such as .Produces(200, "text/csv"). Use it where Zinc can't tell from the route: a plain handler, or a Bytes, File or Stream output, whose media type is chosen when the handler runs. It applies to the success status or a status declared with Response. Calling it again for a status replaces its types.
func (Route) RequestExample ¶ added in v0.6.4
RequestExample adds a named example of the request body, a value of the route's input type. Fields bound from the path, query, headers or cookies are left out, as the body doesn't carry them, and so are nil fields.
func (Route) Response ¶ added in v0.6.0
Response declares another response the route can send, such as a 409 with a ConflictBody{}. A nil value means the response has no body. Declaring the same status again replaces it.
func (Route) Security ¶ added in v0.6.0
Security names the security schemes that protect the route, replacing its group's. Any one of them is enough; SecurityAll needs them all. A name can carry a scope after a colon, such as "oauth:pets:read". With no names, the route is marked public.
func (Route) SecurityAll ¶ added in v0.6.0
SecurityAll is Security for schemes that must all pass together, such as an API key and a bearer token, replacing the group's.
func (Route) Status ¶ added in v0.4.0
Status sets the route's success status, such as http.StatusCreated for a route that creates a resource. It's the status of whatever the route writes, for typed and plain handlers alike, unless a handler or middleware sets another with Context.Status, or returns an error. The spec documents it. It panics unless code is a success status (2xx) or a redirect (301, 302, 303, 307 or 308), the status a Redirect output or Context.Redirect sends. On a route whose output is Redirect, it panics unless code is a redirect.
type RouteInfo ¶
type RouteInfo struct {
Name string
Method string
Path string
Params []string
Mounted bool
Handler string
// Status is the success status declared with Route.Status, or 0.
Status int
// Builtin marks an endpoint the app serves itself: the OpenAPI spec and
// the reference page.
Builtin bool
}
RouteInfo is an immutable snapshot of registered route metadata.
type RouteSpec ¶ added in v0.1.0
type RouteSpec struct {
Name string
Method string
Path string
Handler HandlerFunc
}
RouteSpec describes a route supplied by configuration, plugins, or generated code.
type RuleSetValidator ¶ added in v0.7.0
RuleSetValidator is a Validator that declares the validate-tag rules it enforces, such as "required", "min" and "email". The OpenAPI spec claims only those rules, and a typed handler whose input or output uses any other rule panics when it's registered, so a rule is never silently unenforced. A Validator without RuleSet makes no claims: the spec lists no validate rules, and nothing is checked at registration.
type SchemaNamer ¶ added in v0.6.4
type SchemaNamer interface {
OpenAPIName() string
}
SchemaNamer lets a named type choose its component name in the OpenAPI spec, in place of its Go name, such as "Pet" for a struct named petRecord or a generic Page[Pet], or "UserStatus" for an enum type named Status. A struct's input variant adds Input to the name, and its request-body variant Body, unless the name already ends with it. If two types claim one name, the later is qualified by its package, as with Go names.
type SchemaProvider ¶ added in v0.6.0
SchemaProvider lets a type describe itself in the OpenAPI spec when the schema Zinc derives from its Go shape would be wrong, such as a type with a custom MarshalJSON. OpenAPISchema returns a JSON Schema 2020-12 object, such as map[string]any{"type": "string", "format": "date"}.
type StaticConfig ¶
StaticConfig controls directory serving and index behaviour.
type StaticOption ¶
type StaticOption func(*StaticConfig)
StaticOption mutates static-file configuration during registration.
func WithStaticBrowse ¶
func WithStaticBrowse(browse bool) StaticOption
WithStaticBrowse enables or disables directory listings.
func WithStaticIndex ¶
func WithStaticIndex(index string) StaticOption
WithStaticIndex changes the filename served for directory requests.
type StatusCoder ¶ added in v0.4.0
type StatusCoder interface {
StatusCode() int
}
StatusCoder is implemented by errors that choose their own HTTP status, so a handler can return a domain error and let the error handler map it:
func (ErrUserNotFound) StatusCode() int { return http.StatusNotFound }
For statuses below 500, the error's own message is sent to the client.
type Stream ¶ added in v0.6.3
Stream copies Reader to the response with media type Type, or application/octet-stream when Type is empty. A Reader that's also an io.Closer is closed after the copy.
type TemplateExecutor ¶ added in v0.0.76
TemplateExecutor is implemented by html/template and text/template sets.
type TemplateRenderer ¶ added in v0.0.76
type TemplateRenderer struct {
Engine TemplateExecutor
// contains filtered or unexported fields
}
TemplateRenderer adapts parsed templates to Zinc's Renderer contract.
func NewHTMLTemplateRenderer ¶ added in v0.0.76
func NewHTMLTemplateRenderer(engine *htmltemplate.Template, opts ...TemplateRendererOption) *TemplateRenderer
NewHTMLTemplateRenderer wraps an html/template set.
func NewTemplateRenderer ¶ added in v0.0.76
func NewTemplateRenderer(engine TemplateExecutor, opts ...TemplateRendererOption) *TemplateRenderer
NewTemplateRenderer wraps a parsed template set.
func NewTextTemplateRenderer ¶ added in v0.0.76
func NewTextTemplateRenderer(engine *texttemplate.Template, opts ...TemplateRendererOption) *TemplateRenderer
NewTextTemplateRenderer wraps a text/template set.
type TemplateRendererOption ¶ added in v0.0.76
type TemplateRendererOption func(*TemplateRenderer)
TemplateRendererOption configures template name resolution.
func WithTemplateSuffixes ¶ added in v0.0.76
func WithTemplateSuffixes(suffixes ...string) TemplateRendererOption
WithTemplateSuffixes configures fallback suffixes tried after an exact name.
type ValidationError ¶ added in v0.0.63
type ValidationError struct {
Err error
}
ValidationError wraps a failure returned by the configured Validator. The default error handler answers it with 422, adding the field messages when the validator's error has a Fields() map[string]string method.
func (*ValidationError) Error ¶ added in v0.4.0
func (e *ValidationError) Error() string
func (*ValidationError) Fields ¶ added in v0.4.0
func (e *ValidationError) Fields() map[string]string
Fields returns per-field messages from the validator's error, or nil.
func (*ValidationError) StatusCode ¶ added in v0.4.0
func (*ValidationError) StatusCode() int
StatusCode implements StatusCoder.
func (*ValidationError) Unwrap ¶ added in v0.4.0
func (e *ValidationError) Unwrap() error
Unwrap exposes the validator's error.
Source Files
¶
- accessors.go
- app.go
- app_validate.go
- bind.go
- bind_isolate.go
- bind_plan.go
- bind_setter.go
- bind_sources.go
- cfg.go
- ctx.go
- error.go
- formats.go
- group.go
- headers.go
- http.go
- http_middleware.go
- openapi.go
- openapi_hooks.go
- openapi_schema.go
- output.go
- output_headers.go
- response.go
- response_writer.go
- route_docs.go
- router.go
- router_arena.go
- router_methods.go
- router_pattern.go
- router_radix.go
- router_tree.go
- static.go
- template_renderer.go
- typed.go
- validate.go
- version.go
- zinc.go
Directories
¶
| Path | Synopsis |
|---|---|
|
internal
|
|
|
docspage
Package docspage renders the API reference page for an OpenAPI spec.
|
Package docspage renders the API reference page for an OpenAPI spec. |
|
marks
Package marks lets Zinc's own middleware tell Zinc what it needs at registration: to run before routing, such as rewrite, or to answer CORS preflight requests, such as cors.
|
Package marks lets Zinc's own middleware tell Zinc what it needs at registration: to run before routing, such as rewrite, or to answer CORS preflight requests, such as cors. |
|
Package middleware is the home of Zinc's standard middleware.
|
Package middleware is the home of Zinc's standard middleware. |
|
apidocs
Package apidocs serves a browsable reference page for an OpenAPI spec, such as the one every Zinc app serves at /openapi.json.
|
Package apidocs serves a browsable reference page for an OpenAPI spec, such as the one every Zinc app serves at /openapi.json. |
|
compress
Package compress compresses responses for clients that accept gzip.
|
Package compress compresses responses for clients that accept gzip. |
|
contenttype
Package contenttype rejects request bodies of media types or content codings the application does not accept.
|
Package contenttype rejects request bodies of media types or content codings the application does not accept. |
|
headers
Package headers sets response headers and selects middleware by request header.
|
Package headers sets response headers and selects middleware by request header. |
|
healthcheck
Package healthcheck answers a health endpoint before routing work.
|
Package healthcheck answers a health endpoint before routing work. |
|
internal/shared
Package shared holds helpers used by more than one Zinc middleware package.
|
Package shared holds helpers used by more than one Zinc middleware package. |
|
internal/testutil
Package testutil holds helpers shared by middleware tests.
|
Package testutil holds helpers shared by middleware tests. |
|
limiter
Package limiter bounds how fast, or how many at once, requests reach downstream handlers.
|
Package limiter bounds how fast, or how many at once, requests reach downstream handlers. |
|
logger
Package logger logs one line per request.
|
Package logger logs one line per request. |
|
nocache
Package nocache tells browsers and intermediaries not to cache responses.
|
Package nocache tells browsers and intermediaries not to cache responses. |
|
pprof
Package pprof serves the net/http/pprof profiling endpoints.
|
Package pprof serves the net/http/pprof profiling endpoints. |
|
prometheus
Package prometheus records request counts and durations and serves them in the Prometheus text format, without depending on the Prometheus client.
|
Package prometheus records request counts and durations and serves them in the Prometheus text format, without depending on the Prometheus client. |
|
proxy
Package proxy forwards requests to upstream servers.
|
Package proxy forwards requests to upstream servers. |
|
redirect
Package redirect answers matching paths with a redirect.
|
Package redirect answers matching paths with a redirect. |
|
requestid
Package requestid gives every request an identifier, reusing the one the client or an upstream proxy sent.
|
Package requestid gives every request an identifier, reusing the one the client or an upstream proxy sent. |
|
rewrite
Package rewrite routes matching paths as other paths.
|
Package rewrite routes matching paths as other paths. |
|
session
Package session keeps string values in a signed client-side cookie.
|
Package session keeps string values in a signed client-side cookie. |
|
trailingslash
Package trailingslash normalizes trailing slashes in request paths.
|
Package trailingslash normalizes trailing slashes in request paths. |