Skip to content
zz-languagePublic

About

Cors for web

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

┌─────────────────────────────────────────────────────────────────┐
│  cors — fine-grained, high-performance CORS for zx web servers  │
└─────────────────────────────────────────────────────────────────┘

CORS middleware for std.http servers in zz. Deny by default, secure-by-default configuration, sub-microsecond hot path, zero per-request regex compilation, and full socket-less test coverage.

Install

zz add cors

Quick start

import cors
import std.http

func main() {
    s := http.server()
    s = s.route("GET", "/api/hi", |_req| "hi")
    s = cors.middleware(s, cors.allow(["https://app.example.com"]))
    http.listen(s, 8080) ?? println("failed to start server")
}

Security by default

cors.config() denies every origin. Opt into each behavior:

cfg := cors.config()
cfg = cors.set_allow_origin(cfg, "https://app.example.com")
cfg = cors.set_allow_credentials(cfg, true)   // never combined with "*"
cfg = cors.set_max_age(cfg, 86400)            // preflight cache
s = cors.middleware(s, cfg)

Or use shorthand constructors:

cors.allow(["https://app.example.com"])        // exact match list
cors.allow_all()                                // "*" — NO credentials
cors.dynamic(|o: str| str.ends_with(o, ".example.com"))  // func matcher

API

Function Description
cors.config() Secure default: deny-all config
cors.allow(origins) Config with exact-match origins
cors.allow_all() Config allowing any origin (*)
cors.dynamic(fn) Config with func(origin) -> bool matcher
cors.middleware(server, config) Attach CORS to a server
cors.with(server, config) Alias for middleware
cors.origin_ok(config, origin) Pure origin check (testable)

Builder setters (set_* prefix)

set_allow_origin, set_allow_origin_regex, set_allow_origin_fn, set_allow_credentials, set_expose_headers, set_allow_methods, set_allow_headers, set_max_age, set_vary_origin, set_preflight_status, set_preflight_passthrough, set_reflect_origin

Each returns a new config (immutable-by-value style).

Behavior

Scenario Result
No Origin header Request untouched, no CORS headers
Allowed origin ACAO: <origin>, plus Vary: Origin if dynamic
Denied origin 403 "cors: origin not allowed"
allow_all() ACAO: *
Credentials + wildcard Build-time error; never emitted at runtime
OPTIONS preflight + allowed origin 204 + ACAM, ACAH, ACMA (if >0)
preflight_passthrough OPTIONS falls to route handler
null origin (file://) Denied unless explicitly configured

Security rules

  1. Never * + credentials — build-time error.
  2. Never reflect arbitrary Origin — opt-in via set_reflect_origin(true).
  3. Deny by default — empty origins = no CORS headers.
  4. Preflight only for OPTIONS — other methods never short-circuited.

Examples

Docs

MIT — see LICENSE.

About

Cors for web

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors