Skip to content

Commit 65e9e35

Browse files
schicklingclaude
andauthored
Document subtle CORS middleware allowedHeaders behavior (#5936)
Co-authored-by: Claude Sonnet 4.5 <[email protected]>
1 parent ba9e790 commit 65e9e35

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@effect/platform": patch
3+
---
4+
5+
Document subtle CORS middleware `allowedHeaders` behavior: when empty array (default), it reflects back the client's `Access-Control-Request-Headers` (permissive), and when non-empty array, it only allows specified headers (restrictive). Added comprehensive JSDoc with examples.

packages/platform/src/HttpMiddleware.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,56 @@ export const searchParamsParser: <E, R>(
117117
> = internal.searchParamsParser
118118

119119
/**
120+
* Creates a CORS (Cross-Origin Resource Sharing) middleware for HTTP applications.
121+
*
122+
* @param options - CORS configuration options
123+
* @param options.allowedOrigins - Origins allowed to access the resource. Can be:
124+
* - An array of origin strings (e.g., `["https://example.com", "https://api.example.com"]`)
125+
* - A predicate function to dynamically allow origins
126+
* - If empty array (default): allows all origins with `Access-Control-Allow-Origin: *`
127+
* @param options.allowedMethods - HTTP methods allowed for CORS requests.
128+
* Default: `["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"]`
129+
* @param options.allowedHeaders - Headers allowed in CORS requests. **Important behavior**:
130+
* - If empty array (default): reflects back the client's `Access-Control-Request-Headers`,
131+
* effectively allowing all headers requested by the client
132+
* - If non-empty array: only the specified headers are allowed
133+
* - This means the default behavior is permissive, not restrictive
134+
* @param options.exposedHeaders - Headers exposed to the client in the response.
135+
* Default: `[]`
136+
* @param options.maxAge - Maximum time (in seconds) that preflight request results can be cached.
137+
* If not specified, no `Access-Control-Max-Age` header is sent
138+
* @param options.credentials - Whether to allow credentials (cookies, authorization headers, etc.).
139+
* Default: `false`
140+
*
141+
* @example
142+
* ```ts
143+
* import { HttpMiddleware, HttpRouter, HttpServerResponse } from "@effect/platform"
144+
*
145+
* // Allow all origins and reflect requested headers (default behavior)
146+
* HttpRouter.empty.pipe(
147+
* HttpRouter.get("/", HttpServerResponse.empty()),
148+
* HttpMiddleware.cors()
149+
* )
150+
*
151+
* // Restrict to specific origins and headers
152+
* HttpRouter.empty.pipe(
153+
* HttpRouter.get("/", HttpServerResponse.empty()),
154+
* HttpMiddleware.cors({
155+
* allowedOrigins: ["https://example.com"],
156+
* allowedHeaders: ["Content-Type", "Authorization"],
157+
* credentials: true
158+
* })
159+
* )
160+
*
161+
* // Dynamic origin checking with predicate
162+
* HttpRouter.empty.pipe(
163+
* HttpRouter.get("/", HttpServerResponse.empty()),
164+
* HttpMiddleware.cors({
165+
* allowedOrigins: (origin) => origin.endsWith(".example.com")
166+
* })
167+
* )
168+
* ```
169+
*
120170
* @since 1.0.0
121171
* @category constructors
122172
*/

0 commit comments

Comments
 (0)