petitweb

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 10, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

README

Petitweb for Go

Petitweb

Petitweb is a small, TinyGo-oriented web application framework built directly on net/http. Classic mode handles ordinary document requests, form posts, redirects, downloads, and APIs without shipping a browser runtime.

app := petitweb.New(
    petitweb.WithMiddleware(
        petitweb.RequestID("", nil),
        petitweb.Recover(petitweb.ErrorHandler{}),
    ),
)

app.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {
    err := petitweb.HTML(w, http.StatusOK, petitweb.RenderFunc(func(w io.Writer) error {
        _, err := io.WriteString(w, "<!doctype html><h1>Hello</h1>")
        return err
    }))
    if err != nil {
        app.WriteError(w, r, err)
    }
})

log.Fatal(app.ListenAndServe(":8080"))

The runtime provides:

  • standard http.Handler, http.ServeMux, and middleware composition;
  • startup validation, health/readiness/OpenAPI endpoints, graceful shutdown, and reverse-order resource cleanup;
  • safe RFC 9457 or application-supplied HTML error rendering;
  • complete HTML, JSON, XML, CSV, redirect, and download responses;
  • request IDs, request-scoped loggers, recovery, request-body limits, and validated browser security headers;
  • generated typed request/response mapping through tinybind-go.

Modern component graphs, patch protocols, hydration, and browser JavaScript are not dependencies of this package.

Editor support

tools/vscode is a Visual Studio Code extension that highlights the three source dialects — *.pw.html, *.pw.sql, and *.pw.dynamo — including the template expressions embedded in their HTML, SQL, and clause bodies. It is a grammar only: nothing is executed, no binary is needed, and it works on a file opened with no workspace. Diagnostics and completion are planned for a later version through a pw lsp language server.

Authentication

Opaque server-side login sessions live in session, and sessionstore/sqlite stores them in a database/sql database. Importing plugin/auth adds the [auth] binding and the login flow itself; nothing is installed until auth.enabled is true, so an unused import costs one configuration binding.

Browser authentication supports OIDC, passkeys, or both. API servers can use auth.mode = "jwt_only" to verify a bearer access token on every request without creating a session or mounting browser login endpoints. JWT-only is not an --auth choice in pw init; it belongs to the dedicated api-server preset and is documented in the authentication guide.

OIDC Authorization Code with PKCE is implemented over contrib/oidc. examples/oidclogin is a complete application that keeps its sessions in SQLite and logs in against contrib/devidp, the development-only provider pw dev starts and configures for it.

The Hello World example can print combined configuration scaffolds registered by every imported package. Redirect stdout when a file is wanted:

cd examples/helloworld
go run ./cmd/helloworld --generate-config toml > config.dev.toml
go run ./cmd/helloworld --generate-config env > .env

APP_ENV selects the runtime environment (dev, stg, prod, or any other lowercase token) and defaults to dev. Project-local configuration is read from ./config.{APP_ENV}.toml and then ./config/config.{APP_ENV}.toml; the user and system configuration directories keep the environment-neutral config.toml. --config-path overrides the search entirely.

Tests can run an application from an isolated copy of every registered framework and application configuration. The customizer initially sees port -1; TestRun reserves an available loopback port before startup.

server := testutil.TestRun(t, handlers.Handlers(), func(config *testutil.Config) {
    testutil.Update[AppConfig](config, func(app *AppConfig) {
        app.Mode = "test"
    })
    testutil.Update[pw.MiddlewareConfig](config, func(middleware *pw.MiddlewareConfig) {
        middleware.RDB.Enabled = true
        middleware.RDB.DSN = "sqlite://:memory:"
        middleware.RDB.MaxOpenConns = 1
        middleware.RDB.MaxIdleConns = 1
    })
}, testutil.WithMigrations("migrations"))

Documentation

Overview

Package petitweb provides the reflection-free runtime for Petitweb classic applications. It deliberately builds on net/http: handlers, middleware, and response writers remain ordinary standard-library values.

Index

Constants

View Source
const (
	LevelTrace = pwruntime.LevelTrace
	LevelDebug = pwruntime.LevelDebug
	LevelInfo  = pwruntime.LevelInfo
	LevelWarn  = pwruntime.LevelWarn
	LevelError = pwruntime.LevelError
)

Severities.

Variables

This section is empty.

Functions

func CSV

func CSV(w http.ResponseWriter, status int, records [][]string) error

CSV writes records using the standard CSV encoder.

func Download

func Download(w http.ResponseWriter, status int, filename, contentType string, content []byte) error

Download writes bytes as an attachment using a safely encoded filename.

func HTML

func HTML(w http.ResponseWriter, status int, renderer Renderer) error

HTML writes a complete HTML response. The renderer is buffered so its error cannot leave a partially committed success response.

func JSON

func JSON(w http.ResponseWriter, status int, value any) error

JSON writes a JSON response.

func ReadRequestID

func ReadRequestID(ctx context.Context) (string, bool)

ReadRequestID returns the validated request correlation ID.

func Redirect

func Redirect(w http.ResponseWriter, r *http.Request, location string, status int)

Redirect performs a normal browser redirect.

func WriteError

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

WriteError writes with safe defaults and RFC 9457 negotiation.

func XML

func XML(w http.ResponseWriter, status int, value any) error

XML writes an XML response.

Types

type App

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

App owns an application's mux, middleware, operational endpoints, and server lifecycle. Configuration is frozen the first time Handler or Serve is called.

func New

func New(options ...Option) *App

New constructs an application with safe server defaults.

func (*App) Handle

func (a *App) Handle(pattern string, handler http.Handler)

Handle registers a standard net/http handler.

func (*App) HandleFunc

func (a *App) HandleFunc(pattern string, handler http.HandlerFunc)

HandleFunc registers a standard net/http handler function.

func (*App) Handler

func (a *App) Handler() http.Handler

Handler freezes configuration and returns the fully composed handler. Invalid startup configuration panics; callers that need error handling should call Validate first or use Serve/ListenAndServe.

func (*App) ListenAndServe

func (a *App) ListenAndServe(addr string) error

ListenAndServe validates and serves until the server is shut down.

func (*App) Middlewares

func (a *App) Middlewares() []Middleware

Middlewares returns an immutable snapshot of configured middleware.

func (*App) Mux

func (a *App) Mux() *httpmux.ServeMux

Mux returns the application's standard library mux. It must be configured before Handler or Serve freezes the application.

func (*App) Run

func (a *App) Run(ctx context.Context, addr string) error

Run serves until ctx is cancelled, then performs graceful shutdown.

func (*App) Serve

func (a *App) Serve(server *http.Server) error

Serve runs the application using server's listener settings and Petitweb's validated timeouts. Supplying a server allows tests and advanced deployments to use an existing listener via server.Serve separately after Handler().

func (*App) SetErrorRenderer

func (a *App) SetErrorRenderer(renderer ErrorRenderer)

SetErrorRenderer installs an HTML error renderer before serving.

func (*App) Shutdown

func (a *App) Shutdown(ctx context.Context) error

Shutdown drains active handlers and closes resources in reverse order.

func (*App) String

func (a *App) String() string

func (*App) Use

func (a *App) Use(middleware ...Middleware)

Use appends middleware before the application is frozen.

func (*App) Validate

func (a *App) Validate() error

Validate checks all startup invariants without freezing the App.

func (*App) WriteError

func (a *App) WriteError(w http.ResponseWriter, r *http.Request, err error)

WriteError negotiates an error using the renderer configured on the App.

type Attribute

type Attribute = pwruntime.Attribute

Attribute is one scalar key-value pair on a record.

func Bool

func Bool(key string, value bool) Attribute

func Err

func Err(err error) Attribute

Err renders an error as a record attribute. A nil error is safe.

func Float64

func Float64(key string, value float64) Attribute

func Int

func Int(key string, value int) Attribute

func Int64

func Int64(key string, value int64) Attribute

func String

func String(key, value string) Attribute

Attribute constructors.

type ErrorHandler

type ErrorHandler struct {
	Renderer ErrorRenderer
	// Logger is optional; the zero value falls back to the request logger.
	Logger Logger
}

ErrorHandler negotiates safe HTML and RFC 9457 error responses.

func (ErrorHandler) WriteError

func (h ErrorHandler) WriteError(w http.ResponseWriter, r *http.Request, err error)

WriteError writes err exactly once. Internal error causes are never exposed.

type ErrorPage

type ErrorPage struct {
	Status    int
	Title     string
	Detail    string
	Code      string
	RequestID string
	// contains filtered or unexported fields
}

ErrorPage is the sanitized model passed to an application's HTML renderer.

func (ErrorPage) String

func (p ErrorPage) String() string

type ErrorRenderer

type ErrorRenderer func(http.ResponseWriter, *http.Request, ErrorPage) error

ErrorRenderer writes a complete HTML error response.

type HSTSConfig

type HSTSConfig = middlewares.HSTSConfig

HSTSConfig controls Strict-Transport-Security on direct HTTPS requests.

type Lifecycle

type Lifecycle = middlewares.Lifecycle

Lifecycle describes an API resource's deprecation and sunset dates.

type Logger

type Logger = pwruntime.Logger

Logger is the context-bound logger returned by ReadLogger.

func ReadLogger

func ReadLogger(ctx context.Context) Logger

ReadLogger always returns a usable request-aware logger. A request that never passed through RequestID still gets the logger installed on the context, and a context with nothing installed still gets one that can be called.

type Middleware

type Middleware func(http.Handler) http.Handler

Middleware is the standard Go HTTP middleware signature.

func LifecycleHeaders

func LifecycleHeaders(lifecycle Lifecycle) (Middleware, error)

LifecycleHeaders announces an API resource's lifecycle without changing its response status or behavior.

func MaxRequestBody

func MaxRequestBody(bytes int64) Middleware

MaxRequestBody limits downstream reads from the request body.

func Recover

func Recover(handler ErrorHandler) Middleware

Recover converts a panic into a safe negotiated error response.

func RequestID

func RequestID(header string, logger Logger) Middleware

RequestID validates or creates a request ID and exposes it through context. The zero Logger is accepted and resolves to the one installed on the request.

func SecurityHeaders

func SecurityHeaders(config SecurityHeadersConfig) (Middleware, error)

SecurityHeaders sets policy headers before downstream response commitment. Strict-Transport-Security is limited to direct HTTPS connections.

type Option

type Option func(*App) error

Option configures an App before it starts serving.

func WithCloser

func WithCloser(closer func(context.Context) error) Option

WithCloser registers a process-lifetime resource closer. Closers run in reverse registration order after active requests have drained.

func WithErrorRenderer

func WithErrorRenderer(renderer ErrorRenderer) Option

WithErrorRenderer installs the HTML error renderer.

func WithMiddleware

func WithMiddleware(middleware ...Middleware) Option

WithMiddleware appends middleware. Middleware executes in the order supplied.

func WithOpenAPI

func WithOpenAPI(document []byte) Option

WithOpenAPI supplies a generated OpenAPI document for the configured endpoint.

func WithReadinessCheck

func WithReadinessCheck(check ReadyCheck) Option

WithReadinessCheck adds a critical dependency readiness check.

func WithServerConfig

func WithServerConfig(config ServerConfig) Option

WithServerConfig replaces the default server configuration.

type ReadyCheck

type ReadyCheck func(context.Context) error

ReadyCheck reports whether a critical application dependency can serve.

type RenderFunc

type RenderFunc func(io.Writer) error

RenderFunc adapts a generated render function to Renderer.

func (RenderFunc) Render

func (f RenderFunc) Render(w io.Writer) error

type Renderer

type Renderer interface {
	Render(io.Writer) error
}

Renderer is implemented by generated, reflection-free HTML templates.

type SecurityHeadersConfig

type SecurityHeadersConfig = middlewares.SecurityHeadersConfig

SecurityHeadersConfig contains browser security response headers.

func DefaultSecurityHeaders

func DefaultSecurityHeaders() SecurityHeadersConfig

DefaultSecurityHeaders returns the classic mode defaults.

type ServerConfig

type ServerConfig struct {
	Address           string
	ReadHeaderTimeout time.Duration
	ReadTimeout       time.Duration
	WriteTimeout      time.Duration
	IdleTimeout       time.Duration
	ShutdownTimeout   time.Duration
	MaxRequestBody    int64
	TrustedProxies    []string
	// Health, Readiness, and OpenAPI are the absolute paths their endpoints
	// serve, and an unset path serves nothing. There is no default path: an
	// application that answers on /healthz should say so where a reader of its
	// setup can see it, rather than inherit it from here.
	Health    string
	Readiness string
	OpenAPI   string
}

ServerConfig controls the classic HTTP server and operational endpoints.

func DefaultServerConfig

func DefaultServerConfig() ServerConfig

DefaultServerConfig returns conservative production-oriented defaults.

func (ServerConfig) Validate

func (c ServerConfig) Validate() error

Validate checks startup invariants before a listener accepts requests.

Directories

Path Synopsis
Package authstate provides expiring, single-use state storage for browser authentication flows.
Package authstate provides expiring, single-use state storage for browser authentication flows.
dynamo
Package dynamo stores single-use authentication ceremony state in DynamoDB.
Package dynamo stores single-use authentication ceremony state in DynamoDB.
firestore
Package firestore stores single-use authentication ceremony state in Firestore in Datastore mode.
Package firestore stores single-use authentication ceremony state in Firestore in Datastore mode.
memory
Package memory provides process-local authentication state storage.
Package memory provides process-local authentication state storage.
mysql
Package mysql registers the MySQL dialect of the authentication state store.
Package mysql registers the MySQL dialect of the authentication state store.
postgres
Package postgres registers the PostgreSQL dialect of the authentication state store.
Package postgres registers the PostgreSQL dialect of the authentication state store.
redis
Package redis provides a Redis and Valkey backed authstate.Store.
Package redis provides a Redis and Valkey backed authstate.Store.
sqlite
Package sqlite registers the SQLite dialect of the authentication state store.
Package sqlite registers the SQLite dialect of the authentication state store.
authstore
dynamo
Package dynamo holds the account-side authentication stores of plugin/auth in DynamoDB.
Package dynamo holds the account-side authentication stores of plugin/auth in DynamoDB.
firestore
Package firestore holds the account-side authentication stores of plugin/auth in Firestore in Datastore mode.
Package firestore holds the account-side authentication stores of plugin/auth in Firestore in Datastore mode.
cmd
pw command
contrib
cbor
Package cbor implements a bounded, reflection-free subset of RFC 8949.
Package cbor implements a bounded, reflection-free subset of RFC 8949.
devidp
Package devidp implements a development-only OpenID Provider.
Package devidp implements a development-only OpenID Provider.
internal/authn
Package authn contains bounded security primitives shared by contrib authentication protocols.
Package authn contains bounded security primitives shared by contrib authentication protocols.
jwt
Package jwt strictly parses, signs, and verifies a bounded signed JWT subset.
Package jwt strictly parses, signs, and verifies a bounded signed JWT subset.
oauth
Package oauth implements a bounded OAuth 2.0 Authorization Code client with S256 PKCE.
Package oauth implements a bounded OAuth 2.0 Authorization Code client with S256 PKCE.
oidc
Package oidc implements a bounded OpenID Connect relying-party client over the OAuth Authorization Code flow.
Package oidc implements a bounded OpenID Connect relying-party client over the OAuth Authorization Code flow.
otel
Package otel contains the small set of attribute value types shared by the Petitweb trace and log packages.
Package otel contains the small set of attribute value types shared by the Petitweb trace and log packages.
otel/exporter/otlphttp
Package otlphttp exports traces and logs with OTLP/HTTP JSON.
Package otlphttp exports traces and logs with OTLP/HTTP JSON.
otel/log
Package log provides correlated and standalone OpenTelemetry log records.
Package log provides correlated and standalone OpenTelemetry log records.
otel/propagation
Package propagation implements W3C Trace Context extraction and injection.
Package propagation implements W3C Trace Context extraction and injection.
otel/trace
Package trace provides a small, explicit OpenTelemetry tracing subset.
Package trace provides a small, explicit OpenTelemetry tracing subset.
passkey
Package passkey implements bounded server-side WebAuthn registration and authentication for ES256 passkeys.
Package passkey implements bounded server-side WebAuthn registration and authentication for ES256 passkeys.
passkey/passkeytest
Package passkeytest is a test-only software authenticator for github.com/shibukawa/popcornwave/contrib/passkey.
Package passkeytest is a test-only software authenticator for github.com/shibukawa/popcornwave/contrib/passkey.
Package database resolves a Popcorn Wave rdb DSN onto the engine that opens it.
Package database resolves a Popcorn Wave rdb DSN onto the engine that opens it.
dynamo
Package dynamo opens the application's DynamoDB client from configuration and keeps it as process state every operation reaches through Handle.
Package dynamo opens the application's DynamoDB client from configuration and keeps it as process state every operation reaches through Handle.
firestore
Package firestore opens the application's Firestore client from configuration and keeps it as process state every operation reaches through Handle.
Package firestore opens the application's Firestore client from configuration and keeps it as process state every operation reaches through Handle.
mysql
Package mysql registers the MySQL and MariaDB engine for a mysql:// DSN.
Package mysql registers the MySQL and MariaDB engine for a mysql:// DSN.
postgres
Package postgres registers the PostgreSQL engine for a postgres:// DSN.
Package postgres registers the PostgreSQL engine for a postgres:// DSN.
sqlite
Package sqlite registers the SQLite engine for a sqlite:// DSN.
Package sqlite registers the SQLite engine for a sqlite:// DSN.
Package fasttestutil is the fasthttp half of the backend-neutral test seam.
Package fasttestutil is the fasthttp half of the backend-neutral test seam.
internal
apidoc
Package apidoc composes the documentation page an OpenAPI document is read through.
Package apidoc composes the documentation page an OpenAPI document is read through.
botdetect
Package botdetect classifies a User-Agent as a client that will not run the boundary runtime.
Package botdetect classifies a User-Agent as a client that will not run the boundary runtime.
configview
Package configview decides how a resolved configuration value is shown.
Package configview decides how a resolved configuration value is shown.
dbseed
Package dbseed applies version-control-owned dataset files to the framework-owned database pool.
Package dbseed applies version-control-owned dataset files to the framework-owned database pool.
devconsole
Package devconsole serves the pw dev web console: one loopback listener holding an index and every pane.
Package devconsole serves the pw dev web console: one loopback listener holding an index and every pane.
firestoretest
Package firestoretest is an in-process Datastore server for the framework's own Firestore stores.
Package firestoretest is an in-process Datastore server for the framework's own Firestore stores.
pathpattern
Package pathpattern is the path-matching grammar the framework's path-scoped policies share.
Package pathpattern is the path-matching grammar the framework's path-scoped policies share.
pwcheck
Package pwcheck holds the diagnostic check catalog.
Package pwcheck holds the diagnostic check catalog.
pwenv
Package pwenv resolves the runtime environment token that selects project-local configuration files.
Package pwenv resolves the runtime environment token that selects project-local configuration files.
pwmigrate
Package pwmigrate applies versioned SQL migrations with goose.
Package pwmigrate applies versioned SQL migrations with goose.
pwtree
Package pwtree lays out dotted configuration keys as an aligned tree.
Package pwtree lays out dotted configuration keys as an aligned tree.
requestid
Package requestid mints and checks the correlation ID a request carries.
Package requestid mints and checks the correlation ID a request carries.
requestorigin
Package requestorigin answers three questions for every caller that asks them: what scheme did this request arrive over, what origin does this deployment serve it as, and which client sent it.
Package requestorigin answers three questions for every caller that asks them: what scheme did this request arrive over, what origin does this deployment serve it as, and which client sent it.
runtimegen command
Command runtimegen produces the browser runtime embedded by package pw.
Command runtimegen produces the browser runtime embedded by package pw.
safeurl
Package safeurl decides whether a URL may be handed to a browser as a navigation target or written into a URL-bearing attribute.
Package safeurl decides whether a URL may be handed to a browser as a navigation target or written into a URL-bearing attribute.
sqlscript
Package sqlscript executes a multi-statement SQL script one statement at a time.
Package sqlscript executes a multi-statement SQL script one statement at a time.
transportbench/benchserver command
Command benchserver answers the same three routes on either transport, so an external load generator can measure one against the other.
Command benchserver answers the same three routes on either transport, so an external load generator can measure one against the other.
transportfixture
Package transportfixture is authored handler code written the way an application writes it, so the transport analysis has something in this repository to run against.
Package transportfixture is authored handler code written the way an application writes it, so the transport analysis has something in this repository to run against.
Package middlewares contains the net/http middleware shared by Popcorn Wave applications.
Package middlewares contains the net/http middleware shared by Popcorn Wave applications.
Package migrate applies versioned SQL migrations to a Popcorn Wave database.
Package migrate applies versioned SQL migrations to a Popcorn Wave database.
plugin
auth
Package auth adds browser authentication and bearer-token API authentication to a Popcorn Wave application.
Package auth adds browser authentication and bearer-token API authentication to a Popcorn Wave application.
auth/authtest
Package authtest installs an authenticated request context without a server, a database, or a ceremony.
Package authtest installs an authenticated request context without a server, a database, or a ceremony.
auth/passkeye2e
Package passkeye2e holds the end-to-end test of the passkey ceremony endpoints.
Package passkeye2e holds the end-to-end test of the passkey ceremony endpoints.
auth/passkeyonlye2e
Package passkeyonlye2e holds the end-to-end test of the passkey_only mode.
Package passkeyonlye2e holds the end-to-end test of the passkey_only mode.
Package pw is the stable application-facing Popcorn Wave API.
Package pw is the stable application-facing Popcorn Wave API.
Package pwdata serves the pw dev data pane from inside the application.
Package pwdata serves the pw dev data pane from inside the application.
Package pwfast is the pw surface over a fasthttp request, for the build that decision:transport-source-transform generates.
Package pwfast is the pw surface over a fasthttp request, for the build that decision:transport-source-transform generates.
Package pwpage is the runtime that generated page tree code calls.
Package pwpage is the runtime that generated page tree code calls.
Package pwruntime contains the narrow runtime contract used by generated Popcorn Wave code.
Package pwruntime contains the narrow runtime contract used by generated Popcorn Wave code.
Package pwstory holds the registry the template storybook renders from.
Package pwstory holds the registry the template storybook renders from.
Package pwtest is the backend-neutral vocabulary a test uses to describe one request and inspect one response.
Package pwtest is the backend-neutral vocabulary a test uses to describe one request and inspect one response.
ratelimitstore
redis
Package redis counts rate limit arrivals in a shared Redis or Valkey server.
Package redis counts rate limit arrivals in a shared Redis or Valkey server.
Package session stores typed per-browser state.
Package session stores typed per-browser state.
Package sessionconfig holds the configuration bindings of per-browser state.
Package sessionconfig holds the configuration bindings of per-browser state.
Package sessionstore keeps Popcorn Wave login sessions in a relational database.
Package sessionstore keeps Popcorn Wave login sessions in a relational database.
dynamo
Package dynamo stores login sessions in DynamoDB.
Package dynamo stores login sessions in DynamoDB.
firestore
Package firestore stores login sessions in Firestore in Datastore mode.
Package firestore stores login sessions in Firestore in Datastore mode.
mysql
Package mysql registers the MySQL dialect of the session store.
Package mysql registers the MySQL dialect of the session store.
postgres
Package postgres registers the PostgreSQL dialect of the session store.
Package postgres registers the PostgreSQL dialect of the session store.
redis
Package redis stores Popcorn Wave login sessions in Redis or Valkey.
Package redis stores Popcorn Wave login sessions in Redis or Valkey.
sqlite
Package sqlite registers the SQLite dialect of the session store.
Package sqlite registers the SQLite dialect of the session store.
Package skills carries the agent skill sources this repository publishes.
Package skills carries the agent skill sources this repository publishes.
Package testutil runs Popcorn Wave applications from isolated copies of the registered runtime configuration.
Package testutil runs Popcorn Wave applications from isolated copies of the registered runtime configuration.

Jump to

Keyboard shortcuts

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