urlpattern

package
v1.0.1 Latest Latest
Warning

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

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

Documentation

Overview

Package urlpattern implements the URL pattern mini-language used for per-schema public routing: parsing, rendering an entity to a path, matching a path back to its variables, and a Router that resolves a path to the schemas that may serve it.

A pattern is a slash-separated path whose segments are either literals or one of the whole-segment tokens {parent}, {slug}, {path}, {year}, {month} and {day}:

/post/{slug}
/blog/{slug}
/docs/{parent}/{slug}
/{year}/{month}/{slug}
/{path}

The last segment is either {slug} or {path}, exactly one of them. {path} is the entity's whole ancestor chain of slugs plus its own, joined by '/' (services/seo/local), so it spans one to MaxPathDepth URL segments. {parent} is optional at render and match time: when the parent is empty its segment is omitted (it cannot be combined with {path}). {year} ("2024"), {month} ("05") and {day} ("09") are the entity's publication date.

Locale. Content carries a locale (a BCP 47 tag) but patterns have no language token: the default locale is never in the path, and the public site serves only entities whose locale equals the site language. A second locale would need: a language path token or prefix in a pattern, Resolve returning the locale of the match, a per-locale public filter in place of the exact site language match, hreflang alternates, per-locale sitemaps and feeds, translation links between entities, and an admin language switcher. None of this is built.

The package is pure (no I/O) so it can be unit tested exhaustively.

Index

Constants

View Source
const MaxPathDepth = 8

MaxPathDepth caps the segments a {path} value may have (ancestors plus the entity), so a parent cycle or a hostile URL can never grow without bound.

Variables

View Source
var ErrInvalidPattern = errors.New("invalid url pattern")

ErrInvalidPattern is wrapped by every Parse failure.

View Source
var ErrMissingVar = errors.New("missing url variable")

ErrMissingVar is returned by Render when a required variable is empty.

Functions

func Render

func Render(p *Pattern, v Vars) (string, error)

Render substitutes vars into the pattern. {slug} (or {path}) is required; an empty {parent} omits its segment. Values may not contain '/', except a {path} value, whose segments must be non-empty and at most MaxPathDepth.

func SplitPath

func SplitPath(path string) []string

SplitPath returns the segments of a {path} value.

Types

type Candidate

type Candidate struct {
	// SchemaSlug is the schema's own slug; SchemaSlugs is the slug plus its
	// aliases, i.e. every schema slug whose rows may be served here.
	SchemaSlug  string
	SchemaSlugs []string
	Pattern     *Pattern
	Vars        Vars
	// Override is non-nil when the match came from an override pattern: the
	// caller must verify the entity's attribute equals Override.Equals.
	Override *Override
}

Candidate is one way a request path can be served.

type Override

type Override struct {
	Attribute    string
	Equals       string
	Pattern      string
	SitemapGroup string
}

Override swaps the pattern for entities whose attribute Attribute equals Equals. SitemapGroup optionally names a different sitemap child.

type Pattern

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

Pattern is a parsed URL pattern.

func Parse

func Parse(pattern string) (*Pattern, error)

Parse validates and parses a pattern.

func (*Pattern) FirstLiteral

func (p *Pattern) FirstLiteral() string

FirstLiteral returns the first path segment when it is a literal (for example "post" for /post/{slug}), or "" when the pattern starts with a token.

func (*Pattern) HasDate

func (p *Pattern) HasDate() bool

HasDate reports whether the pattern has a {year}, {month} or {day} token.

func (*Pattern) HasParent

func (p *Pattern) HasParent() bool

HasParent reports whether the pattern has an (optional) {parent} token.

func (*Pattern) HasPath

func (p *Pattern) HasPath() bool

HasPath reports whether the pattern ends in {path}.

func (*Pattern) LiteralCount

func (p *Pattern) LiteralCount() int

LiteralCount is the number of literal segments (higher = more specific).

func (*Pattern) Segments

func (p *Pattern) Segments() []Segment

Segments returns a copy of the parsed segments.

func (*Pattern) String

func (p *Pattern) String() string

String returns the original pattern text.

func (*Pattern) TokenCount

func (p *Pattern) TokenCount() int

TokenCount is the number of token segments.

type Router

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

Router resolves paths to candidate schemas and entities to URLs. It is immutable after NewRouter and safe for concurrent use.

func NewRouter

func NewRouter(routes []SchemaRoute) (*Router, error)

NewRouter parses every route. It fails on the first invalid pattern.

func (*Router) CanonicalSchema

func (r *Router) CanonicalSchema(schemaSlug string) (string, bool)

CanonicalSchema maps a schema slug or alias to the owning schema's own slug.

func (*Router) Lookup

func (r *Router) Lookup(schemaSlug string, attrs map[string]string) (Target, bool)

Lookup returns the pattern for an entity of schemaSlug (own slug or alias). attrs are the entity's attributes flattened to strings; the first matching override wins.

func (*Router) Resolve

func (r *Router) Resolve(path string) []Candidate

Resolve returns every candidate whose pattern matches path, most specific first (more literal segments, then fewer tokens, then schema slug order).

func (*Router) SchemaSlugs

func (r *Router) SchemaSlugs(schemaSlug string) []string

SchemaSlugs returns the schema's own slug plus aliases for any known slug.

func (*Router) URLFor

func (r *Router) URLFor(schemaSlug string, attrs map[string]string, v Vars) (string, bool, error)

URLFor renders the canonical path for an entity. It returns false when the schema is unknown to the router; the error reports missing variables.

type SchemaRoute

type SchemaRoute struct {
	SchemaSlug   string
	Aliases      []string
	Pattern      string
	SitemapGroup string
	Overrides    []Override
}

SchemaRoute describes how one schema is addressed. Pattern is raw pattern text; Aliases are extra schema slugs resolving to this schema.

type Segment

type Segment struct {
	Literal string
	Token   Token
}

Segment is one path segment: a literal, or a token when Token != TokenNone.

type Target

type Target struct {
	Pattern      *Pattern
	SitemapGroup string
	// Override is non-nil when an override (not the schema's base pattern) applies.
	Override *Override
}

Target is the pattern chosen for one entity.

type Token

type Token int

Token identifies a variable segment.

const (
	// TokenNone marks a literal segment.
	TokenNone Token = iota
	TokenParent
	TokenSlug
	TokenPath
	TokenYear
	TokenMonth
	TokenDay
)

func (Token) String

func (t Token) String() string

type Vars

type Vars struct {
	Slug   string
	Parent string
	// Path is the slash-joined slug chain ending with Slug ("a/b/slug").
	// Render falls back to Slug when it is empty.
	Path string
	// Year, Month and Day are zero-padded ("2024", "05", "09").
	Year, Month, Day string
}

Vars carries the values substituted into / extracted from a pattern.

func Match

func Match(p *Pattern, path string) (Vars, bool)

Match extracts variables from path. The path must be absolute; a single trailing slash is ignored. A pattern with {parent} also matches the path without that segment (Parent left empty).

Jump to

Keyboard shortcuts

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