Help us shape the future of Go! Take the 2026 Go Developer Survey

web

package
v0.30.0 Latest Latest
Warning

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

Go to latest
Published: Oct 19, 2026 License: MIT Imports: 32 Imported by: 0

Documentation

Overview

Package web provides the request context (*Ctx) used by Vukem handlers: request helpers, typed input, responses, and the central error handler.

A handler has the signature func(*Ctx) error. Returning an error hands it to the error handler, which renders the right response for the client (HTML, redirect with flashed errors, HTMX fragment or problem+json).

Parse, ParseQuery and Bind turn request input into typed values through z schemas; Services carries the shared dependencies (URL generator, view renderer, logger, authorizer) the router hands to every Ctx.

See https://github.com/AlexGalhardo/vukem/blob/main/docs/http.md.

Example
package main

import (
	"fmt"
	"log/slog"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/AlexGalhardo/vukem/errs"
	"github.com/AlexGalhardo/vukem/web"
)

// serve runs h the way the router does: errors go to the error handler.
func serve(h web.HandlerFunc, req *http.Request) *httptest.ResponseRecorder {
	rec := httptest.NewRecorder()
	web.NewCtx(rec, req, &web.Services{Log: slog.New(slog.DiscardHandler)}).Serve(h)
	return rec
}

func main() {
	show := func(c *web.Ctx) error {
		if c.Query("id") != "1" {
			return errs.ErrNotFound
		}
		return c.JSON(http.StatusOK, web.Map{"id": 1, "title": "Hello"})
	}

	ok := httptest.NewRequest(http.MethodGet, "/posts?id=1", http.NoBody)
	rec := serve(show, ok)
	fmt.Println(rec.Code, strings.TrimSpace(rec.Body.String()))

	missing := httptest.NewRequest(http.MethodGet, "/posts?id=2", http.NoBody)
	missing.Header.Set("Accept", "application/json")
	rec = serve(show, missing)
	fmt.Println(rec.Code, rec.Header().Get("Content-Type"))
}
Output:
200 {"id":1,"title":"Hello"}
404 application/problem+json

Index

Examples

Constants

View Source
const (
	OldInputKey = "_old"
	ErrorsKey   = "_errors"
	TokenKey    = "_token"
	// SessionUserKey holds the id of the logged-in user (auth guards set it
	// on login) so server-side stores can revoke a user's sessions.
	SessionUserKey = "_user_id"
)

Reserved session keys used by flash, old input and validation errors.

View Source
const DefaultMaxBody = 10 << 20

DefaultMaxBody is the request body limit applied by Input and BindJSON when no smaller limit was set by middleware (A06: resource exhaustion).

Variables

This section is empty.

Functions

func AuditEvent added in v0.26.0

func AuditEvent(r *http.Request, event string, attrs ...any)

AuditEvent logs a routine audit record (an admin recorded a payout, changed a role) at INFO with the same envelope as SecurityEvent: a stable "event" attribute, method, path and request_id. It is dispatched as a security.Audit, so security alerts are not mixed with routine records. Pass the actor as an attribute ("actor_id", u.AuthID()); never pass secrets (a config.Secret is logged masked) or personal data such as names and emails. The dispatched record carries the client IP, which is personal data: stored audit records need a retention period.

func Bind

func Bind[T any](c *Ctx) (T, error)

Bind parses the request input into T using the schema derived from T's `validate` struct tags (z.For).

func BodyLimitOf added in v0.19.0

func BodyLimitOf(r *http.Request) (int64, bool)

BodyLimitOf returns the body limit set by LimitBody, if any.

func CSPNonce added in v0.18.0

func CSPNonce(ctx context.Context) string

CSPNonce returns the request's CSP nonce, or "".

func DefaultErrorHandler

func DefaultErrorHandler(c *Ctx, err error)

DefaultErrorHandler renders err according to the client:

  • JSON clients get RFC 9457 problem+json (422 includes field errors; z.Issues and z.FieldError errors count as validation errors);
  • classic form posts with a validation error go to the validation hook (flash errors and redirect back) when one is installed;
  • htmx requests get an HTML fragment with the status (htmx 4 swaps 4xx);
  • Services.ErrorPage, when set, renders the page in its own format (an Inertia page for Inertia requests);
  • browsers get an HTML status page (views "errors/<status>" if present).

5xx details are never sent to clients unless Services.Debug is set (docs/security.md, A10).

func ETagOf

func ETagOf(v any) (string, error)

ETagOf returns a strong ETag ("\"...\"") for v: the SHA-256 of its JSON encoding (or of the bytes when v is []byte or string).

func ErrorsFrom added in v0.19.0

func ErrorsFrom(ctx context.Context) map[string][]string

ErrorsFrom is Ctx.Errors for code that only has the request context, such as templ components.

func Fail

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

Fail renders err through the error handler. Middleware uses it to reject a request (401, 413, 415, 429...) with the same format as handlers.

func FlashFrom added in v0.19.0

func FlashFrom(ctx context.Context, key string) any

FlashFrom returns the value flashed under key by the previous request, or nil. It is Ctx.FlashValue for code that only has the request context, such as templ components.

func FormToMap

func FormToMap(values url.Values) map[string]any

FormToMap converts url.Values into nested maps and lists: "a=1&a=2" → {"a": ["1","2"]}, "tags[]=x" → {"tags": ["x"]}, "author[email]=e" → {"author": {"email": "e"}}, "items[0][name]=n" → {"items": [{"name": "n"}]}.

func IsJSONMediaType added in v0.21.0

func IsJSONMediaType(contentType string) bool

IsJSONMediaType reports whether a Content-Type value is application/json or an application/*+json type. Parameters are ignored, so a CORS-simple "text/plain; x=+json" body is never taken for JSON.

func IssueLocalizer added in v0.18.0

func IssueLocalizer(ctx context.Context) func(z.Issues) z.Issues

IssueLocalizer returns the function stored by WithIssueLocalizer, or nil.

func JSONWith

func JSONWith[T any](c *Ctx, status int, schema z.Schema[T], v T) error

JSONWith writes v as JSON after checking it against schema when Services.CheckResponses is enabled (development and test by default). A mismatch is a server bug: it is logged and answered with 500 instead of sending data that breaks the API contract.

func LimitBody

func LimitBody(w http.ResponseWriter, r *http.Request, n int64) *http.Request

LimitBody caps the request body at n bytes and marks the request so handlers do not apply DefaultMaxBody on top. Body-limit middleware uses it. Called again on the same request, the new limit replaces the old one, so a route can raise or lower the router-wide default.

A declared Content-Length above n fails on the first read, before any byte is consumed, with an *http.MaxBytesError; undeclared (chunked) bodies fail once they cross n.

func OldInput added in v0.19.0

func OldInput(ctx context.Context, field string) string

OldInput is Ctx.Old for code that only has the request context, such as templ components.

func Parse

func Parse[T any](c *Ctx, schema z.Schema[T]) (T, error)

Parse reads the request input (JSON, form or multipart body merged over the query string) and parses it with schema. Validation issues become an *errs.ValidationError, so returning the error from a handler yields a 422 problem+json, an HTMX fragment or a redirect back with flashed errors.

in, err := web.Parse(c, requests.StorePostSchema)
if err != nil {
	return err
}
Example
package main

import (
	"fmt"
	"log/slog"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/AlexGalhardo/vukem/web"
	"github.com/AlexGalhardo/vukem/z"
)

type createPost struct {
	Title string `json:"title"`
}

var createPostSchema = z.Struct[createPost](z.Shape{"title": z.String().Trim().Min(3)})

// serve runs h the way the router does: errors go to the error handler.
func serve(h web.HandlerFunc, req *http.Request) *httptest.ResponseRecorder {
	rec := httptest.NewRecorder()
	web.NewCtx(rec, req, &web.Services{Log: slog.New(slog.DiscardHandler)}).Serve(h)
	return rec
}

func main() {
	store := func(c *web.Ctx) error {
		in, err := web.Parse(c, createPostSchema)
		if err != nil {
			return err // 422 problem+json, HTMX fragment or redirect back
		}
		return c.String(http.StatusCreated, "created "+in.Title)
	}

	req := httptest.NewRequest(http.MethodPost, "/posts", strings.NewReader(`{"title":"  Gophers  "}`))
	req.Header.Set("Content-Type", "application/json")
	rec := serve(store, req)
	fmt.Println(rec.Code, rec.Body.String())

	req = httptest.NewRequest(http.MethodPost, "/posts", strings.NewReader(`{"title":"Go"}`))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Accept", "application/json")
	rec = serve(store, req)
	fmt.Println(rec.Code)
}
Output:
201 created Gophers
422

func ParseInput added in v0.15.0

func ParseInput[T any](schema z.Schema[T], input map[string]any) (T, error)

ParseInput validates an already assembled input map (validation errors become a 422 ValidationError). Messages stay in English and Refine errors are not logged: it has no request to read them from. Prefer ParseMap inside a handler.

func ParseMap added in v0.28.0

func ParseMap[T any](c *Ctx, schema z.Schema[T], input map[string]any) (T, error)

ParseMap validates an already assembled input map with the request's context and logger: validation errors become a localized 422 ValidationError (see WithIssueLocalizer) and the raw errors of failed Refine/Custom checks are logged, never sent to the client.

func ParseParams

func ParseParams[T any](c *Ctx, schema z.Schema[T], names ...string) (T, error)

ParseParams parses the named path parameters ({id}, {slug}...).

func ParseQuery

func ParseQuery[T any](c *Ctx, schema z.Schema[T]) (T, error)

ParseQuery parses only the query string.

func RequestID

func RequestID(ctx context.Context) string

RequestID returns the request id stored in ctx, or "".

func SafeRedirect

func SafeRedirect(r *http.Request, target, fallback string) string

SafeRedirect returns target when it is a relative path or has the same host as r, and fallback otherwise.

func SecurityEvent

func SecurityEvent(r *http.Request, event string, attrs ...any)

SecurityEvent logs a security-relevant event at WARN with a stable "event" attribute (docs/security.md, A09) and dispatches it as a security.Event.

func WithCSPNonce added in v0.18.0

func WithCSPNonce(ctx context.Context, nonce string) context.Context

WithCSPNonce stores the request's Content-Security-Policy nonce in ctx (middleware.SecureHeaders does this).

func WithIssueLocalizer added in v0.18.0

func WithIssueLocalizer(ctx context.Context, fn func(z.Issues) z.Issues) context.Context

WithIssueLocalizer stores fn in ctx; Parse, Bind, ParseQuery and ParseParams pass validation issues through it before building the *errs.ValidationError, so field messages follow the request locale. The i18n middleware installs one bound to the resolved locale.

func WithRequestID

func WithRequestID(ctx context.Context, id string) context.Context

WithRequestID stores the request id in ctx.

func WithServices

func WithServices(ctx context.Context, s *Services) context.Context

WithServices stores s in ctx so middleware can render errors consistently.

func WithSession

func WithSession(ctx context.Context, s Session) context.Context

WithSession stores s in ctx (session middleware does this).

func WithValidationHook

func WithValidationHook(ctx context.Context, hook ValidationHook) context.Context

WithValidationHook installs hook for requests carrying ctx.

Types

type Authorizer added in v0.6.0

type Authorizer interface {
	Authorize(ctx context.Context, ability string, subject any) error
}

Authorizer decides abilities for the user in ctx: nil, or an error with status 401, 403 or 404.

type Ctx

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

Ctx is the per-request context. It must not be used after the handler returns or from other goroutines.

func NewCtx

func NewCtx(w http.ResponseWriter, r *http.Request, s *Services) *Ctx

NewCtx returns a Ctx for w and r. Routers call it; tests may too.

func (*Ctx) Accepted

func (c *Ctx) Accepted(v any) error

Accepted writes v as JSON with 202.

func (*Ctx) Authorize added in v0.6.0

func (c *Ctx) Authorize(ability string, subject any) error

Authorize checks ability on subject (nil for gate abilities) with Services.Authorizer and returns the error to return from the handler. Denials are logged as "authz.denied" security events. Without an Authorizer it denies (fail closed).

func (*Ctx) Back

func (c *Ctx) Back(fallback string) error

Back redirects to the Referer when it is same-origin, else to fallback. Off-site referers are ignored (open-redirect protection, A01).

func (*Ctx) BindJSON

func (c *Ctx) BindJSON(v any) error

BindJSON decodes the JSON body into v, rejecting unknown fields (422 with a field error per key, for struct targets), trailing data and bodies over the size limit.

func (*Ctx) Blob

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

Blob writes raw bytes with a content type.

func (*Ctx) CheckIfMatch

func (c *Ctx) CheckIfMatch(current string) error

CheckIfMatch enforces optimistic concurrency for writes: when the client sent If-Match and it does not match the current ETag, it returns a 412 error. Without If-Match it returns nil.

func (*Ctx) Context

func (c *Ctx) Context() context.Context

Context returns the request context.

func (*Ctx) Cookie

func (c *Ctx) Cookie(name string) string

Cookie returns a request cookie value, or "" when absent.

func (*Ctx) Created

func (c *Ctx) Created(location string, v any) error

Created writes v as JSON with 201 and a Location header.

func (*Ctx) Download

func (c *Ctx) Download(fsys fs.FS, name, filename string) error

Download serves name from fsys as an attachment called filename (the base of name when empty). The name is sanitized like export.ContentDisposition: last path element only, no control or bidi characters, an RFC 5987 filename* when it is not ASCII. The header is set only once the file opened, so an error page is not an attachment.

func (*Ctx) Errors

func (c *Ctx) Errors() map[string][]string

Errors returns validation errors flashed by the previous request.

func (*Ctx) File

func (c *Ctx) File(fsys fs.FS, name string) error

File serves name from fsys (with Range and If-Modified-Since support).

func (*Ctx) Flash

func (c *Ctx) Flash(key string, value any) error

Flash stores a message for the next request (e.g. after a redirect).

func (*Ctx) FlashValue

func (c *Ctx) FlashValue(key string) any

FlashValue returns a flashed value from the previous request, or nil.

func (*Ctx) FormFile

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

FormFile returns an uploaded file. A missing file, or a request that is not multipart/form-data (a form without enctype, a JSON body), is a 422 validation error on name.

func (*Ctx) FormValue

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

FormValue returns a form or query value.

func (*Ctx) Fragment

func (c *Ctx) Fragment(name, block string, data any, opts ...RenderOption) error

Fragment renders a single block of a view.

func (*Ctx) HTML

func (c *Ctx) HTML(status int, html string) error

HTML writes a text/html response from a trusted string. Never pass user input: use views (html/template) for escaping.

func (*Ctx) HTMX

func (c *Ctx) HTMX() *htmx.Response

HTMX returns the htmx response-header builder for this request.

func (*Ctx) HandleError

func (c *Ctx) HandleError(err error)

HandleError passes err to the error handler.

func (*Ctx) Header

func (c *Ctx) Header(name string) string

Header returns a request header.

func (*Ctx) IP

func (c *Ctx) IP() string

IP returns the client IP. X-Forwarded-For (or ClientIPHeader when set) is honoured only when the direct peer is a trusted proxy (docs/security.md, A01/A02).

func (*Ctx) Input

func (c *Ctx) Input() (map[string]any, error)

Input returns the request body (JSON object, urlencoded or multipart form) merged over the query string as a generic map ready for schema parsing: JSON keeps its types (numbers as json.Number); form values are strings, repeated or "[]" keys become lists and "a[b]" keys nest.

func (*Ctx) IsHTMX

func (c *Ctx) IsHTMX() bool

IsHTMX reports whether the request was made by htmx.

func (*Ctx) IsHTTPS added in v0.28.0

func (c *Ctx) IsHTTPS() bool

IsHTTPS reports whether the client reached the app over HTTPS: the connection is TLS, or TrustForwardedProto is set and a TrustedProxies peer sent a single X-Forwarded-Proto: https line (a second line may come from the client).

func (*Ctx) IsJSON

func (c *Ctx) IsJSON() bool

IsJSON reports whether the request body is JSON.

func (*Ctx) IsPartial

func (c *Ctx) IsPartial() bool

IsPartial reports whether htmx asked for a fragment.

func (*Ctx) JSON

func (c *Ctx) JSON(status int, v any) error

JSON writes v as JSON with status.

func (*Ctx) Log

func (c *Ctx) Log() *slog.Logger

Log returns the request logger.

func (*Ctx) Method

func (c *Ctx) Method() string

Method returns the request method.

func (*Ctx) MustURL

func (c *Ctx) MustURL(name string, params ...any) string

MustURL is URL for templates and code paths where the route is known to exist; it returns "#" and logs on error instead of panicking.

func (*Ctx) NoContent

func (c *Ctx) NoContent() error

NoContent writes 204.

func (*Ctx) NotModified

func (c *Ctx) NotModified(etag string, lastModified time.Time) bool

NotModified sets the ETag (and Last-Modified when non-zero) headers and reports whether the client's cached copy is current. When it returns true a 304 was written and the handler must return without a body:

if c.NotModified(etag, post.UpdatedAt) { return nil }

func (*Ctx) Old

func (c *Ctx) Old(field string) string

Old returns the input submitted by the previous (failed) form post for field, so forms can be re-filled. Nested fields use dots ("author.email").

func (*Ctx) Param

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

Param returns a path parameter ({name} in the route pattern).

func (*Ctx) ParamInt

func (c *Ctx) ParamInt(name string) (int64, error)

ParamInt returns a path parameter as int64, or a 404 error when it is not a valid integer (a non-numeric id names no resource).

func (*Ctx) Path

func (c *Ctx) Path() string

Path returns the request path.

func (*Ctx) Problem

func (c *Ctx) Problem(status int, title, detail string) error

Problem writes an application/problem+json response.

func (*Ctx) Query

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

Query returns a query string value.

func (*Ctx) QueryBool

func (c *Ctx) QueryBool(name string) bool

QueryBool reports whether a query value is a true-like value.

func (*Ctx) QueryInput

func (c *Ctx) QueryInput() map[string]any

QueryInput returns the query string as a generic map (see Input).

func (*Ctx) QueryInt

func (c *Ctx) QueryInt(name string, def int) int

QueryInt returns a query value as int, or def when absent or invalid.

func (*Ctx) Redirect

func (c *Ctx) Redirect(target string) error

Redirect redirects to target. Unsafe methods get 303 See Other so the browser follows with GET; GET/HEAD get 302 Found. Use RedirectStatus for other codes. htmx requests receive HX-Location instead (navigation without a full reload).

func (*Ctx) RedirectRoute

func (c *Ctx) RedirectRoute(name string, params ...any) error

RedirectRoute redirects to a named route.

func (*Ctx) RedirectStatus

func (c *Ctx) RedirectStatus(status int, target string) error

RedirectStatus redirects with an explicit 3xx status.

func (*Ctx) Render

func (c *Ctx) Render(name string, data any, opts ...RenderOption) error

Render renders a view into the response. Output is buffered, so a template error becomes a clean 500 instead of a half-written page.

func (*Ctx) Request

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

Request returns the underlying request.

func (*Ctx) RouteName

func (c *Ctx) RouteName() string

RouteName returns the name of the matched route, if any.

func (*Ctx) SSE added in v0.18.0

func (c *Ctx) SSE(fn func(*sse.Stream) error, opts ...sse.Option) error

SSE streams server-sent events to the client with fn (see package sse):

return c.SSE(func(s *sse.Stream) error { return hub.Stream(s, "posts") })

func (*Ctx) Serve

func (c *Ctx) Serve(h HandlerFunc)

Serve runs h with c and routes a returned error to the error handler. A status set with Status and not yet sent is sent when h returns nil.

func (*Ctx) Services

func (c *Ctx) Services() *Services

Services returns the shared services.

func (*Ctx) Session

func (c *Ctx) Session() Session

Session returns the request session or nil when sessions are not enabled.

func (*Ctx) SetCookie

func (c *Ctx) SetCookie(ck *http.Cookie)

SetCookie adds a Set-Cookie header.

func (*Ctx) SetHeader

func (c *Ctx) SetHeader(name, value string)

SetHeader sets a response header.

func (*Ctx) SetRequest

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

SetRequest replaces the request (e.g. after adding context values).

func (*Ctx) SetRouteName

func (c *Ctx) SetRouteName(name string)

SetRouteName is used by routers to record the matched route.

func (*Ctx) Status

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

Status sets the response status without sending it: the next helper that writes the response with the default 200 (JSON(200, v), Render, View, inertia.Render, a plain Write) sends it instead, with its headers. c.Status(201).JSON(200, v) answers 201 with Content-Type application/json. Any other status wins over it: a redirect, NoContent, a 304, JSON(202, v). A handler that returns nil without writing sends the status alone; a returned error or a panic answers with its own status.

func (*Ctx) Stream

func (c *Ctx) Stream(status int, contentType string, r io.Reader) error

Stream copies r to the response.

func (*Ctx) String

func (c *Ctx) String(status int, s string) error

String writes a text/plain response.

func (*Ctx) URL

func (c *Ctx) URL(name string, params ...any) (string, error)

URL builds the URL for a named route.

func (*Ctx) View

func (c *Ctx) View(v View, opts ...RenderOption) error

View renders a component such as a templ.Component.

func (*Ctx) WantsJSON

func (c *Ctx) WantsJSON() bool

WantsJSON reports whether the client prefers a JSON response: it accepts JSON but not HTML, or sent a JSON body without stating a preference.

func (*Ctx) Writer

func (c *Ctx) Writer() *ResponseWriter

Writer returns the response writer.

type ErrorHandler

type ErrorHandler func(c *Ctx, err error)

ErrorHandler writes the response for an error returned by a handler.

type ErrorPage added in v0.27.0

type ErrorPage struct {
	// Status is the HTTP status.
	Status int
	// Title is the status text, or "Validation failed" for a 4xx with
	// field errors.
	Title string
	// Detail is the error's own (translated) message for 4xx; empty when
	// it would repeat Title, and always empty for 5xx.
	Detail string
	// Errors holds the field errors of a 4xx validation error (all
	// messages per field); nil otherwise.
	Errors map[string][]string
}

ErrorPage is the client-safe description of an error that DefaultErrorHandler hands to Services.ErrorPage. Its text never holds a 5xx cause or message, nor a wrapped cause (CWE-209).

type ErrorPageFunc added in v0.27.0

type ErrorPageFunc func(c *Ctx, e ErrorPage) bool

ErrorPageFunc renders an error page described by e. It reports whether it wrote a response; false falls back to the HTML page.

type EventDispatcher added in v0.13.0

type EventDispatcher interface {
	Dispatch(ctx context.Context, event any) error
}

EventDispatcher delivers security events to listeners (an events.Bus).

type HandlerFunc

type HandlerFunc func(c *Ctx) error

HandlerFunc handles a request. Returned errors go to the error handler.

type Map

type Map = map[string]any

Map is a convenience alias for template and JSON data.

type Problem

type Problem struct {
	Type      string              `json:"type"`
	Title     string              `json:"title"`
	Status    int                 `json:"status"`
	Detail    string              `json:"detail,omitempty"`
	Instance  string              `json:"instance,omitempty"`
	RequestID string              `json:"request_id,omitempty"`
	Errors    map[string][]string `json:"errors,omitempty"`
}

Problem is an RFC 9457 problem details document.

type RenderOption

type RenderOption func(*renderOpts)

RenderOption configures Render.

func Block

func Block(name string) RenderOption

Block renders only the named block for htmx partial requests and the full page otherwise (template fragments):

return c.Render("posts/index", data, web.Block("post-list"))

func Partial added in v0.19.0

func Partial(v View) RenderOption

Partial is Block for View: c.View renders v instead of the page for htmx partial requests (templ fragments):

return c.View(views.PostsIndex(posts), web.Partial(views.PostList(posts)))

func WithStatus

func WithStatus(code int) RenderOption

WithStatus sets the response status (default 200).

type Renderer

type Renderer interface {
	Render(ctx context.Context, w io.Writer, name string, data any) error
	RenderBlock(ctx context.Context, w io.Writer, name, block string, data any) error
	Has(name string) bool
}

Renderer renders named views. The view package implements it; ctx gives templates access to request-scoped data (session, CSRF token, CSP nonce).

type ResponseWriter

type ResponseWriter struct {
	http.ResponseWriter
	// contains filtered or unexported fields
}

ResponseWriter wraps http.ResponseWriter to record the status and whether the response was written. It supports http.ResponseController.

func (*ResponseWriter) Flush added in v0.28.0

func (w *ResponseWriter) Flush()

Flush sends the status (a pending Ctx.Status, else 200) and flushes the underlying writer. Without it, http.ResponseController would flush the unwrapped writer and send an implicit 200 behind this one's back.

func (*ResponseWriter) FlushError added in v0.28.0

func (w *ResponseWriter) FlushError() error

FlushError is Flush reporting http.ErrNotSupported when the underlying writer cannot flush (http.ResponseController prefers it).

func (*ResponseWriter) Hijack added in v0.28.0

func (w *ResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error)

Hijack hands the connection to the caller (WebSocket upgrades). No status is sent: the hijacker writes its own response, and the writer counts as written so nothing is sent on the connection afterwards.

func (*ResponseWriter) Size

func (w *ResponseWriter) Size() int64

Size returns the number of body bytes written.

func (*ResponseWriter) Status

func (w *ResponseWriter) Status() int

Status returns the written status (0 when nothing was written).

func (*ResponseWriter) Unwrap

func (w *ResponseWriter) Unwrap() http.ResponseWriter

Unwrap supports http.ResponseController.

func (*ResponseWriter) Write

func (w *ResponseWriter) Write(b []byte) (int, error)

Write writes the body, sending a 200 status first when needed.

func (*ResponseWriter) WriteHeader

func (w *ResponseWriter) WriteHeader(code int)

WriteHeader records and writes the status. A status set earlier with Ctx.Status replaces a 200 (the implicit status of Write, and the default of helpers such as Render, View or inertia.Render); any other code (a redirect, 204, 304, an explicit 202) is sent as given.

func (*ResponseWriter) WriteString added in v0.20.1

func (w *ResponseWriter) WriteString(s string) (int, error)

WriteString writes s like Write, without copying it into a []byte when the underlying writer is an io.StringWriter.

func (*ResponseWriter) Written

func (w *ResponseWriter) Written() bool

Written reports whether the status line was sent.

type Services

type Services struct {
	URLs   URLGenerator
	Views  Renderer
	Errors ErrorHandler
	Log    *slog.Logger
	// Debug enables detailed error pages (never in production).
	Debug bool
	// DebugOut receives a colored report of every 5xx error when Debug is
	// on (the app sets os.Stderr in development).
	DebugOut io.Writer
	// TrustedProxies lists CIDRs whose X-Forwarded-For is honoured by IP().
	TrustedProxies []*net.IPNet
	// ClientIPHeader, when set, names a header (such as X-Real-IP) that a
	// trusted proxy sets to the client IP. IP() then reads it instead of
	// X-Forwarded-For, only from TrustedProxies peers; a missing, repeated
	// or non-IP value falls back to the peer address.
	ClientIPHeader string
	// TrustForwardedProto makes IsHTTPS honour X-Forwarded-Proto: https,
	// only from TrustedProxies peers (TRUST_FORWARDED_PROTO).
	TrustForwardedProto bool
	// IPv6Prefix is the prefix length per-IP keys (ratelimit.ByIP) group
	// IPv6 clients by, since one client usually owns a whole /64; 0 or any
	// value outside 1-128 means 64. IPv4 (and IPv4-mapped IPv6) keys stay
	// per address.
	IPv6Prefix int
	// ProblemBaseURL prefixes RFC 9457 problem "type" URIs; empty means
	// "about:blank".
	ProblemBaseURL string
	// CheckResponses makes JSONWith validate outgoing data against its
	// schema (enabled outside production by the app).
	CheckResponses bool
	// Events receives a security.Event for every SecurityEvent (alerting)
	// and a security.Audit for every AuditEvent.
	Events EventDispatcher
	// Authorizer backs Ctx.Authorize and the "can" template function
	// (an authz.Gate). Without one, every authorization check denies.
	Authorizer Authorizer
	// ErrorPage lets a frontend adapter render DefaultErrorHandler's error
	// page in its own format (vukem.WithInertia installs
	// inertia.Inertia.ErrorPage, an Inertia page for Inertia requests).
	// Nil keeps the HTML page.
	ErrorPage ErrorPageFunc
}

Services are the shared dependencies every Ctx can reach. The router owns one Services value; fields may be nil when the feature is not installed.

func ServicesFrom

func ServicesFrom(ctx context.Context) *Services

ServicesFrom returns the services stored in ctx, or an empty value.

type Session

type Session interface {
	// Get returns a value, or nil.
	Get(key string) any
	// Put stores a value (JSON-compatible) for this and later requests.
	Put(key string, value any)
	// Forget removes keys.
	Forget(keys ...string)
	// Pull returns and removes a value.
	Pull(key string) any
	// Flash stores a value available only on the next request.
	Flash(key string, value any)
	// Regenerate issues a new session id keeping the data (call on login
	// and privilege changes to prevent session fixation).
	Regenerate()
	// Invalidate clears all data and issues a new id (call on logout).
	Invalidate()
	// ID returns the session id (meaningful for server-side stores).
	ID() string
}

Session is the request session as seen by handlers. The session package implements it; web only depends on this interface.

func SessionFrom

func SessionFrom(ctx context.Context) Session

SessionFrom returns the session stored in ctx, or nil.

type URLGenerator

type URLGenerator interface {
	URL(name string, params ...any) (string, error)
}

URLGenerator builds URLs for named routes.

type ValidationHook

type ValidationHook func(c *Ctx, verr *errs.ValidationError) bool

ValidationHook lets session-aware code (flash + redirect back) handle validation errors for classic HTML form posts. It reports whether it wrote a response.

type View

type View interface {
	Render(ctx context.Context, w io.Writer) error
}

View is a self-rendering component; templ.Component satisfies it.

Jump to

Keyboard shortcuts

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