Documentation
¶
Overview ¶
Package print is a GoFastr battery for printable documents. A host declares named, route-addressable print documents — the print-battery equivalent of a screen/route — and the battery server-renders each into a clean, chrome-free, print-friendly HTML page (its own @page size and margins, the browser's native print dialog, no nav/sidebar/runtime).
The HTML core is pure Go with no extra dependencies. Real PDF output is opt-in through the pluggable PDFRenderer interface; the headless-Chromium implementation lives in the separate battery/print/chromepdf subpackage so this package never imports chromedp.
See https://github.com/DonaldMurillo/gofastr for documentation.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrForbidden = errors.New("print: forbidden")
ErrForbidden is the sentinel a Document.Build returns to render a clean 403. Prefer an Access policy for authz; this is for cases only Build can decide.
var ErrNotFound = errors.New("print: document not found")
ErrNotFound is the sentinel a Document.Build returns when the requested resource doesn't exist (or the caller may not see it). It renders a clean 404 instead of a 500.
Functions ¶
func Public ¶
Public allows every request, authenticated or not. Use only for documents that contain no per-user data.
func RequireAuth ¶
RequireAuth allows the request only when an authenticated user is present in context (set by the framework's auth chain). It is the default policy, so per-user documents are never world-readable unless a Document explicitly opts into Public.
Types ¶
type AccessPolicy ¶
AccessPolicy gates a print document. It runs with the request and returns the HTTP status to short-circuit with, plus a message. A zero status means "allow". Policies run BEFORE Document.Build, so an unauthorized caller never triggers a data load.
func RequireOwner ¶
func RequireOwner(owns func(r *http.Request, user any) bool) AccessPolicy
RequireOwner allows the request only when a user is authenticated AND the owns callback returns true for that user. The user is passed as the opaque value the auth chain stored (handler.GetUser); the host asserts its own concrete user type. The framework cannot know an app's ownership model, so this delegates it.
type Battery ¶
type Battery struct {
// contains filtered or unexported fields
}
Battery is the framework.Battery implementation for printable documents.
func New ¶
New constructs the print battery. Pass the result to framework.App.RegisterBattery after declaring documents with Document.
func (*Battery) Document ¶
Document declares a printable document. Returns the battery for chaining. Panics on a duplicate name, an invalid declaration, or a call after Init — documents are immutable once routes are mounted.
func (*Battery) Init ¶
Init implements framework.Battery. Mounts every declared document's HTML route, its sibling PDF route, and the shared auto-print script.
type Config ¶
type Config struct {
// PathPrefix is the URL prefix for all print documents.
// Defaults to "/print". A trailing slash is trimmed.
PathPrefix string
// DefaultPage is the page setup inherited by documents that don't
// set their own. Zero value resolves to A4 portrait, 12mm margins.
DefaultPage PageConfig
// DefaultAccess gates documents whose Access is nil. Defaults to
// RequireAuth — so per-user documents are never world-readable
// unless a document explicitly opts into Public.
DefaultAccess AccessPolicy
// AppCSSURL, when non-empty, is linked into every print shell so
// documents inherit the host's design tokens (var(--*)). Typically
// "/__gofastr/app.css". Empty = print base only. runtime.js is
// NEVER linked.
AppCSSURL string
// BaseURL is the canonical, host-configured origin of the app (e.g.
// "https://app.example.com"), used ONLY on the PDF path to make the
// app.css link absolute so headless Chromium — which renders an
// in-memory data: document with no origin — can fetch the tokens.
// It is deliberately NOT derived from the request Host header, which
// is client-controlled and would otherwise let a spoofed Host point
// the server-side fetch at an arbitrary/internal address (SSRF).
// When empty, the PDF app.css link stays relative (and simply won't
// resolve in the data: document — PDFs render with the print base
// only). The HTML path never needs this.
BaseURL string
// PDFRenderer is the pluggable PDF backend. nil = PDF routes return
// 501. The chromedp-backed implementation lives in the separate
// battery/print/chromepdf subpackage so this package imports no
// chromedp.
PDFRenderer PDFRenderer
// PrintBaseCSS overrides the built-in readable print base stylesheet.
// Empty = use the battery default.
PrintBaseCSS string
}
Config configures the print battery.
type Document ¶
type Document struct {
// Name is a stable identifier. It is the registry key, the default
// PDF filename stem, and what shows up in logs. Required, unique
// per battery.
Name string
// Path is the route relative to Config.PathPrefix. It supports the
// router's Go-1.22 {param} syntax, e.g. "/invoice/{id}". Required,
// must begin with "/".
Path string
// Title is the document <title> (and the default PDF filename stem
// when Name is unsuitable). For per-request titles set TitleFunc.
Title string
// TitleFunc, when non-nil, overrides Title per request — e.g.
// "Invoice #1042". The returned string is HTML-escaped by the shell.
TitleFunc func(r *http.Request) string
// Build produces the document body for one request. This is the
// host's hook: it reads route params via router.Param(r, …), closes
// over the host's own services/DB to load data, and returns the body
// component. The component is rendered with component.SafeRenderCtx
// (panic-safe, RenderCtx-aware).
//
// Return ErrNotFound to render a clean 404; any other error renders a
// clean 500 status page — never a stack trace. Required.
Build func(r *http.Request) (component.Component, error)
// Page overrides the battery default PageConfig for this document
// (an invoice may be A4 portrait while a receipt is an 80mm roll).
// nil = inherit Config.DefaultPage.
Page *PageConfig
// Access gates the document, evaluated BEFORE Build so an
// unauthorized caller never triggers a data load. nil = inherit
// Config.DefaultAccess (which itself defaults to RequireAuth).
Access AccessPolicy
// AutoPrint, when true, opens the browser print dialog on load. It
// is implemented as a CSP-safe external script (see autoPrintPath),
// not an inline <script>. Ignored on the PDF path.
AutoPrint bool
// Stylesheet is optional document-specific CSS appended after the
// generated @page rules and the print base. It is trusted host
// input (not user input) and injected verbatim into a <style>.
Stylesheet string
}
Document declares one named, route-addressable print document — the print-battery equivalent of a screen/route. Each document mounts a chrome-free, print-friendly HTML route (and, when a PDFRenderer is configured, a sibling PDF route).
type Margins ¶
Margins holds the four page margins as CSS lengths (e.g. "12mm"). An empty side inherits the battery default ("12mm").
type Orientation ¶
type Orientation string
Orientation is the page orientation for named sizes.
const ( Portrait Orientation = "portrait" Landscape Orientation = "landscape" )
The supported orientations.
type PDFRenderer ¶
type PDFRenderer interface {
// RenderPDF converts the shelled HTML into a PDF. page carries the
// resolved page setup (paper size + margins). baseURL is the
// scheme+host origin of the originating request, so an adapter can
// resolve absolute resource links (e.g. the app.css stylesheet)
// against the live host.
RenderPDF(ctx context.Context, html string, page PageConfig, baseURL string) ([]byte, error)
}
PDFRenderer turns a fully-assembled, standalone print HTML document into PDF bytes. It is the pluggable seam that keeps this package free of any headless-browser dependency: the chromedp-backed implementation lives in battery/print/chromepdf.
type PageConfig ¶
type PageConfig struct {
Size PageSize
Orientation Orientation
Margin Margins
CustomWidth string // only when Size == Custom, e.g. "80mm"
CustomHeight string // only when Size == Custom, e.g. "auto"
}
PageConfig is the physical page setup. It is turned into @page CSS for the HTML shell and into paper/margin flags for the PDF renderer.
func A4Portrait ¶
func A4Portrait(m Margins) PageConfig
A4Portrait is a convenience constructor for the most common page setup.
func LetterPortrait ¶
func LetterPortrait(m Margins) PageConfig
LetterPortrait is a convenience constructor for US Letter portrait.
func (PageConfig) Ptr ¶
func (p PageConfig) Ptr() *PageConfig
Ptr returns a pointer to a copy of p, for use in Document.Page.