You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
add Cloudflare Workers as first-class runtime (default)
New `runtime` config field: `"cloudflare"` (default) or `"lambda"`.
Deploy dispatches to the appropriate backend based on config.
Cloudflare Workers support:
- `deploy-cf.ts`: deploy/destroy/list via CF REST API (no wrangler dep)
- `cloudflare.ts`: Worker entry point using shared `handler.ts` logic
- Config injected into bundle at deploy time via placeholder replacement
- `cloudflare.*` config fields for account ID, worker name, routes
Refactored deploy layer:
- `deploy.ts` → `deploy-lambda.ts` (Lambda-specific)
- New `deploy.ts` dispatcher routes to CF or Lambda
- `tags.ts` lists proxies across both runtimes
- `cli.ts` shows runtime in output, `ls --runtime` filter
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: README.md
+60-45Lines changed: 60 additions & 45 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,12 +1,12 @@
1
1
# cors-prxy
2
2
3
-
Minimal, security-focused Lambda CORS proxy — deploy per-project allowlisted trampolines via CLI or GitHub Actions.
3
+
Minimal, security-focused CORS proxy — deploy per-project allowlisted trampolines to Cloudflare Workers or AWS Lambda via CLI or GitHub Actions.
4
4
5
5
## Why
6
6
7
-
Frontend apps need CORS proxies to fetch OG metadata, RSS feeds, and other cross-origin resources. Public proxies are unreliable and a security risk. Self-hosting is easy but repetitive — every project reinvents the same Lambda + allowlist pattern.
7
+
Frontend apps need CORS proxies to fetch OG metadata, RSS feeds, and other cross-origin resources. Public proxies are unreliable and a security risk. Self-hosting is easy but repetitive — every project reinvents the same proxy + allowlist pattern.
8
8
9
-
`cors-prxy` gives each project its own Lambda proxy with an explicit domain allowlist, deployed via CLI or GitHub Actions.
9
+
`cors-prxy` gives each project its own proxy with an explicit domain allowlist, deployed via CLI or GitHub Actions.
10
10
11
11
## Install
12
12
@@ -32,18 +32,35 @@ Create `.cors-prxy.json` in your project root:
32
32
}
33
33
```
34
34
35
+
This deploys to **Cloudflare Workers** by default. For AWS Lambda, add `"runtime": "lambda"`.
36
+
37
+
### Config fields
38
+
35
39
| Field | Type | Default | Description |
36
40
|-------|------|---------|-------------|
37
-
|`name`|`string`| (required) |Lambda function name / resource identifier |
38
-
|`region`|`string`|`us-east-1`|AWS region|
41
+
|`name`|`string`| (required) |Proxy name / resource identifier |
Request bodies are forwarded automatically for non-GET/HEAD methods. Only configured headers are forwarded — no cookies or credentials leak by default.
88
+
55
89
## CLI
56
90
57
91
```sh
58
-
cors-prxy deploy #create or update Lambda proxy
92
+
cors-prxy deploy #deploy proxy (CF Workers or Lambda)
59
93
cors-prxy deploy -c custom.json
60
94
61
-
cors-prxy ls # list all cors-prxy Lambdas in account
62
-
cors-prxy ls -r us-east-1,eu-west-1
95
+
cors-prxy ls # list all proxies (both runtimes)
96
+
cors-prxy ls --runtime cloudflare
63
97
cors-prxy ls --json
64
98
65
99
cors-prxy status # show current project's proxy info
66
-
cors-prxy logs # tail CloudWatch logs
100
+
cors-prxy logs # tail logs (CloudWatch for Lambda, wrangler for CF)
67
101
cors-prxy logs -f # follow
68
102
69
-
cors-prxy destroy # remove Lambda + IAM role
103
+
cors-prxy destroy # remove proxy
70
104
cors-prxy destroy -y # skip confirmation
71
105
72
106
cors-prxy dev # local proxy on :3849
@@ -75,9 +109,14 @@ cors-prxy dev -p 4000 # custom port
75
109
76
110
### What `deploy` creates
77
111
78
-
-**Lambda function** (Node.js 22.x, ESM) with a [Function URL] (no API Gateway)
79
-
-**IAM execution role** with CloudWatch Logs permissions
80
-
- All resources tagged for discovery (no local state file needed)
112
+
**Cloudflare Workers** (default):
113
+
- Worker script on `workers.dev` subdomain
114
+
- Requires `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID` (or `cloudflare.accountId` in config)
115
+
116
+
**AWS Lambda**:
117
+
- Lambda function (Node.js 22.x, ESM) with a [Function URL] (no API Gateway)
118
+
- IAM execution role with CloudWatch Logs permissions
119
+
- All resources tagged for discovery
81
120
82
121
`deploy` is idempotent: creates if missing, updates if changed.
83
122
@@ -112,61 +151,37 @@ Supports both OIDC and static credentials (`aws-access-key-id` / `aws-secret-acc
112
151
## How it works
113
152
114
153
```
115
-
Browser → Lambda Function URL → Upstream
116
-
(allowlist check) (fetch + cache)
154
+
Browser → CF Worker / Lambda → Upstream
155
+
(allowlist check) (fetch + cache)
117
156
(CORS headers)
118
157
(rate limit)
119
158
```
120
159
121
-
Request: `GET /?url=<encoded-url>`
160
+
Request: `GET /?url=<encoded-url>` (query mode) or `GET /<host>/<path>` (path mode)
122
161
123
162
1. Parse + validate URL against allowlist
124
163
2. If denied: `403 { error: "Domain not allowed", allowed: [...] }`
125
-
3. Check in-memory LRU cache
164
+
3. Check in-memory LRU cache (GET/HEAD only)
126
165
4. Fetch upstream (10s timeout, 5MB size limit)
127
166
5. Return response with CORS headers, cache result
128
167
129
-
### Response headers
130
-
131
-
```
132
-
Access-Control-Allow-Origin: <matchedorigin>
133
-
Access-Control-Allow-Methods: GET, HEAD, OPTIONS
134
-
Access-Control-Max-Age: <fromconfig>
135
-
Cache-Control: public, max-age=<ttl>
136
-
X-Cors-Prxy: <function-name>
137
-
```
138
-
139
168
### Security
140
169
141
170
- **Domain allowlist**: only configured domains are proxied, glob matching via [picomatch]
Add first-class Cloudflare Workers support as a deployment target alongside Lambda. CFW becomes the default runtime — better cold-start performance, global edge deployment, simpler auth model.
6
+
7
+
## Config changes
8
+
9
+
### `runtime` field
10
+
11
+
```typescript
12
+
interfaceCorsProxyConfig {
13
+
// ... existing fields ...
14
+
15
+
/** Deployment runtime. Default: "cloudflare" */
16
+
runtime?:"cloudflare"|"lambda"
17
+
18
+
/** Cloudflare-specific config (when runtime is "cloudflare") */
19
+
cloudflare?: {
20
+
/** CF account ID. Can also be set via CLOUDFLARE_ACCOUNT_ID env var. */
21
+
accountId?:string
22
+
/** Worker name. Defaults to config `name`. */
23
+
workerName?:string
24
+
/** Custom route pattern, e.g. "proxy.example.com/*". Optional — uses workers.dev by default. */
25
+
route?:string
26
+
/** Compatibility date. Default: "2024-01-01" */
27
+
compatibilityDate?:string
28
+
}
29
+
}
30
+
```
31
+
32
+
When `runtime` is `"lambda"` (or unset in legacy configs that already have `region`), behavior is unchanged. When `runtime` is `"cloudflare"` (or unset and no `region`), deploy as a CF Worker.
33
+
34
+
### Default runtime detection
35
+
36
+
- If `runtime` is set explicitly: use it
37
+
- If `region` is set but `runtime` is not: assume `"lambda"` (backwards compat)
38
+
- Otherwise: default to `"cloudflare"`
39
+
40
+
## CLI behavior
41
+
42
+
No new subcommands. Existing commands dispatch on runtime:
43
+
44
+
| Command | Lambda | Cloudflare |
45
+
|---------|--------|------------|
46
+
|`deploy`| Create/update Lambda + Function URL + IAM role | Create/update CF Worker via API |
47
+
|`destroy`| Delete Lambda + IAM role | Delete CF Worker |
Bundle with esbuild, inject config as a `define` constant (similar to Lambda's env var approach but baked into the bundle — CF Workers don't have a great env var story for large configs).
97
+
98
+
### Upload format
99
+
100
+
CF Workers API expects a multipart form upload with:
101
+
-`metadata` part: JSON with `{ "main_module": "index.mjs", "compatibility_date": "..." }`
102
+
-`index.mjs` part: the bundled worker code
103
+
104
+
### Endpoint
105
+
106
+
After deploy, the worker is available at `https://{worker-name}.{account-subdomain}.workers.dev`. The deploy command prints this URL.
107
+
108
+
### Worker metadata / discovery
109
+
110
+
For `ls` to discover CF Workers deployed by cors-prxy, embed metadata in the worker script name or use the CF Workers API to list scripts and check for a naming convention: `cors-prxy-{name}`.
111
+
112
+
## New files
113
+
114
+
```
115
+
src/
116
+
cloudflare.ts # CF Workers entry point (bundled + uploaded)
117
+
deploy-cf.ts # CF API interactions (deploy, destroy, list)
118
+
scripts/
119
+
bundle-cloudflare.js # esbuild bundler for CF Worker
120
+
```
121
+
122
+
`deploy.ts` becomes `deploy-lambda.ts` (rename for clarity), and `deploy.ts` becomes a dispatcher:
Existing `.cors-prxy.json` configs without `runtime` that have `region` set continue to deploy as Lambda (backwards compat). New configs default to Cloudflare.
157
+
158
+
To migrate an existing Lambda proxy to CF:
159
+
1. Add `"runtime": "cloudflare"` + `cloudflare.accountId` to config
160
+
2.`cors-prxy deploy`
161
+
3. Update consumers to new endpoint
162
+
4.`cors-prxy destroy --runtime lambda` to clean up old Lambda
163
+
164
+
## Environment variables
165
+
166
+
| Var | Description |
167
+
|-----|-------------|
168
+
|`CLOUDFLARE_API_TOKEN`| CF API token (same as wrangler) |
169
+
|`CLOUDFLARE_ACCOUNT_ID`| CF account ID (fallback if not in config) |
0 commit comments