Skip to content

struct0x/crum

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

crum

Minimal, secure, and composable cookie builder for Go.

Go Reference Go Report Card

Overview

A tiny, well‑tested builder for constructing validated net/http cookies with secure defaults.

It helps you set Path, Domain, Expires/MaxAge, Secure/HttpOnly, SameSite, and Partitioned coherently while enforcing RFC‑style validation and common security constraints (e.g., SameSite=None requires Secure=true).

Features

Crum’s CookieBuilder produces an *http.Cookie with safe defaults and consistent behavior:

  • Defaults: Path="/", Secure=true, HttpOnly=true, SameSite=Lax, session cookie (no persistence) unless you opt in.
  • Validation: strict name token; rejects control chars, semicolons, commas, and backslashes in values; ASCII enforcement unless you pass a pre‑encoded value.
  • Coherent persistence: TTL() or MaxAgeSeconds() set both MaxAge and Expires; Session() clears them; Delete() sets a past Expires and negative MaxAge and clears the value.
  • Cross‑site safety: SameSiteNone() also enforces Secure(true).
  • Quality of life: normalize Path (empty → "/"), strip leading dot in Domain.
  • FromCookie to transform existing cookies.

Installation

Use standard Go module tooling:

  go get github.com/struct0x/crum

Then import it:

package main

import "github.com/struct0x/crum"

Usage

Here are common scenarios distilled from the public API and tests.

  • Session cookie with secure defaults:
package main

import (
	"github.com/struct0x/crum"
)

func main() {
	c := crum.NewCookie("sid", sessionID).MustBuild()
	// Name=sid, Path=/, Secure, HttpOnly, SameSite=Lax; no Expires/MaxAge
}
  • Persistent cookie (30 days), strict same‑site:
package main

import (
	"github.com/struct0x/crum"
)

func main() {
	c, err := crum.NewCookie("remember", token).
		TTL(30 * 24 * time.Hour).
		SameSiteStrict().
		Build()
	if err != nil { /* handle */
	}
}    
  • Cross‑site flow: SameSite=None (forces Secure=true) with 24h TTL:
package main

import (
	"time"

	"github.com/struct0x/crum"
)

func main() {
	c, err := crum.NewCookie("cs", v).
		SameSiteNone().
		TTL(24 * time.Hour).
		Build()
}
  • Set Domain and normalize Path:
package main

import (
	"github.com/struct0x/crum"
)

func main() {
	c := crum.NewCookie("k", "v").
		Path(""). // normalized to "/"
		Domain(".example.com"). // leading dot stripped → example.com
		MustBuild()
}
  • Delete a cookie previously set (clear value, expire immediately):
package main

import (
	"github.com/struct0x/crum"
)

func main() {
	c := crum.NewCookie("sid", "").Delete().MustBuild()
}
  • Infer persistence from absolute time:
package main

import (
	"github.com/struct0x/crum"
)

func main() {
	c := crum.NewCookie("k", "v").
		Expires(time.Now().Add(2 * time.Hour)).
		MustBuild()
	// MaxAge inferred if omitted
}
  • Start from an existing cookie and transform it:
package main

import (
	"github.com/struct0x/crum"
)

func main() {
	c2 := crum.FromCookie(c1).Delete().MustBuild()
}
  • Advanced/testing: deterministic clock or pre‑encoded value:
package main

import (
	"time"

	"github.com/struct0x/crum"
)

func main() {
	c := crum.NewCookie("k", "v").WithClock(func() time.Time { return fixed }).TTL(time.Hour).MustBuild()
	c := crum.NewCookie("tok", "").UnsafeValue("YWJjMTIzXy0u~").MustBuild()
}
  • Partitioned cookies:
package main

import (
	"github.com/struct0x/crum"
)

func main() {
	c := crum.NewCookie("k", "v").Partitioned(true).MustBuild()
}

API quick reference

  • Construction: NewCookie(name, value), FromCookie(*http.Cookie)
  • Persistence: TTL(d), MaxAgeSeconds(s), Expires(t), Session(), Delete()
  • Attributes: Path(p), Domain(d), Secure(on), HttpOnly(on), SameSiteStrict(), SameSiteLax(), SameSiteNone(), Partitioned(on)
  • Testing/util: WithClock(fn), UnsafeValue(v)
  • Finalize: Build() (*http.Cookie, error), MustBuild() *http.Cookie

Validation highlights enforced by Build():

  • Non‑empty name; strictly validated token (ASCII; no spaces or separators).
  • Value must be ASCII; no control chars, semicolons, commas, or backslashes. Use your own encoding (e.g., URL/base64) for non‑ASCII payloads.
  • SameSite=None requires Secure=true.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

About

Minimal, secure, and composable cookie builder for Go

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages