Documentation
¶
Overview ¶
Package errors provides an optional renderer for render failures.
Index ¶
- Constants
- func ExtractTemplateLocation(err error) string
- func Respond(w http.ResponseWriter, r *http.Request, parent *partial.Partial, status int, ...)
- func Stage(options ...Option) partial.RenderStage
- func StyleHash() string
- func StylesheetFS() fs.FS
- type Data
- type Mode
- type Option
- func WithFlash(message func(ctx *partial.RenderContext, data Data) string) Option
- func WithFragmentTemplate(path string) Option
- func WithLang(lang func(ctx *partial.RenderContext, data Data) string) Option
- func WithMessage(message func(ctx *partial.RenderContext, data Data) string) Option
- func WithMode(mode Mode) Option
- func WithTemplate(path string) Option
- func WithTitle(title func(ctx *partial.RenderContext, data Data) string) Option
Constants ¶
const EventTemplateFailed = "ext.errors.template_failed"
EventTemplateFailed is emitted, as a warning, when a custom error template (see WithTemplate) fails and the built-in markup answers instead.
const RenderKindError partial.RenderKind = "error"
RenderKindError is the renderer kind used for error fragments.
const SafeMessage = "Something went wrong. Please try again."
SafeMessage is Data.Message in ModeSafe: it tells nothing of the error, which is for the log.
const StylesheetName = "partial-errors.css"
StylesheetName is the name of the stylesheet in StylesheetFS.
Variables ¶
This section is empty.
Functions ¶
func ExtractTemplateLocation ¶
ExtractTemplateLocation extracts a template file and line from an error message.
func Respond ¶ added in v0.15.0
func Respond(w http.ResponseWriter, r *http.Request, parent *partial.Partial, status int, err error)
Respond answers r for err, an error that happened outside a render, such as a form post whose handler failed to save it, the way the Stage of parent's tree answers a render that failed: with its error page, its error fragment or its error flash message, rendered with parent's functions, includes and models, with the text of WithMessage, and written with status. parent is the partial whose tree has the Stage, such as the root of a site's pages. The response is never cached.
if err := comments.Add(r.Context(), form); err != nil {
log.Error("add comment", "error", err)
errors.Respond(w, r, root, http.StatusInternalServerError, err)
return
}
A full-page request gets the error page. A partial request, such as an htmx form post, gets the error flash message with WithFlash, out of band, leaving the request's target as it is (htmx's HX-Reswap: none). Without a flash message it gets the error page for a 5xx status, which the interactions client shows as the whole page for a link or form with clientAttrs "reloadOnError", and the error fragment for any other status, such as 429, which the client library swaps into the target where it swaps such answers (htmx 4 does; htmx 2 swaps no error response). Data.Status is status, and Data.PartialID and Data.Templates are empty: no partial failed. A status of 0 or less is 500.
When parent's tree has no Stage, Respond answers with the built-in markup, in ModeSafe. It writes the response itself, as http.Error does: the caller writes nothing more.
func Stage ¶
func Stage(options ...Option) partial.RenderStage
Stage returns a render stage that handles error render contexts: an error page with status 500, or for partial requests an error fragment with status 200, which the client swaps in place. Under partial.FailResponse, partial.Write keeps status 500 for the fragment as well. Respond answers an error that happened outside a render with the same stage.
func StyleHash ¶ added in v0.15.0
func StyleHash() string
StyleHash returns the Content-Security-Policy hash source of the inline <style> element of the built-in error page, 'sha256-…' with its quotes, for a policy without 'unsafe-inline':
style-src 'self' 'sha256-…'
Add it to the policy of the error page, and to that of every page whose links or forms carry data-partial-reload-on-error: the interactions client writes the error page of a failed POST into the page that sent it, under that page's policy. The hash changes only when go-partial changes the page's style; an application that answers with an error template of its own (WithTemplate) needs none. The built-in error fragment has no inline style; see StylesheetFS.
func StylesheetFS ¶ added in v0.15.0
StylesheetFS returns a file system that holds the CSS of the built-in error fragment as StylesheetName, for applications that serve, fingerprint and version it with their other assets. The fragment takes the place of a failing part of a page and answers a failing partial request inside the application's own page. It carries no style of its own, so that a Content-Security-Policy without 'unsafe-inline' lets it through: serve this file and link it from the application's layout, copy its rules into the application's CSS, or style the classes go-partial-error, go-partial-error__title, go-partial-error__message and go-partial-error__details differently. Unstyled, the fragment reads as a heading, a paragraph and a list.
assets := partial.Overlay(appAssets, errors.StylesheetFS()) <link rel="stylesheet" href="/assets/partial-errors.css">
Types ¶
type Data ¶
type Data struct {
Error error
Message string
Title string
Lang string
Status int
PartialID string
Templates []string
Request *http.Request
URL *url.URL
Location string
Detailed bool
TemplateLabel string
}
Data is the template data used by the error renderer.
Message is the error's message in ModeDetailed, and SafeMessage in ModeSafe, so an error template can show it in both; WithMessage chooses another. Error and Location tell what failed: show them only when Detailed is true. Status is the status of the error: the one given to Respond, or 500 for a render that failed. Title is the heading of the page, the status text of Status (http.StatusText) or the text of WithTitle. PartialID and Templates name the partial that failed to render, in ModeDetailed only; they are empty in ModeSafe, and for an error of Respond, which happened outside a render. Lang is the language of the page, the text of WithLang, which the built-in page writes as its lang attribute, en when it is empty.
func BuildData ¶
func BuildData(ctx *partial.RenderContext, mode Mode) Data
BuildData converts a render context into error template data.
func FromContext ¶ added in v0.15.0
FromContext returns the Data of the error page or error fragment that a custom error template (see WithTemplate and WithFragmentTemplate) renders with ctx, and reports whether ctx is the context of such a render: the context a template function with a context.Context parameter is called with while the template, or a partial it includes, renders. A function that writes something of the page that failed, such as its structured data, can leave it out of the error page.
func structuredData(ctx context.Context) template.HTML {
if _, failed := errors.FromContext(ctx); failed {
return ""
}
...
}
type Option ¶
type Option func(*config)
Option configures the error renderer.
func WithFlash ¶ added in v0.15.0
func WithFlash(message func(ctx *partial.RenderContext, data Data) string) Option
WithFlash answers a partial request that fails to render with an error flash message instead of the error fragment: added to the flash target out of band, with the flash template and target of the tree's exp/flash Stage, as the page's own messages appear, and leaving the request's target as it is (htmx's HX-Reswap: none). The message is the text that message returns, such as a translated sentence; a nil message, or an empty text, is Data.Message: SafeMessage in ModeSafe, the error in ModeDetailed, or the text of WithMessage. Failing parts of a page, and trees without a flash stage, still get the error fragment.
root.Use(flash.Stage(flash.WithTemplate("flash.gohtml")), errors.Stage(errors.WithFlash(nil)))
Under partial.FailResponse the response keeps status 500: with htmx 4, let the page swap the out-of-band parts of 5xx responses with hx-status:5xx="swap:none" (connector.Attr.KeepOnServerError); htmx 2 swaps no error response.
func WithFragmentTemplate ¶ added in v0.15.0
WithFragmentTemplate renders the error fragment, which takes the place of a failing part of a page and answers a failing partial request, with the template at path, such as a toast, instead of the built-in fragment; see WithTemplate. Without WithTemplate, the template renders the error page too.
func WithLang ¶ added in v0.15.0
func WithLang(lang func(ctx *partial.RenderContext, data Data) string) Option
WithLang sets Data.Lang, the language of the error page, to the text that lang returns, such as the language of the page that failed, so the built-in page, whose text WithMessage may translate, has the right lang attribute; a template of the application's own can write it too. lang is called for each error render, with the data it changes; an empty text leaves Data.Lang empty, which the built-in page writes as en.
errors.Stage(errors.WithLang(func(ctx *partial.RenderContext, _ errors.Data) string {
return localization.Locale(ctx)
}))
func WithMessage ¶ added in v0.15.0
func WithMessage(message func(ctx *partial.RenderContext, data Data) string) Option
WithMessage sets Data.Message, which the error page, the error fragment and the error flash message (see WithFlash) show, to the text that message returns, such as a translation of SafeMessage in the request's language. message is called for each error render, in both modes, with the data it changes: Data.Message is SafeMessage or, when Data.Detailed is true, the error. An empty text keeps it.
errors.Stage(errors.WithMessage(func(ctx *partial.RenderContext, data errors.Data) string {
if data.Detailed {
return ""
}
return translate(ctx.Request, data.Message)
}))
func WithTemplate ¶ added in v0.15.0
WithTemplate renders the error page, the failure response of a full request, with the template at path, such as a theme's 500.gohtml, instead of the built-in page. The template is read from the file system of the partial that failed and renders as its child, with its functions, stages, includes and @model values; its dot is a Data, which it can declare with @dot github.com/donseba/go-partial/ext/errors.Data. Data.Message is SafeMessage in ModeSafe and the error in ModeDetailed, or the text of WithMessage; Data.Error holds the error in both: show it only when Data.Detailed is true. The template renders with the includes the partial gives its descendants, so a root with SetChildIncludes("partials/*.gohtml") gives an error page the partials its pages use. When the template itself fails, the built-in page is rendered. Without WithFragmentTemplate, the template answers partial requests too.
func WithTitle ¶ added in v0.15.0
func WithTitle(title func(ctx *partial.RenderContext, data Data) string) Option
WithTitle sets Data.Title, the heading of the built-in error page and fragment, to the text that title returns, such as a translation of the status text in the request's language. title is called for each error render, with the data it changes: Data.Title is the status text of Data.Status (http.StatusText). An empty text keeps it. In ModeDetailed, a failed render keeps the heading "Template render error", which is for the developer.
errors.Stage(errors.WithTitle(func(ctx *partial.RenderContext, data errors.Data) string {
return translate(ctx.Request, data.Title)
}))