Help us shape the future of Go! Take the 2026 Go Developer Survey

epform

package
v1.152.0 Latest Latest
Warning

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

Go to latest
Published: Oct 28, 2026 License: Apache-2.0 Imports: 24 Imported by: 0

Documentation

Overview

Package epform is the form contract of an endpoint (#2176): a bound script that defines form_spec(req) and form_submit(req, values) is a form. A GET is answered with the spec form_spec returns, checked here and signed into a form token; a submission is checked against the spec its token carries (declared fields only, types, required fields, limits, the honeypot and the minimum fill time) before form_submit runs, and form_submit may add its own per-field errors or accept.

Index

Constants

View Source
const (
	// SpecName is called with the request on a GET and returns the spec.
	SpecName = scriptdialect.FormSpecName
	// SubmitName is called with the request and the checked values on a
	// submission, and returns None to accept or {"errors": {...}}.
	SubmitName = scriptdialect.FormSubmitName
)

The functions a form script defines.

View Source
const (
	// TokenField carries the form token the GET issued.
	TokenField = "form_token"
	// HoneypotField is rendered hidden from people; a value in it is a
	// program filling every field it finds, and the submission is refused.
	HoneypotField = "website"
)

The fields a submission carries that are the platform's, not the form's.

View Source
const (
	TypeText           = "text"
	TypeLongText       = "long_text"
	TypeEmail          = "email"
	TypeNumber         = "number"
	TypeDate           = "date"
	TypeSingleChoice   = "single_choice"
	TypeMultipleChoice = "multiple_choice"
	TypeCheckbox       = "checkbox"
	TypeHidden         = "hidden"
	// TypeFile takes files, saved as managed resources (#2333).
	TypeFile = "file"
)

Field types.

View Source
const (
	// DefaultMinFillSeconds is how long after its token was issued a form may
	// be submitted, unless the spec asks for longer.
	DefaultMinFillSeconds = 2

	// DefaultTextLength and DefaultLongTextLength bound a text field that
	// names no max_length; MaxLength is the most any may name.
	DefaultTextLength     = 1000
	DefaultLongTextLength = 10000
	MaxLength             = 100000
)

Bounds of a spec.

View Source
const (
	// DefaultMaxFiles is how many files a file field takes when it names no
	// max_files; MaxFiles is the most any may name.
	DefaultMaxFiles = 1
	MaxFiles        = 20
	// DefaultMaxFileBytes bounds each file of a field that names no
	// max_bytes, below the deployment's upload ceiling when that is lower.
	DefaultMaxFileBytes int64 = 10 << 20
)

Bounds of a file field (#2333).

View Source
const (
	FileKeyName        = "name"
	FileKeyContentType = "content_type"
	FileKeySize        = "size"
	FileKeyURI         = "uri"
	FileKeyResourceID  = "resource_id"
)

The keys each file of a file field is described by: in form_submit's values, and in the stored submission, which adds where it was saved.

View Source
const EmbedLabel = "endpoint-form-embed-v1"

EmbedLabel domain-separates the embed marker key from the viewer token key it is derived from.

View Source
const EmbedParam = "form_embed"

EmbedParam is the query parameter a form's page is handed its embed marker in; the page does not pass it to the form.

View Source
const EmbedTTL = 12 * time.Hour

EmbedTTL is how long an embed marker is honored after the asset it was written into was served.

View Source
const KeyLabel = "endpoint-form-v1"

KeyLabel domain-separates the form token key from the key it is derived from.

View Source
const PagePrefix = "/forms/"

PagePrefix is the hosted form pages' prefix (#2331): a form's page is PagePrefix + its endpoint's name.

View Source
const TokenTTL = 24 * time.Hour

TokenTTL is how long a form may be submitted after it was shown.

View Source
const ViewerHeader = "X-Form-Viewer"

ViewerHeader carries a viewer token on a request to a form.

View Source
const ViewerLabel = "endpoint-form-viewer-v1"

ViewerLabel domain-separates the viewer token key from the form token key it is derived from.

View Source
const ViewerParam = "form_viewer"

ViewerParam is the query parameter a form's page is handed a viewer token in; the page sends it on as ViewerHeader and does not pass it to the form.

View Source
const ViewerTTL = 12 * time.Hour

ViewerTTL is how long a viewer token is honored after the asset it was written into was opened.

Variables

View Source
var ErrRefused = errors.New("the submission was refused")

ErrRefused is a submission refused as a whole rather than field by field: its token is missing, altered, expired or another form's, the honeypot was filled, or it came back sooner than a person fills it in.

Types is every field type, in the order they are documented.

Functions

func Check

func Check(spec Spec, issued time.Time, submitted map[string][]string, files []Upload, now time.Time) (values map[string]any, errs map[string]string, err error)

Check is a submission checked against spec, issued when its token was signed: the values form_submit is handed, by field, or the per-field errors, or ErrRefused when the honeypot was filled or the form came back sooner than a person fills it in. Every declared field is in values: an empty one is "" (a list for a multiple choice or a file field, False for a checkbox). A file field's value describes each of its files, in the order they were sent.

func Defines

func Defines(file *syntax.File) bool

Defines reports whether file is a form script: it defines form_spec taking one parameter and form_submit taking two.

func DefinesSource

func DefinesSource(source string) bool

DefinesSource is Defines over a source, false when it does not parse.

func EmbedKey

func EmbedKey(viewerKey []byte) []byte

EmbedKey is the embed marker key, derived from the viewer token key; nil when that is nil.

func Key

func Key(master []byte) []byte

Key is the form token key, derived from master (the bot check's challenge key, which every replica derives from the browser-session signing key), so a token one replica signs opens on another. Nil when master is nil: such a deployment answers no form.

func OpenEmbed

func OpenEmbed(key []byte, endpoint, token string, now time.Time) bool

OpenEmbed reports whether token is an embed marker signed with key for endpoint and not expired.

func Sign

func Sign(key []byte, endpoint string, spec Spec, now time.Time) (string, error)

Sign is the form token for spec, shown on endpoint at now.

func SignEmbed

func SignEmbed(key []byte, endpoint string, now time.Time) string

SignEmbed is the embed marker for endpoint, honored until now plus EmbedTTL; "" without a key.

func SignViewer

func SignViewer(key []byte, endpoint string, v Viewer, now time.Time) (string, error)

SignViewer is the viewer token for v on endpoint, honored until now plus ViewerTTL.

func ViewerKey

func ViewerKey(formKey []byte) []byte

ViewerKey is the viewer token key, derived from the form token key; nil when that is nil.

Types

type Choice

type Choice struct {
	Value string `json:"value"`
	Label string `json:"label"`
}

Choice is one option of a choice field.

type Field

type Field struct {
	Name     string `json:"name"`
	Label    string `json:"label,omitempty"`
	Type     string `json:"type"`
	Required bool   `json:"required,omitempty"`
	// MaxLength bounds a text, long text or email field's characters.
	MaxLength int `json:"max_length,omitempty"`
	// Min and Max bound a number field.
	Min *float64 `json:"min,omitempty"`
	Max *float64 `json:"max,omitempty"`
	// Help is shown under the field.
	Help    string   `json:"help,omitempty"`
	Choices []Choice `json:"choices,omitempty"`
	// Sensitive is encrypted when the submission is stored (#2179): the
	// form's source and its table hold ciphertext, and the plaintext is read
	// only on the owner's submissions view and through platform.decrypt.
	// form_submit is handed it as typed.
	Sensitive bool `json:"sensitive,omitempty"`
	// MaxFiles, MaxBytes and Accept bound a file field (#2333): how many
	// files, how large each may be, and the content types it takes, judged
	// from each file's bytes ("image/png", or "image/*" for a family; none
	// takes any type).
	MaxFiles int      `json:"max_files,omitempty"`
	MaxBytes int64    `json:"max_bytes,omitempty"`
	Accept   []string `json:"accept,omitempty"`
}

Field is one field of a form.

type Spec

type Spec struct {
	Fields []Field `json:"fields"`
	// Prefill is each field's starting value; a hidden field's is the value a
	// submission must carry back unchanged.
	Prefill map[string]any `json:"prefill,omitempty"`
	// Confirmation is shown once the form is accepted.
	Confirmation string `json:"confirmation,omitempty"`
	// Redirect is where the browser is sent once the form is accepted.
	Redirect string `json:"redirect,omitempty"`
	// MinFillSeconds is how long after it was shown the form may be
	// submitted, at least DefaultMinFillSeconds.
	MinFillSeconds int `json:"min_fill_seconds,omitempty"`
}

Spec is what form_spec returns: the fields, the values they start with, what a person is shown once the form is accepted, and where they are sent.

func Open

func Open(key []byte, endpoint, token string, now time.Time) (Spec, time.Time, error)

Open is the spec a token carries and when it was issued, or ErrRefused with why: no token, one signed with another key or altered, one issued for another endpoint, or one past TokenTTL.

func SpecFrom

func SpecFrom(v starlark.Value) (Spec, error)

SpecFrom reads what form_spec returned into a checked spec.

func (Spec) CheckUploads

func (s Spec) CheckUploads(ceiling int64) error

CheckUploads reports a file field whose max_bytes is past ceiling, the most a managed resource may hold on this deployment (resources.managed.max_upload_bytes).

func (Spec) HasFiles

func (s Spec) HasFiles() bool

HasFiles reports whether the spec declares a file field.

func (Spec) Sensitive

func (s Spec) Sensitive() []string

Sensitive names the spec's sensitive fields, in the order declared.

func (Spec) Validate

func (s Spec) Validate() error

Validate reports the first thing wrong with the spec.

type Upload

type Upload struct {
	Field string
	Name  string
	Data  []byte
}

Upload is one file a submission carries: the field it was sent in, the name the browser gave it, and its bytes.

func Read

func Read(contentType string, body []byte) (map[string][]string, []Upload, error)

Read reads a submission body into each field's values and the files it carries: a urlencoded body and a JSON object alike, where a JSON number, boolean or array of them reads as the strings a urlencoded body would carry, and a multipart/form-data body, the one form a submission with files takes (#2333).

func (Upload) ContentType

func (u Upload) ContentType() string

ContentType is the upload's type, judged from its bytes and never from the name or type the browser sent.

type Viewer

type Viewer struct {
	UserID   string `json:"u"`
	Email    string `json:"m"`
	AuthType string `json:"t,omitempty"`
	Persona  string `json:"p,omitempty"`
	Admin    bool   `json:"a,omitempty"`
}

Viewer is who a signed-in person was when an asset embedding a form was opened for them (#2177). A form inside an asset is framed with the asset's sandbox, whose opaque origin carries no session, so the platform writes this, signed, into the form's address as it serves the asset, and an authenticated form takes it as the caller.

func OpenViewer

func OpenViewer(key []byte, endpoint, token string, now time.Time) (Viewer, error)

OpenViewer is the viewer a token carries, or ErrRefused: altered, signed with another key, issued for another endpoint, or expired.

Jump to

Keyboard shortcuts

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