Documentation
¶
Overview ¶
Package kit is the server runtime for Tern applications.
A route directory's Go package defines what the route does on the server, by exporting:
func Load(ctx *kit.Ctx) (T, error) // data for +page.svelte
func LayoutLoad(ctx *kit.Ctx) (T, error) // data for +layout.svelte
var Actions = kit.Actions{...} // form actions for the page
func GET(ctx *kit.Ctx) error // endpoint handlers: GET, POST, …
T must encode to a JSON object: a struct or a map. Its JSON is passed to the Svelte component as data, with TypeScript types generated from T.
Slow data can be streamed: put a Deferred in the data, created with Defer, and render it with {#await} in Svelte.
Errors control the response. Return Error or NotFound for an expected error page, Redirect to redirect, and Fail from an action to report a validation error. Any other error is logged and shown as "Internal Error".
`tern gen` writes tern.gen.go, which wires every route into a Manifest and defines ternApp. A typical main.go:
func main() {
app, err := ternApp(kit.WithHook(auth))
if err != nil {
log.Fatal(err)
}
if err := app.ListenAndServe(); err != nil {
log.Fatal(err)
}
}
Index ¶
- Constants
- Variables
- func ClientIP(r *http.Request) string
- func DecodeQuery(q url.Values, dst any) error
- func Error(status int, message string) error
- func Fail(status int, data any) error
- func FieldError(field, message string) error
- func FormError(message string) error
- func NotFound() error
- func Parent[T any](c *Ctx) (T, error)
- func QueryName(f reflect.StructField) string
- func Redirect(status int, location string) error
- type ActionFunc
- type Actions
- type App
- type Ctx
- func (c *Ctx) BasePath() string
- func (c *Ctx) ClientIP() string
- func (c *Ctx) Content() fs.FS
- func (c *Ctx) Cookie(name string) (string, bool)
- func (c *Ctx) Deadline() (time.Time, bool)
- func (c *Ctx) DeleteCookie(name string)
- func (c *Ctx) Depends(keys ...string)
- func (c *Ctx) Dev() bool
- func (c *Ctx) Done() <-chan struct{}
- func (c *Ctx) Err() error
- func (c *Ctx) EventStream(fn func(ctx context.Context, s *EventStream) error) error
- func (c *Ctx) Form() (url.Values, error)
- func (c *Ctx) Header(name string) string
- func (c *Ctx) JSON(status int, v any) error
- func (c *Ctx) Locale() string
- func (c *Ctx) Param(name string) string
- func (c *Ctx) Params() map[string]string
- func (c *Ctx) Path(p string) string
- func (c *Ctx) RouteID() string
- func (c *Ctx) SetBodyLimit(n int64)
- func (c *Ctx) SetCookie(ck *http.Cookie)
- func (c *Ctx) SetHeader(name, value string)
- func (c *Ctx) SetLocale(locale string)
- func (c *Ctx) T(key string, params ...map[string]any) string
- func (c *Ctx) Text(status int, s string) error
- func (c *Ctx) URL() *url.URL
- func (c *Ctx) Value(key any) any
- func (c *Ctx) WebSocket(opts *WebSocketOptions, fn func(ctx context.Context, ws *WebSocket) error) error
- func (c *Ctx) Writer() http.ResponseWriter
- type Deferred
- type Email
- type Event
- type EventStream
- type FailError
- type FallbackDef
- type FieldErrors
- type HTTPError
- type HandlerFunc
- type HookFunc
- type Invalid
- type LayoutDef
- type LiveOptions
- type LoadFunc
- type Manifest
- type Option
- func WithAddr(addr string) Option
- func WithBodyLimit(n int64) Option
- func WithContentSecurityPolicy(policy string) Option
- func WithContentSecurityPolicyReportOnly(policy string) Option
- func WithHook(h HookFunc) Option
- func WithLive(o LiveOptions) Option
- func WithLiveBroker(b goscript.Broker) Option
- func WithLogger(l *slog.Logger) Option
- func WithMatcher(name string, match func(value string) bool) Option
- func WithMiddleware(mw ...func(http.Handler) http.Handler) Option
- func WithOpenAPI(path, title, version string) Option
- func WithPlugins(plugins ...Plugin) Option
- func WithSSRCache(bytes int) Option
- func WithSSRTimeout(d time.Duration) Option
- func WithSSRWorkers(n int) Option
- func WithTrustedOrigins(origins ...string) Option
- func WithTrustedProxies(proxies ...string) Option
- func WithoutCSRFProtection() Option
- func WithoutNativeSSR() Option
- func WithoutSSR() Option
- type PageDef
- type Plugin
- type RedirectError
- type RouteDef
- type Setup
- func (s *Setup) AllowCrossOrigin(pattern string)
- func (s *Setup) Endpoint(pattern string, fn HandlerFunc)
- func (s *Setup) Handle(pattern string, h http.Handler)
- func (s *Setup) Head(html string)
- func (s *Setup) HeadFunc(fn func(c *Ctx, nonce string) string)
- func (s *Setup) Hook(h HookFunc)
- func (s *Setup) Logger() *slog.Logger
- func (s *Setup) Matcher(name string, match func(value string) bool)
- func (s *Setup) Middleware(mw func(http.Handler) http.Handler)
- func (s *Setup) Name() string
- func (s *Setup) OnShutdown(fn func(ctx context.Context) error)
- func (s *Setup) OnStart(fn func(ctx context.Context) error)
- func (s *Setup) TrustOrigin(origin string)
- type Validator
- type WebSocket
- type WebSocketOptions
Constants ¶
const LivePath = "/_tern/live"
LivePath is the WebSocket that live Go components (<script lang="go" live>) talk to.
Variables ¶
var ErrNoEmails = ssr.ErrNoEmails
ErrNoEmails is returned by RenderEmail when the app has no src/emails.
Functions ¶
func ClientIP ¶ added in v1.4.0
ClientIP returns the address of the client that made r, taking WithTrustedProxies into account. Middleware and plugins can use it; handlers with a Ctx can call Ctx.ClientIP.
func DecodeQuery ¶ added in v1.2.0
DecodeQuery fills the struct dst points to from query parameters, by each field's query tag, else its json tag name, else its name. Fields may be strings, booleans, numbers, time.Time (RFC 3339), types with UnmarshalText, pointers to these (nil when absent), or slices of them (from repeated parameters).
func Error ¶
Error returns an expected error with the given status and a message that is safe to show to users. Return it from Load, an action or an endpoint to render the nearest +error.svelte.
Any other error returned from your code is treated as unexpected: it is logged, and users see only "Internal Error".
func Fail ¶
Fail returns an action failure with a 4xx status. The page re-renders with data available as the `form` prop, so it can show errors next to fields and keep the user's input.
func FieldError ¶ added in v1.4.0
FieldError fails a FormAction with a message on one field, such as kit.FieldError("email", "That email is already registered.").
func Parent ¶
Parent waits for the layouts above the current load, merges their data, and decodes it into T. Use it in Load or LayoutLoad to build on data a parent layout loaded:
type Parent struct{ User User `json:"user"` }
p, err := kit.Parent[Parent](ctx)
Loads that do not call Parent run fully in parallel.
func QueryName ¶ added in v1.2.0
func QueryName(f reflect.StructField) string
QueryName is the query parameter name of a struct field; see DecodeQuery.
Types ¶
type ActionFunc ¶
ActionFunc handles a form submission. Its result is sent to the page as the `form` prop. Use Action to write actions with a typed result, so the generated `form` type is precise.
func Action ¶
func Action[T any](f func(*Ctx) (T, error)) ActionFunc
Action adapts a typed action function:
var Actions = kit.Actions{
"default": kit.Action(create),
}
func create(ctx *kit.Ctx) (Created, error) { ... }
func FormAction ¶ added in v1.4.0
func FormAction[In, Out any](fn func(*Ctx, In) (Out, error)) ActionFunc
FormAction adapts an action that takes its form as a struct. The form is decoded into In and checked against its validate tags, and then its Validate method if it has one, before fn runs:
type NewProject struct {
Name string `form:"name" validate:"required,min=3,max=60" label:"Project name"`
Email string `form:"email" validate:"required,email"`
Seats int `form:"seats" validate:"min=1,max=500"`
}
var Actions = kit.Actions{
"create": kit.FormAction(func(ctx *kit.Ctx, in NewProject) (Created, error) { ... }),
}
If a check fails, the action fails with status 400 and an Invalid. tern gen writes the same rules to ./$forms, so the page can check them as the user types. The rules are:
required the field must have a value; a checkbox must be checked
min=N, max=N characters for text, the value for numbers, the date for
dates, choices for []string
len=N exactly N characters
email, url an email address; an http or https URL
pattern=RE the whole value matches RE; it must be the last rule
oneof=a|b|c one of these values
same=field equal to another field, such as a password confirmation
Fields are named by their form tag, else their json name. The label tag names them in messages (default: the name, humanized), and message replaces all of a field's messages. form:"name,secret" keeps a value out of Invalid.Values; fields named like "password" are secret anyway. time.Time fields are dates (YYYY-MM-DD), or with form:"name,datetime", a datetime-local input's value.
type Actions ¶
type Actions map[string]ActionFunc
Actions maps action names to handlers. A form posting to the page with no ?/name runs "default"; <form action="?/create"> runs "create".
type App ¶
type App struct {
// contains filtered or unexported fields
}
App serves a Tern application. It implements http.Handler, so it can be used with any server or router; App.ListenAndServe runs it with production-ready defaults.
func New ¶
New creates an App from a generated manifest. Generated code calls it for you; see the ternApp function in tern.gen.go.
func (*App) Close ¶
Close releases the app's resources, such as server-rendering VMs. ListenAndServe and Serve call it on shutdown.
func (*App) ListenAndServe ¶
ListenAndServe runs the app until it receives SIGINT or SIGTERM, then shuts down gracefully, letting in-flight requests finish for up to 10 seconds.
It listens on the address set with WithAddr, or HOST:PORT from the environment, defaulting to port 3000 on all interfaces.
func (*App) RenderEmail ¶ added in v1.2.0
RenderEmail renders the email template src/emails/<name>.svelte with props, which are passed to the component as JSON. The template's <svelte:head><title> is the subject:
<script lang="ts">
let { name, link }: { name: string; link: string } = $props();
</script>
<svelte:head><title>Welcome, {name}</title></svelte:head>
<h1>Welcome, {name}!</h1>
<p><a href={link}>Confirm your email</a></p>
Templates render with the same engine as pages; under tern dev they update as you edit them, and /__tern/emails previews them. Send the result with the mail package.
type Ctx ¶
type Ctx struct {
// Request is the incoming request.
Request *http.Request
// Locals holds request-scoped values, typically set by a hook (for
// example the signed-in user) and read by loads and actions.
Locals map[string]any
// contains filtered or unexported fields
}
Ctx is the request context passed to Load, LayoutLoad, actions, endpoints and hooks. It implements context.Context, so it can be passed directly to database calls and other APIs that take a context.
func (*Ctx) BasePath ¶ added in v1.0.0
BasePath returns the app's base path from tern.json, such as "/app", or "".
func (*Ctx) ClientIP ¶ added in v1.4.0
ClientIP returns the client's IP address. Behind a reverse proxy, configure it with WithTrustedProxies; otherwise it is the proxy's address.
func (*Ctx) Content ¶ added in v1.2.0
Content returns the app's src/content directory: embedded in the binary in production, and read from disk in development so edits show on reload. The content package builds typed collections on top of it.
func (*Ctx) DeleteCookie ¶
DeleteCookie removes a cookie set with the default path "/".
func (*Ctx) Depends ¶ added in v0.4.0
Depends declares that the running load depends on keys, such as "app:projects" or a URL it fetches. Calling invalidate("app:projects") in the browser reruns every load that depends on it.
On client navigation, a layout's load only runs again when something it used changed: a parameter read with Param, the URL read with URL, the data of a parent it read with Parent, or an invalidated dependency. Reading Request directly is not tracked; use these methods instead.
func (*Ctx) EventStream ¶ added in v1.2.0
EventStream responds with a stream of server-sent events. fn runs until it returns, the client disconnects, or the server shuts down; its ctx is canceled in the last two cases. A comment is sent every 20 seconds to keep proxies from closing an idle connection.
func GET(ctx *kit.Ctx) error {
updates := hub.Subscribe(ctx, "status")
return ctx.EventStream(func(ctx context.Context, s *kit.EventStream) error {
for {
select {
case <-ctx.Done():
return nil
case u := <-updates:
if err := s.Send("status", u); err != nil {
return err
}
}
}
})
}
func (*Ctx) Locale ¶ added in v1.1.0
Locale returns the request's locale, such as "de", or "" if the app has no src/locales. Tern picks it from a "lang" route parameter, the locale cookie (set by setLocale in the browser), Accept-Language, and finally the default locale. A load that reads it reruns when it changes.
func (*Ctx) Param ¶
Param returns the value of a route parameter, or "" if it is absent. A load that reads a parameter runs again when the parameter changes.
func (*Ctx) Path ¶ added in v1.0.0
Path prefixes an app path such as "/projects/1" with the base path, for links built in Go. kit.Redirect adds the base path itself.
func (*Ctx) SetBodyLimit ¶ added in v1.2.0
SetBodyLimit raises (or lowers) the request body limit for this request, such as for an action that accepts file uploads. Call it before reading the body, with ctx.Form or otherwise. The default is set with WithBodyLimit.
func (*Ctx) SetCookie ¶
SetCookie adds a Set-Cookie header; setting the same cookie again in a request replaces it. Unset fields get safe defaults: Path "/", SameSite=Lax, and Secure unless the request is plain HTTP to localhost. Set HttpOnly yourself for cookies scripts must not read, such as session cookies. Loads may call it concurrently.
func (*Ctx) SetLocale ¶ added in v1.1.0
SetLocale overrides the request's locale, for example from a user's saved preference in a hook. Unsupported locales are ignored.
func (*Ctx) T ¶ added in v1.1.0
T translates key into the request's locale, for text produced on the server such as validation errors. params fill placeholders like {name} and plurals; see the guide for the message syntax.
func (*Ctx) URL ¶
URL returns the request URL. A load that reads it runs again on every client navigation that changes the URL.
func (*Ctx) WebSocket ¶ added in v1.2.0
func (c *Ctx) WebSocket(opts *WebSocketOptions, fn func(ctx context.Context, ws *WebSocket) error) error
WebSocket upgrades the request to a WebSocket connection and runs fn until it returns, the client disconnects, or the server shuts down; its ctx is canceled in the last two cases. Connections from other sites are refused unless their origin is allowed in opts.
func GET(ctx *kit.Ctx) error {
return ctx.WebSocket(nil, func(ctx context.Context, ws *kit.WebSocket) error {
for {
var msg Message
if err := ws.Receive(&msg); err != nil {
return err
}
if err := ws.Send(Reply{Text: msg.Text}); err != nil {
return err
}
}
})
}
func (*Ctx) Writer ¶
func (c *Ctx) Writer() http.ResponseWriter
Writer returns the response writer for endpoints, with headers and cookies set through the Ctx already applied. Do not use it in loads.
type Deferred ¶
type Deferred[T any] struct { // contains filtered or unexported fields }
Deferred is a value that a load starts computing but does not wait for. The page renders as soon as the rest of the data is ready, and the deferred value streams to the browser when it resolves. In Svelte it is a Promise:
type Data struct {
Post Post `json:"post"`
Comments kit.Deferred[[]Comment] `json:"comments"`
}
{#await data.comments}Loading…{:then comments}…{:catch error}…{/await}
Create one with Defer.
func Defer ¶
Defer runs fn in the background and returns its result as a Deferred, so slow data does not hold up the page. fn should respect ctx for cancellation; it runs only for the lifetime of the request.
func (Deferred[T]) MarshalJSON ¶
MarshalJSON encodes a placeholder that the client replaces with a Promise.
func (*Deferred[T]) UnmarshalJSON ¶
UnmarshalJSON ignores its input: deferred values are not available to kit.Parent, only to the browser.
type Email ¶ added in v1.2.0
type Email struct {
Subject string
HTML string
// Text is the plain-text version, made from the HTML.
Text string
}
Email is a rendered email template; see App.RenderEmail.
type Event ¶ added in v1.2.0
type Event struct {
// Name is the event type; "" is the default "message" event.
Name string
// ID is stored by the browser and sent back as Last-Event-ID when it
// reconnects, so a stream can resume.
ID string
// Data is sent as JSON, unless it is a string.
Data any
// Retry tells the browser how long to wait before reconnecting.
Retry time.Duration
}
Event is one server-sent event.
type EventStream ¶ added in v1.2.0
type EventStream struct {
// contains filtered or unexported fields
}
EventStream is a server-sent events connection, opened with Ctx.EventStream. Browsers read it with EventSource, or with stream() from @ternkit/tern.
func (*EventStream) LastEventID ¶ added in v1.2.0
func (s *EventStream) LastEventID() string
LastEventID returns the ID of the last event the browser received before it reconnected, or "".
func (*EventStream) Send ¶ added in v1.2.0
func (s *EventStream) Send(name string, data any) error
Send sends an event with a name and data, which is encoded as JSON unless it is a string.
func (*EventStream) SendEvent ¶ added in v1.2.0
func (s *EventStream) SendEvent(e Event) error
SendEvent sends an event with all its fields.
type FailError ¶
FailError is returned by an action to report a failed submission, typically a validation error. Its Data is sent to the page as `form`.
type FallbackDef ¶
type FallbackDef struct {
// Layouts are indices into Manifest.Layouts: the root layout, if any.
Layouts []int
}
FallbackDef renders 404s for URLs that match no route.
type FieldErrors ¶ added in v1.4.0
FieldErrors maps field names to messages. Return it from a FormAction, or from an input's Validate method, to fail with errors on those fields; the key "" is a message for the whole form.
func (FieldErrors) Error ¶ added in v1.4.0
func (e FieldErrors) Error() string
type HTTPError ¶
HTTPError is an expected error with an HTTP status, such as a 404. Its message is shown to the user, so it must not contain secrets.
type HandlerFunc ¶
HandlerFunc handles an endpoint request, such as an exported GET.
func OutputEndpoint ¶ added in v1.2.0
func OutputEndpoint[Out any](fn func(*Ctx) (Out, error)) HandlerFunc
OutputEndpoint adapts a typed endpoint without input.
func TypedEndpoint ¶ added in v1.2.0
func TypedEndpoint[In, Out any](method string, fn func(*Ctx, In) (Out, error)) HandlerFunc
TypedEndpoint adapts a typed endpoint; generated code calls it.
type HookFunc ¶
HookFunc runs before every page, data, action and endpoint request. It can read the request, set Locals, and return an error such as kit.Redirect to stop the request.
type Invalid ¶ added in v1.4.0
type Invalid struct {
// Errors maps field names to messages.
Errors map[string]string `json:"errors"`
// Values holds what was posted, except secret fields such as passwords.
Values map[string]any `json:"values"`
// Message is an error about the whole form, such as "Wrong email or password."
Message string `json:"message,omitempty"`
}
Invalid is what a FormAction fails with when the form doesn't pass its rules: the page's form prop, so it can show each error next to its field and refill what was typed. Tern UI's Form reads it.
type LayoutDef ¶
type LayoutDef struct {
Dir string
// Component is the +layout.svelte path relative to the project root,
// or "" if the directory only has a LayoutLoad.
Component string
Load LoadFunc
}
LayoutDef is a layout directory.
type LiveOptions ¶ added in v1.3.0
type LiveOptions struct {
// MaxInstances caps the components one page may mount at once. The
// default is 256.
MaxInstances int
// Rate is how many calls and bound values per second one page may
// send, with bursts of twice that. The default is 50.
Rate float64
// SendBuffer is how many messages may wait for a slow browser before
// the connection is closed; the page reconnects and starts fresh. The
// default is 256.
SendBuffer int
// PingInterval keeps idle connections open through proxies. The
// default is 25 seconds.
PingInterval time.Duration
// Origins lists other origins allowed to connect, as for
// [WebSocketOptions].
Origins []string
}
LiveOptions tune live components; see WithLive.
type LoadFunc ¶
LoadFunc is a Load or LayoutLoad function with its result type erased. Generated code builds it with LoadOf.
type Manifest ¶
type Manifest struct {
// Layouts are shared by routes and referenced by index.
Layouts []LayoutDef
// Routes, in matching priority order.
Routes []RouteDef
// Fallback describes what renders when no route matches.
Fallback FallbackDef
// AppHTML is the contents of src/app.html.
AppHTML string
// Client is the built client: Vite's output directory, including
// .vite/manifest.json. It may be nil in development.
Client fs.FS
// ClientEntry is the Vite manifest key of the client entry module.
ClientEntry string
// ServerBundle is the server renderer built by `vite build --ssr`, or
// "" to render on the client only.
ServerBundle string
// Native is the server renderer compiled to Go by tern build, if it
// was: it makes a realm with the app's modules evaluated. Pages render
// with it, and with ServerBundle only what it can't render. The
// generated tern_native.gen.go sets it.
Native func(setup func(*js.Realm)) *js.Realm
// BasePath is the URL prefix the app is served under, from tern.json,
// such as "/app"; "" serves it at the root.
BasePath string
// Locales holds src/locales/<locale>.json, or nil without i18n.
Locales fs.FS
// Content holds src/content, or nil if the app has none. See Ctx.Content.
Content fs.FS
// Live is set when the app has live Go components; tern gen registers
// them with the goscript package.
Live bool
// OpenAPI is the OpenAPI description of the typed endpoints, served
// with WithOpenAPI.
OpenAPI []byte
// DefaultLocale is the fallback locale; "" picks "en" or the first.
DefaultLocale string
}
Manifest describes an app's routes and assets. It is produced by `tern gen` in tern.gen.go; you do not write it by hand.
Manifest and the *Def types are the interface between generated code and the runtime. They are not covered by Tern's compatibility promise and may change in minor releases: `go get -tool` keeps the CLI that generates them and the kit package that reads them at the same version.
type Option ¶
type Option func(*options)
Option configures an App.
func WithAddr ¶
WithAddr sets the address ListenAndServe listens on. The default is HOST:PORT from the environment, or ":3000".
func WithBodyLimit ¶
WithBodyLimit sets the maximum request body size for actions and endpoints, in bytes. The default is 1 MiB.
func WithContentSecurityPolicy ¶ added in v0.4.0
WithContentSecurityPolicy sends a Content-Security-Policy header on every page. Tern adds a per-request nonce to script-src (creating the directive if needed) and puts it on its own scripts, so a strict policy such as "default-src 'self'" works without 'unsafe-inline'. Use %tern.nonce% in src/app.html for your own inline scripts.
func WithContentSecurityPolicyReportOnly ¶ added in v0.4.0
WithContentSecurityPolicyReportOnly is like WithContentSecurityPolicy but sends Content-Security-Policy-Report-Only, to test a policy without enforcing it.
func WithHook ¶
WithHook adds a hook. Hooks run in the order they are added, after the hooks of plugins, so they can use sessions and other plugin state.
func WithLiveBroker ¶ added in v1.3.0
WithLiveBroker connects live components in every process of the app through b, so goscript.Shared values, goscript.Presence counts and goscript.Publish reach all of them. Any realtime.Broker works, such as the PostgreSQL one in realtime/pgbroker.
func WithLogger ¶
WithLogger sets the logger for unexpected errors and server events. The default logs to slog.Default().
func WithMatcher ¶
WithMatcher registers a parameter matcher used by directories such as id.param.integer. The built-in matchers "integer" and "uuid" are always available.
func WithMiddleware ¶
WithMiddleware wraps the app in standard net/http middleware. The first middleware added is the outermost.
func WithOpenAPI ¶ added in v1.2.0
WithOpenAPI serves the OpenAPI description that tern gen writes for the app's typed endpoints at path, such as "/openapi.json", with the given title and version.
func WithPlugins ¶ added in v1.0.0
WithPlugins adds plugins. They are set up in order, after the other options, so a plugin's hooks and middleware run after those added directly with WithHook and WithMiddleware.
func WithSSRCache ¶ added in v1.2.0
WithSSRCache sets how much server-rendered HTML is kept in memory, in bytes. A render depends only on the page's data and URL, so a page that looks the same for many visitors renders once; pages with per-user data get their own entries, evicted least recently used first. The default is 32 MiB; 0 turns the cache off.
func WithSSRTimeout ¶
WithSSRTimeout bounds how long a server render may take before the page falls back to client rendering. The default is 5 seconds.
func WithSSRWorkers ¶
WithSSRWorkers sets how many pages can render on the server at once. The default is GOMAXPROCS. Pages compiled to Go render in parallel on every worker; with the JavaScript engine, each worker is a VM using roughly 5 to 20 MB, and the default is at most 4: the VMs share a lock in the C runtime, so more rarely render faster.
func WithTrustedOrigins ¶
WithTrustedOrigins allows cross-origin form submissions and endpoint requests from the given origins, such as "https://example.com".
func WithTrustedProxies ¶ added in v1.4.0
WithTrustedProxies names the reverse proxies in front of the app, as IP addresses or CIDR ranges such as "10.0.0.0/8" or "127.0.0.1". Requests from these peers may set X-Forwarded-For, which Ctx.ClientIP and ClientIP then read, and X-Forwarded-Proto.
Once any proxy is configured, X-Forwarded-Proto from other peers is ignored. Without this option, ClientIP is the connection's own address and X-Forwarded-Proto is honored from anyone, as before.
func WithoutCSRFProtection ¶
func WithoutCSRFProtection() Option
WithoutCSRFProtection disables cross-origin request protection. Only use it if something in front of the app already provides it.
func WithoutNativeSSR ¶ added in v1.5.0
func WithoutNativeSSR() Option
WithoutNativeSSR renders every page with the JavaScript engine, even when tern build compiled the server renderer to Go. Setting TERN_NATIVE=0 does the same without a rebuild.
func WithoutSSR ¶
func WithoutSSR() Option
WithoutSSR renders every page on the client only. Use `const SSR = false` in a route's package to turn it off for one page instead.
type PageDef ¶
type PageDef struct {
// Component is the +page.svelte path relative to the project root.
Component string
Load LoadFunc
Actions Actions
// NoSSR disables server-side rendering for this page; set by
// `const SSR = false` in the route's package.
NoSSR bool
}
PageDef is a route's page.
type Plugin ¶ added in v1.0.0
type Plugin interface {
// Name identifies the plugin in logs and errors.
Name() string
// Setup registers the plugin's behavior. It runs once, when the App is
// created; an error stops the App from starting.
Setup(s *Setup) error
}
Plugin extends an App with reusable behavior: hooks, middleware, matchers, extra HTTP handlers, tags in every page's <head>, and work to do on shutdown. Add plugins with WithPlugins.
type Plugin struct{}
func (Plugin) Name() string { return "hello" }
func (Plugin) Setup(s *kit.Setup) error {
s.Handle("GET /hello", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "hello")
}))
return nil
}
type RedirectError ¶
RedirectError tells Tern to redirect the request.
func (*RedirectError) Error ¶
func (e *RedirectError) Error() string
type RouteDef ¶
type RouteDef struct {
// ID is the route ID, e.g. "/blog/slug.param".
ID string
// Layouts are indices into Manifest.Layouts, outermost first.
Layouts []int
// Page is nil for endpoint-only routes.
Page *PageDef
// Endpoint maps HTTP methods to handlers.
Endpoint map[string]HandlerFunc
// Prerender renders the page to static HTML at build time; set by
// `const Prerender = true` in the route's package.
Prerender bool
// Entries lists the parameters to prerender a dynamic route with; set
// by an exported Entries function in the route's package.
Entries func(*Ctx) ([]map[string]string, error)
}
RouteDef is a page, an endpoint, or both.
type Setup ¶ added in v1.0.0
type Setup struct {
// contains filtered or unexported fields
}
Setup is how a plugin registers its behavior.
func (*Setup) AllowCrossOrigin ¶ added in v1.2.0
AllowCrossOrigin exempts requests matching pattern (net/http.ServeMux syntax) from cross-origin protection. Use it only for endpoints that don't act on cookies, such as an OAuth token endpoint that clients on other sites call with their own credentials.
func (*Setup) Endpoint ¶ added in v1.2.0
func (s *Setup) Endpoint(pattern string, fn HandlerFunc)
Endpoint serves pattern with fn like a route's endpoint: after the hooks, with a Ctx, so it can use sessions and Locals, and with errors handled like an endpoint's. Patterns use net/http.ServeMux syntax, such as "GET /auth/{provider}/login"; read wildcards with ctx.Request.PathValue. Endpoints take precedence over the app's routes.
func (*Setup) Handle ¶ added in v1.0.0
Handle serves pattern with h, before Tern's routes. Patterns use net/http.ServeMux syntax, such as "GET /healthz" or "/metrics".
func (*Setup) Head ¶ added in v1.0.0
Head adds HTML to the <head> of every page, such as a <meta> tag or an analytics script. Scripts should use the per-request nonce; see Setup.HeadFunc.
func (*Setup) HeadFunc ¶ added in v1.0.0
HeadFunc adds HTML computed per request to the <head> of every page. nonce is the request's Content-Security-Policy nonce, for inline scripts.
func (*Setup) Hook ¶ added in v1.0.0
Hook adds a hook that runs before every page, data, action and endpoint request.
func (*Setup) Middleware ¶ added in v1.0.0
Middleware wraps the App in net/http middleware.
func (*Setup) OnShutdown ¶ added in v1.0.0
OnShutdown registers work to do when the App shuts down, such as flushing buffers. Functions run in reverse order of registration.
func (*Setup) OnStart ¶ added in v1.2.0
OnStart registers work to do when the server starts, before it accepts requests, such as running migrations or starting background workers. ctx is canceled when the server begins shutting down; start long-running work in a goroutine that stops then. An error stops the server from starting. Start functions run in order of registration, and not while tern build prerenders pages.
func (*Setup) TrustOrigin ¶ added in v1.1.0
TrustOrigin allows cross-origin form posts and endpoint requests from origin, as WithTrustedOrigins does. CORS plugins use it.
type Validator ¶ added in v1.2.0
type Validator interface{ Validate() error }
Validator is implemented by inputs that check themselves.
type WebSocket ¶ added in v1.2.0
type WebSocket struct {
// contains filtered or unexported fields
}
WebSocket is a WebSocket connection, opened with Ctx.WebSocket.
func (*WebSocket) Conn ¶ added in v1.2.0
Conn returns the underlying github.com/coder/websocket connection, for binary messages, pings and other details.
func (*WebSocket) Receive ¶ added in v1.2.0
Receive reads the next message, which must be JSON, into v. It returns an error when the connection closes; WebSocket treats a normal close as the end of the connection, not a failure.
func (*WebSocket) ReceiveText ¶ added in v1.2.0
ReceiveText reads the next message as text.
func (*WebSocket) Subprotocol ¶ added in v1.2.0
Subprotocol returns the subprotocol the client and server agreed on.
type WebSocketOptions ¶ added in v1.2.0
type WebSocketOptions struct {
// Origins lists other origins allowed to connect, as host patterns
// such as "app.example.com" or "*.example.com". Pages on the app's own
// origin can always connect; browsers on other sites cannot, unless
// they are listed here.
Origins []string
// Subprotocols the server accepts, in order of preference.
Subprotocols []string
// ReadLimit caps the size of a received message, in bytes. The default
// is 1 MiB.
ReadLimit int64
}
WebSocketOptions configure Ctx.WebSocket.