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

contenturl

package
v0.135.0 Latest Latest
Warning

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

Go to latest
Published: Oct 28, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package contenturl gives content uniform URLs, /{lang}/{route}/{CODE}[/{slug}]: the page's language (every page has one, the default included), a short random code ContentKit assigns once per content record (unique per tenant across every kind), a decorative slug, and the host's route for the content kind. The server reads only the code; any other spelling of the path redirects to the canonical one. ?v= selects a version (VersionParam).

Store registers codes and resolves them (and legacy aliases); Router maps content kinds to the host's routes, decides canonical redirects and serves a JSON lookup. Taxonomy nodes and posts are registered by ContentKit itself; hosts Put their own content.

Index

Constants

View Source
const (
	AliasFound = "found"
)
View Source
const (
	AliasGone = "gone" // its content was removed
)
View Source
const (
	AliasNotFound = "not_found" // unknown, or hidden from the request's visitor
)
View Source
const Alphabet = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"

Alphabet is Crockford base32: digits and uppercase letters without I, L, O, U.

View Source
const CodeLength = 9

CodeLength is the length of a content code.

View Source
const MaxAliases = 100

MaxAliases bounds an AliasLookup.

View Source
const VersionCodeLength = 4

VersionCodeLength is the length of a version code.

View Source
const VersionParam = "v"

VersionParam is the query parameter that selects a version on its content's page: /{lang}/{route}/{CODE}/{slug}?v={version code}. A page without it, or whose code names no live version, shows the language's default edition.

Variables

View Source
var (
	ErrInvalid = codes.ErrInvalid
)
View Source
var (
	ErrInvalidCode = fmt.Errorf("%w: not a content code", codes.ErrInvalid)
)

Functions

func AcceptLanguage added in v0.86.0

func AcceptLanguage(languages []string, header string) string

AcceptLanguage is the first of languages an Accept-Language header names, as a tag or a tag's primary subtag; "" when it names none.

func Slugify

func Slugify(title string) string

Slugify turns a title into a URL slug: ASCII [a-z0-9] words joined by hyphens, diacritics dropped, at most 80 bytes cut at a word boundary. Text without Latin letters or digits gives "" (the URL then has no slug).

Types

type AliasKey added in v0.83.0

type AliasKey struct {
	Source string `json:"source"`
	Kind   string `json:"kind"`
	Key    string `json:"key"`
}

AliasKey names another system's identifier: the system (an import batch's source), the identifier's space and the identifier.

type AliasLookup added in v0.83.0

type AliasLookup struct {
	Aliases []AliasKey `json:"aliases"`
}

AliasLookup is legacy identifiers to resolve, at most MaxAliases.

type AliasMatch

type AliasMatch struct {
	Link
	Locator string
}

AliasMatch is what an alias resolves to.

type AliasResult added in v0.83.0

type AliasResult struct {
	AliasKey
	// Status is found, not_found or gone.
	Status string `json:"status"`
	// Resolved is a found alias's link and canonical path.
	Resolved *Resolved `json:"resolved,omitempty"`
	// Locator is a found alias's position inside its content, such as a page.
	Locator string `json:"locator,omitempty"`
}

AliasResult is what one alias resolves to.

type AliasResults added in v0.83.0

type AliasResults struct {
	Aliases []AliasResult `json:"aliases"`
}

AliasResults answers an AliasLookup in its order.

type Code

type Code string

Code is a content code in canonical form: nine characters of Alphabet, at least one a letter, so no code reads as a numeric id.

func ParseCode

func ParseCode(s string) (Code, error)

ParseCode reads a code with Crockford's decoding rules: any letter case, O as 0, I and L as 1, hyphens ignored. U and every other character are refused, as are any length but nine and an all-digit result (a legacy numeric id such as /watch/346791971 is never a code).

func (Code) String

func (c Code) String() string

func (Code) Valid

func (c Code) Valid() bool

Valid reports whether c is in canonical form.

type Decision

type Decision struct {
	// Matched: the request names visible, routed content. When neither
	// Matched nor Gone, the host serves the request as it would without the
	// router (usually its 404).
	Matched bool
	// Gone: the request names routed content the host removed (410).
	Gone bool
	// Redirect: the path is not canonical; answer 301 to Location.
	Redirect bool
	// Private: matched only for this viewer (Preview); never cache or index it.
	Private  bool
	Link     Link
	Language string
	Path     string // the canonical path
	Location string // Path plus the request's query
}

Decision is the canonical verdict on a request.

type Link struct {
	contentref.ContentRef
	Code  Code              `json:"code"`
	Slug  string            `json:"slug"`
	Slugs map[string]string `json:"slugs,omitempty"`
}

Link is what a code resolves to: the content, its canonical code and slugs. After a merge the content and code are the surviving record's.

func (Link) SlugFor

func (l Link) SlugFor(language string) string

SlugFor returns the slug for language, falling back to the default slug.

type Parsed

type Parsed struct {
	Language string // "" when unprefixed (an old link: it redirects)
	Route    string
	Code     Code   // canonical form
	RawCode  string // as written
	Slug     string // decorative segments as written, "/"-joined; "" when absent
}

Parsed is a content path split into its parts.

func ParsePath

func ParsePath(path string, routes Routes, languages []string) (Parsed, bool)

ParsePath splits [/{language}]/{route}/{code}[/{decorative...}][/] where route is one of routes' values and language one of languages; a path without the language, or with stale or extra decorative segments, is still read, for its redirect. ok is false for any other path, including an invalid code.

type Resolved

type Resolved struct {
	Link
	Path string `json:"path"`
	// VersionID is the live version ?v= names; "" when it names none, and the
	// page shows its language's default edition.
	VersionID string `json:"version_id,omitempty"`
}

Resolved is Handler's response: the link and its canonical path ("" when the kind has no route).

type RouterOptions

type RouterOptions struct {
	// Routes maps content kinds to the host's routes. Required.
	Routes Routes
	// Languages are the site's languages, its default first. Required: every
	// content page is under one (/{lang}/{route}/...), which picks its slug;
	// a request without one redirects to the language Accept-Language names,
	// else the default.
	Languages []string
	// BaseURL ("https://example.com") makes Middleware send the canonical URL
	// as a `Link: <url>; rel="canonical"` header. Empty: no header.
	BaseURL string
	// Visibility is the host's verdict on each resolved link, in order
	// (drafts, removed content, viewer restrictions). nil: every registered
	// code is Visible.
	Visibility func(r *http.Request, links []Link) ([]Visibility, error)
	// Gone answers requests for Gone content. nil: a plain 410.
	Gone http.Handler
	// Logger receives resolution failures (5xx). nil: slog.Default().
	Logger *slog.Logger
}

RouterOptions configures a Router.

type Routes

type Routes map[string]string

Routes maps a content kind to the host's route: the first path segment of its pages ("video" -> "watch", "gallery" -> "g"). Several kinds may share a route; a kind without one has no URL.

func (Routes) Validate

func (r Routes) Validate(languages []string) error

Validate checks every route and language is one lowercase path segment and that no language is also a route.

type VersionCode added in v0.86.0

type VersionCode string

VersionCode is a version's code in canonical form: four characters of Alphabet, at least one a letter, unique within its content and fixed for the version's life.

func (VersionCode) String added in v0.86.0

func (c VersionCode) String() string

type VersionKey added in v0.86.0

type VersionKey struct {
	ContentID string
	Code      VersionCode
}

VersionKey names a version by its content and version code.

type Visibility

type Visibility int

Visibility is the host's verdict on resolved content for one request. The zero value is Hidden, so an unset verdict fails closed.

const (
	// Hidden content answers like an unknown code (the host's 404): no
	// redirect, so nothing about it (its slug) leaks.
	Hidden Visibility = iota
	// Visible content is served and canonicalized.
	Visible
	// Gone content was removed for good: 410, no redirect.
	Gone
	// Preview content is served only to the requesting editor (a draft they
	// may edit): resolved like Visible, never cached or indexed.
	Preview
)

Jump to

Keyboard shortcuts

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