roc-lang / roc-lang/basic-webserver
Add a typed, explicit CORS policy evaluator
Nobody has claimed this yet.
- Dominant language
- HTML
- Stars
- 107
- Forks
- 20
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 11
Description
Summary
Add a pure Cors module that evaluates actual and preflight requests against an immutable policy.
Illustrative flow:
match Cors.evaluate(policy, request) {
NotCors => handle(request)
Preflight(response) => Ok(Server.respond(response))
Rejected(response) => Ok(Server.respond(response))
Allowed(cors_headers) => {
response = handle(request)?
Ok(Server.respond(Cors.apply(cors_headers, response)?))
}
}
Why this belongs in the platform
CORS is widely supplied by web-framework middleware, including tower-http. Its header interactions are sufficiently subtle that applications should not independently reproduce them.
It should remain an explicit Roc request/response transformation. It does not require a new middleware runtime or host callback.
Required contract
- CORS is disabled unless an application constructs and invokes a policy.
- Exact serialized origins—scheme, host, and port—are the initial allowlist mechanism.
- Treat the special
nullorigin as denied unless explicitly allowed. - Validate requested methods and header names for preflight requests.
- Support configured exposed headers, credential permission, and bounded preflight max age.
- Reject policy construction that combines credentialed requests with wildcard origin.
- Dynamic origin responses merge
Vary: Origincase-insensitively without discarding existingVaryvalues. Access-Control-Allow-Credentialsmust serialize as lowercasetrue.- Preflight responses do not depend on receiving credentials; browsers do not attach credentials to the preflight itself.
- Malformed or conflicting
Originfields produce a deterministic denial. - The result distinguishes non-CORS, allowed actual, successful preflight, and rejected requests.
Documentation must emphasize that CORS is not CSRF protection. A "simple" cross-origin request can still perform a server-side action even when the browser refuses to expose its response.
Non-goals
- Regex or suffix origin matching in the first version
- Guessing trusted origins from
Hostor forwarded headers - CSRF protection
- Authentication or authorization
- Applying CORS automatically to native file or operational routes
- A generic middleware stack
Acceptance criteria
- Actual and preflight requests are handled from the same validated policy.
- Wildcard/credentials and
Varybehavior follow the Fetch Standard. - Origin, method, and header matching have explicit case and normalization rules.
- No CORS behavior is enabled by default.
- Real-listener tests cover allowed, denied, credentialed, and cached variants.
References
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the required contract and the linked WHATWG Fetch Standard CORS sections, then locate the repository's Roc request/response types and real-listener test setup. Define the policy and result boundaries before implementation. Done means actual and preflight cases, normalization, wildcard/credential, Vary, disabled-by-default, and cached variants are covered by real-listener tests.
Written by the indexing model from the issue text.
Assessment
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100