Skip to content
wiki edited this page Sep 4, 2026 · 1 revision

rextension-cors

Cross-Origin Resource Sharing for Rex.

go get github.com/kryovyx/rextension-cors
import (
	"github.com/kryovyx/rex"
	cors "github.com/kryovyx/rextension-cors"
)

app := rex.New(
	cors.WithCORS(cors.NewConfig(
		cors.WithAllowedOrigins("https://app.example.com", "http://localhost:3000"),
		cors.WithAllowCredentials(true),
	)),
)

That is the whole setup. The extension attaches one middleware per router at PriorityCORS and decorates responses on the way out.

What it does

  • Answers the origin question: may this origin read my responses?
  • Adds Access-Control-* headers to every response, including 401s, 429s and 500s
  • Sets Vary: Origin correctly, including on the refusal path
  • Advertises preflight methods from the router's own Allow set, so they cannot drift out of step with the routes that exist

What it does not do

  • It does not protect against CSRF. Read CORS is not CSRF — this is the one thing worth knowing before you rely on it.
  • It does not register OPTIONS routes. The router already answers preflights from its Allow set; this middleware decorates that answer.
  • It does not reject disallowed origins with a 403. The request proceeds and the browser enforces the refusal. See How It WorksRefusal is silent.

The default allows nothing

NewDefaultConfig() has an empty allowlist, so every cross-origin request is refused. That is the only safe default: an extension that permitted any origin out of the box would turn adding it into a policy decision its author did not make.

Starting with an empty allowlist logs a warning, so the situation is discovered from the log rather than from a browser console.

Sharing the allowlist with CSRF

An application trusts one set of origins. Write it once:

origins := rextension.OriginPolicy{
	AllowedOrigins:   []string{"https://app.example.com"},
	AllowCredentials: true,
}

app := rex.New(
	cors.WithCORS(cors.NewConfig(cors.WithPolicy(origins))),
	security.WithSecurity(&security.Config{CSRF: security.CSRFConfig{Policy: origins}}),
)

OriginPolicy is declared in rextension, so neither module imports the other.

Pages

Clone this wiki locally