package lazycontroller ¶
import "golazy.dev/lazycontroller"
Constants ¶
const LazyDevOpenEditorPath ¶
const LazyDevOpenEditorPath = "/_golazy/open-editor"
Functions ¶
func DefaultViews ¶
DefaultViews returns the framework-owned fallback view filesystem.
lazyapp layers application views over these files so apps can override layouts/app.html.tpl or app/error.html.tpl with ordinary view files.
func DefaultViews() (fs.FS, error)
func DetailErrors ¶
func DetailErrors(ctx context.Context) bool
func Error ¶
func Error(status int, err error) error
func ErrorHandler ¶
func ErrorHandler(ctx context.Context) func(http.Handler) http.Handler
func LazyDevContext ¶
func LazyDevContext(ctx context.Context) context.Context
func PanicError ¶
func PanicError(recovered any) error
func RegisterFormat ¶
RegisterFormat maps one or more content types to a controller format.
func RegisterFormat(format Format, contentTypes ...string)
func RegisterFormatSuffix ¶
RegisterFormatSuffix maps one or more URL suffixes to a controller format.
func RegisterFormatSuffix(format Format, suffixes ...string)
func RegisterLazyDevHandlers ¶
func RegisterLazyDevHandlers(controlPlane *lazycontrolplane.ControlPlane)
func ReportController ¶
func ReportController(r *http.Request, controller any) bool
func ReportError ¶
func ReportError(r *http.Request, controller any, err error) bool
func ResetResponse ¶
func ResetResponse(w http.ResponseWriter) bool
func StatusCode ¶
func StatusCode(err error) int
func WasResponseSent ¶
func WasResponseSent(w http.ResponseWriter) bool
func WithDetailErrors ¶
func WithDetailErrors(ctx context.Context) context.Context
func WithErrorPages ¶
func WithErrorPages(ctx context.Context, files fs.FS) context.Context
func WithFormat ¶
WithFormat returns a context that carries an explicitly requested format.
func WithFormat(ctx context.Context, format Format) context.Context
func WithOpenEditorPath ¶
WithOpenEditorPath records the development endpoint used by error pages to open a backtrace frame in the user's editor.
func WithOpenEditorPath(ctx context.Context, path string) context.Context
func WithPathFor ¶
WithPathFor returns a context carrying the application's route path helper.
func WithPathFor(ctx context.Context, pathFor PathForFunc) context.Context
func WithRenderer ¶
func WithRenderer(ctx context.Context, renderer *Renderer) context.Context
func WriteError ¶
func WriteError(w http.ResponseWriter, _ *http.Request, err error)
func WriteErrorDetail ¶
func WriteErrorDetail(w http.ResponseWriter, _ *http.Request, err error)
func WriteErrorFallback ¶
func WriteErrorFallback(ctx context.Context, w http.ResponseWriter, r *http.Request) bool
func WriteErrorPage ¶
func WriteErrorPage(ctx context.Context, w http.ResponseWriter, r *http.Request, status int) bool
func WriteFile ¶
func WriteFile(ctx context.Context, w http.ResponseWriter, r *http.Request, file string, status int) error
Types ¶
type Base ¶
type Base struct {
// contains filtered or unexported fields
}
func NewBase ¶
func NewBase(ctx context.Context, viewPath ...string) (Base, error)
func (b *Base) Alternate ¶
func (b *Base) Alternate(language, url string) *lazyseo.Meta
func (b *Base) Author ¶
func (b *Base) Author(value string) *lazyseo.Meta
func (b *Base) BindRequest ¶
func (b *Base) BindRequest(w http.ResponseWriter, r *http.Request, route lazyview.Route) error
func (b *Base) Cache ¶
func (b *Base) Cache() *lazycache.Cache
func (b *Base) CacheKey ¶
func (b *Base) CacheKey(parts ...any) bool
func (b *Base) CacheKeyF ¶
func (b *Base) CacheKeyF(parts ...any) bool
func (b *Base) Canonical ¶
func (b *Base) Canonical(value string) *lazyseo.Meta
func (b *Base) ContentType ¶
ContentType sets the response Content-Type header.
func (b *Base) ContentType(value string)
func (b *Base) Decode ¶
Decode parses the current request form and decodes submitted fields into target.
func (b *Base) Decode(target any) error
func (b *Base) Description ¶
func (b *Base) Description(value string) *lazyseo.Meta
func (b *Base) Format ¶
Format returns the negotiated response format for the current request.
func (b *Base) Format() Format
func (b *Base) HandleError ¶
func (b *Base) HandleError(w http.ResponseWriter, r *http.Request, err error) error
func (b *Base) Header ¶
Header returns the response header map for the current controller request.
func (b *Base) Header() http.Header
func (b *Base) Helper ¶
func (b *Base) Helper(name string, helper any)
func (b *Base) Helpers ¶
func (b *Base) Helpers(helpers map[string]any)
func (b *Base) Is ¶
Is reports whether the current request resolved to format.
func (b *Base) Is(format Format) bool
func (b *Base) IsGIF ¶
func (b *Base) IsGIF() bool
func (b *Base) IsHTML ¶
func (b *Base) IsHTML() bool
func (b *Base) IsImage ¶
func (b *Base) IsImage() bool
func (b *Base) IsJPEG ¶
func (b *Base) IsJPEG() bool
func (b *Base) IsJSON ¶
func (b *Base) IsJSON() bool
func (b *Base) IsPNG ¶
func (b *Base) IsPNG() bool
func (b *Base) IsSSE ¶
func (b *Base) IsSSE() bool
func (b *Base) IsTurboFrame ¶
func (b *Base) IsTurboFrame() bool
func (b *Base) IsTurboStream ¶
func (b *Base) IsTurboStream() bool
func (b *Base) JSONLD ¶
func (b *Base) JSONLD(value any) *lazyseo.Meta
func (b *Base) Kind ¶
func (b *Base) Kind(kind lazyseo.PageKind) *lazyseo.Meta
func (b *Base) Language ¶
func (b *Base) Language(value string) *lazyseo.Meta
func (b *Base) LastUpdated ¶
func (b *Base) LastUpdated(value time.Time) *lazyseo.Meta
func (b *Base) Layout ¶
func (b *Base) Layout(layout string)
func (b *Base) Locale ¶
func (b *Base) Locale(value string) *lazyseo.Meta
func (b *Base) Metadata ¶
func (b *Base) Metadata(model any) *lazyseo.Meta
func (b *Base) MustPathFor ¶
MustPathFor builds a path and panics when the route cannot be generated.
func (b *Base) MustPathFor(name string, values ...any) string
func (b *Base) NoLayout ¶
func (b *Base) NoLayout()
func (b *Base) OpenGraph ¶
func (b *Base) OpenGraph(value lazyseo.OpenGraph) *lazyseo.Meta
func (b *Base) OpenGraphType ¶
func (b *Base) OpenGraphType(value string) *lazyseo.Meta
func (b *Base) PathFor ¶
PathFor builds a path from a named route and route parameter values.
func (b *Base) PathFor(name string, values ...any) (string, error)
func (b *Base) PublishedTime ¶
func (b *Base) PublishedTime(value time.Time) *lazyseo.Meta
func (b *Base) Redirect ¶
Redirect sends an HTTP redirect and marks the controller response as written. It defaults to 302 Found. Pass a single 3xx status such as http.StatusMovedPermanently or http.StatusSeeOther to override it.
func (b *Base) Redirect(location string, status ...int) error
func (b *Base) RedirectBack ¶
RedirectBack is an alias for RedirectBackOrTo.
func (b *Base) RedirectBack(fallbackLocation string, status ...int) error
func (b *Base) RedirectBackOrTo ¶
RedirectBackOrTo redirects to the same-host Referer header when present, otherwise it redirects to fallbackLocation.
func (b *Base) RedirectBackOrTo(fallbackLocation string, status ...int) error
func (b *Base) RedirectTo ¶
RedirectTo is an alias for Redirect for controllers that prefer Rails-style wording in action code.
func (b *Base) RedirectTo(location string, status ...int) error
func (b *Base) Render ¶
func (b *Base) Render(view string) error
func (b *Base) RenderHTML ¶
func (b *Base) RenderHTML(view string) error
func (b *Base) RenderSVGString ¶
func (b *Base) RenderSVGString(view string, variants ...string) (string, error)
func (b *Base) RenderTurboFrame ¶
func (b *Base) RenderTurboFrame(id string, opts ...lazyturbo.FrameOption) error
func (b *Base) Request ¶
func (b *Base) Request() *http.Request
func (b *Base) ResetRequest ¶
func (b *Base) ResetRequest()
func (b *Base) Respond ¶
Respond runs the response handler matching the request format.
func (b *Base) Respond(responses Responses) error
func (b *Base) ReturnFile ¶
func (b *Base) ReturnFile(file string, status int) error
func (b *Base) SEO ¶
func (b *Base) SEO(options ...lazyseo.Option) *lazyseo.Meta
func (b *Base) SEOImage ¶
func (b *Base) SEOImage(value string) *lazyseo.Meta
func (b *Base) SEOImageAlt ¶
func (b *Base) SEOImageAlt(value string) *lazyseo.Meta
func (b *Base) SSEStream ¶
SSEStream starts a Server-Sent Events response for the current controller request.
func (b *Base) SSEStream(opts ...lazysse.Option) (*lazysse.Stream, error)
func (b *Base) SchemaType ¶
func (b *Base) SchemaType(value string) *lazyseo.Meta
func (b *Base) ServeErrorPage ¶
func (b *Base) ServeErrorPage(w http.ResponseWriter, r *http.Request, status int) bool
func (b *Base) Set ¶
func (b *Base) Set(name string, value any)
func (b *Base) SetLater ¶
SetLater stores a Valuer and starts loading it immediately.
func (b *Base) SetLater(name string, loader any) Valuer
func (b *Base) SetTurboFrameOptions ¶
func (b *Base) SetTurboFrameOptions(opts ...lazyturbo.FrameOption)
func (b *Base) SetWhenNeeded ¶
SetWhenNeeded stores a Valuer that loads on its first Value call.
func (b *Base) SetWhenNeeded(name string, loader any) Valuer
func (b *Base) Status ¶
Status sets the HTTP status code used by the next controller render.
It does not write the response immediately, so actions can still rely on automatic rendering after setting a non-200 status.
func (b *Base) Status(code int)
func (b *Base) Title ¶
func (b *Base) Title(value string) *lazyseo.Meta
func (b *Base) TwitterCard ¶
func (b *Base) TwitterCard(value lazyseo.TwitterCard) *lazyseo.Meta
func (b *Base) TwitterCardType ¶
func (b *Base) TwitterCardType(value string) *lazyseo.Meta
func (b *Base) Type ¶
func (b *Base) Type(value string) *lazyseo.Meta
func (b *Base) URL ¶
func (b *Base) URL(value string) *lazyseo.Meta
func (b *Base) URLFrom ¶
URLFrom returns location when it is safe to use as an internal redirect target for the current request. Absolute URLs must match the request host; relative URLs must be absolute paths such as "/posts".
func (b *Base) URLFrom(location string) string
func (b *Base) Variants ¶
func (b *Base) Variants(variants ...string)
func (b *Base) Wants ¶
Wants runs the response handler matching the request format.
func (b *Base) Wants(formats Formats) error
type BeforeAction ¶
BeforeAction runs after request binding and before the routed action.
type BeforeAction interface {
BeforeAction() error
}
type Format ¶
Format identifies the response representation selected for a request.
type Format string
func FormatFromContentType ¶
FormatFromContentType resolves a content type to a registered format.
func FormatFromContentType(contentType string) (Format, bool)
func FormatFromRequest ¶
FormatFromRequest returns the request format inferred from Turbo headers, explicit route metadata, and Accept.
func FormatFromRequest(r *http.Request) Format
func FormatFromSuffix ¶
FormatFromSuffix resolves a URL suffix to a registered format.
func FormatFromSuffix(suffix string) (Format, bool)
func NewFormat ¶
NewFormat registers a custom MIME type and returns its symbolic format.
func NewFormat(contentType string, options ...FormatOption) Format
type FormatOption ¶
FormatOption configures a custom format created by NewFormat.
type FormatOption func(*newFormatOptions)
func As ¶
As sets the symbolic format name returned by NewFormat.
func As(name string) FormatOption
func Suffix ¶
Suffix registers one or more URL suffixes for a custom format.
func Suffix(suffixes ...string) FormatOption
type Formats ¶
type Formats map[Format]func() error
type HTTPError ¶
type HTTPError struct {
Status int
Err error
}
func (e *HTTPError) Error ¶
func (e *HTTPError) Error() string
func (e *HTTPError) Unwrap ¶
func (e *HTTPError) Unwrap() error
type PathForFunc ¶
PathForFunc builds a path from a named route and route parameter values.
type PathForFunc func(name string, values ...any) (string, error)
type Renderer ¶
Renderer is the application view renderer.
type Renderer = lazyview.Views
func NewRenderer ¶
func NewRenderer(views fs.FS) (*Renderer, error)
func RendererFromContext ¶
func RendererFromContext(ctx context.Context) (*Renderer, bool)
type RequestBinder ¶
RequestBinder prepares a controller instance for one request.
type RequestBinder interface {
BindRequest(http.ResponseWriter, *http.Request, lazyview.Route) error
}
type RequestResetter ¶
RequestResetter clears request-specific references before a controller returns to a pool.
type RequestResetter interface {
ResetRequest()
}
type Responses ¶
type Responses = Formats
type URLParams ¶
URLParams appends query parameters to a generated route path.
type URLParams = lazypath.URLParams
type Valuer ¶
Valuer resolves request-local view data when a template or controller needs it.
type Valuer interface {
Value() (any, error)
}
Package lazycontroller provides the request-local controller layer used by a GoLazy application: controller lifecycle hooks, view rendering, response helpers, cache-key helpers, deferred view values, typed HTTP errors, redirects, content negotiation, SEO convenience methods, and Server-Sent Events entrypoints.
In a normal GoLazy app, package lazyapp wires this package together with lazyroutes and lazyview. lazyapp creates the lazyview renderer, stores it in the application context with WithRenderer, asks lazyroutes to create or reuse a controller for each matched route, calls BindRequest with the matched lazyview.Route, runs BeforeAction when the controller implements it, and reports returned action errors through ErrorHandler. Controllers normally embed Base:
type PostsController struct { lazycontroller.Base } func (c *PostsController) Index() error { c.Set("Title", "Posts") return nil }When an action returns nil without writing a response, the lazyapp/lazyroutes integration renders the view matching the route action. Calling Render("") explicitly does the same lookup inside Base: the empty view name falls back to the current route action, lower-cased. Render passes controller data, helpers, route metadata, selected variants, layout choice, request context, and the ResponseWriter to lazyview.
The package can also be used without lazyapp. Create a Renderer from an fs.FS, put it in context with WithRenderer, construct Base with NewBase, and bind each request with BindRequest before rendering. See ExampleBase_Render for the smallest standalone HTTP rendering setup.
Rendering conventions
NewRenderer is a thin wrapper around lazyview.New. The filesystem must contain the views and layouts lazyview expects, including the default app layout when using the default Base layout. NewBase reads the renderer from context and keeps that application context as the fallback for each request. BindRequest then layers the request context above the application context so request values win while renderer, route helper, cache, build version, and other application-scoped values remain visible.
Set and Helper provide request-local variables and functions to lazyview. Helpers can also be registered in bulk with Helpers. Package lazyapp normally collects application helpers from packages such as lazyassets and passes them into the renderer path; controller helpers are for per-request additions or overrides. Layout selects a named layout, NoLayout disables layout rendering, and Variants asks lazyview to prefer variant-specific templates.
Render chooses the request format with Format, renders HTML with the selected layout, and renders non-HTML formats without a layout. RenderHTML forces HTML. RenderSVGString renders an SVG view to a string without writing the response. Turbo Frame requests are detected through package lazyturbo: a Turbo-Frame request renders the matching HTML partial and wraps it in a frame response. RenderTurboFrame renders an explicit frame partial named "<id>_frame".
Response and cache helpers
Status changes the status code used by the next render without writing the response immediately. Header and ContentType mutate the current response headers. Redirect and its aliases validate internal or absolute locations, write the redirect immediately, and mark the response as sent.
CacheKey and CacheKeyF connect controller rendering to lazycache. They look up the cache from context, build a key from the build version, variants, route metadata, format, and the provided parts, and short-circuit rendering when a cached body is found. CacheKey scopes the provided parts after the route metadata. CacheKeyF treats the provided parts as the full key after the build and variant scope.
Formats and content negotiation
FormatFromRequest resolves Turbo Frame headers first, then an explicit WithFormat context value, then Accept. FormatFromSuffix and FormatFromContentType expose the global registry used by lazyroutes and custom integrations. NewFormat registers a MIME type and route suffix for application formats beyond HTML, JSON, Turbo Stream, common images, and SSE.
Wants and Respond run exactly one handler from a Formats map based on the negotiated request format. They set Vary headers for Accept and Turbo-Frame, return a 406 HTTPError when no offered format matches, and temporarily make Base.Format report the selected format while the handler runs.
Deferred view values
SetLater and SetWhenNeeded store Valuer values in the view data map. A Valuer exposes Value() (any, error), which lazyview template engines can resolve when the template actually needs the value. SetLater starts the loader immediately in a goroutine, useful for overlapping slow data loading with other controller work. SetWhenNeeded waits until the first Value call. Loaders must be functions returning (value, error) and may accept context.Context; that context is the current request context layered with the application context.
Errors and development hooks
Error wraps an error with an HTTP status, StatusCode reads that status, and PanicError converts a recovered panic into an error carrying a backtrace. ErrorHandler is middleware used by lazyapp to catch reported action errors and panics. If the controller implements HandleError(http.ResponseWriter, *http.Request, error), that method gets the first chance to render the error. Otherwise ErrorHandler writes development details when DetailErrors is enabled or falls back to static error pages registered with WithErrorPages.
RegisterLazyDevHandlers exists only in files built with the lazydev build tag. lazyapp registers those handlers on its lazycontrolplane.ControlPlane during development builds. The current handler exposes the editor-opening endpoint used by detailed error pages; production builds do not include that endpoint.