@run402/functions 1.63.0 → 1.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -51
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -147,72 +147,55 @@ Use `adminDb()` (not `db(req)`) here — there's no incoming request to forward.
|
|
|
147
147
|
|
|
148
148
|
## Routed HTTP functions
|
|
149
149
|
|
|
150
|
-
Deploy-v2 web routes can map public same-origin browser paths to functions, for example `routes: { "replace": [{ "pattern": "/api/*", "target": { "type": "function", "name": "api" } }] }`. A browser request to a routed path does **not** need a Run402 API key at the public edge. Direct `/functions/v1/:name` invocation is unchanged: it remains API-key protected and API-shaped.
|
|
150
|
+
Deploy-v2 web routes can map public same-origin browser paths to functions, for example `routes.replace` / `"routes": { "replace": [{ "pattern": "/api/*", "target": { "type": "function", "name": "api" } }] }`. Use exact `/admin` plus final-wildcard `/admin/*` when a dynamic section root and its children should route to the same function. A browser request to a routed path does **not** need a Run402 API key at the public edge. Direct `/functions/v1/:name` invocation is unchanged: it remains API-key protected and API-shaped.
|
|
151
151
|
|
|
152
|
-
Routed browser traffic invokes
|
|
153
|
-
|
|
154
|
-
Request fields:
|
|
155
|
-
- `version`, `method`, `url`, `path`, `rawPath`, `rawQuery`
|
|
156
|
-
- `headers: Array<[string, string]>`
|
|
157
|
-
- `cookies.raw`
|
|
158
|
-
- `body: null | { encoding: "base64"; data; size }`
|
|
159
|
-
- `context.source`, `projectId`, `releaseId`, `deploymentId`, `host`, `proto`, `routePattern`, `routeKind`, `routeTarget`, `requestId`, plus optional `clientIp` and `userAgent`
|
|
160
|
-
|
|
161
|
-
Response fields:
|
|
162
|
-
- `status` from 200 through 599
|
|
163
|
-
- optional duplicate-safe `headers`
|
|
164
|
-
- optional `cookies: string[]`, preserved as separate `Set-Cookie` headers
|
|
165
|
-
- optional base64 `body`
|
|
166
|
-
|
|
167
|
-
Helpers:
|
|
152
|
+
Routed browser traffic invokes the same Node 22 Fetch Request -> Response handler used by direct functions:
|
|
168
153
|
|
|
169
154
|
```ts
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
type RoutedHttpRequestV1,
|
|
173
|
-
type RoutedHttpResponseV1,
|
|
174
|
-
} from "@run402/functions";
|
|
175
|
-
|
|
176
|
-
export default async function handler(
|
|
177
|
-
event: RoutedHttpRequestV1,
|
|
178
|
-
): Promise<RoutedHttpResponseV1> {
|
|
179
|
-
if (!routedHttp.isRequest(event)) {
|
|
180
|
-
return routedHttp.json({ error: "unsupported_event" }, { status: 400 });
|
|
181
|
-
}
|
|
155
|
+
export default async function handler(req: Request): Promise<Response> {
|
|
156
|
+
const url = new URL(req.url);
|
|
182
157
|
|
|
183
|
-
if (
|
|
184
|
-
return
|
|
158
|
+
if (req.method === "OPTIONS") {
|
|
159
|
+
return new Response(null, {
|
|
185
160
|
status: 204,
|
|
186
|
-
headers:
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
161
|
+
headers: {
|
|
162
|
+
"access-control-allow-origin": "https://app.example.com",
|
|
163
|
+
"access-control-allow-methods": "GET, POST, OPTIONS",
|
|
164
|
+
"access-control-allow-headers": "content-type, authorization",
|
|
165
|
+
},
|
|
191
166
|
});
|
|
192
167
|
}
|
|
193
168
|
|
|
194
|
-
if (
|
|
195
|
-
return
|
|
169
|
+
if (req.method === "POST" && !req.headers.has("x-csrf-token")) {
|
|
170
|
+
return Response.json({ error: "csrf_required" }, { status: 403 });
|
|
196
171
|
}
|
|
197
172
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
cookies: [
|
|
203
|
-
"sid=abc; HttpOnly; Secure; SameSite=Lax; Path=/",
|
|
204
|
-
"theme=dark; Secure; SameSite=Lax; Path=/",
|
|
205
|
-
],
|
|
206
|
-
},
|
|
207
|
-
);
|
|
173
|
+
const headers = new Headers({ "cache-control": "private, no-store" });
|
|
174
|
+
headers.append("Set-Cookie", "sid=abc; HttpOnly; Secure; SameSite=Lax; Path=/");
|
|
175
|
+
headers.append("Set-Cookie", "theme=dark; Secure; SameSite=Lax; Path=/");
|
|
176
|
+
return Response.json({ ok: true, path: url.pathname, query: url.search }, { headers });
|
|
208
177
|
}
|
|
209
178
|
```
|
|
210
179
|
|
|
211
|
-
|
|
180
|
+
Request fields:
|
|
181
|
+
- `req.method` is the original browser method. `GET` routes also match `HEAD`; `HEAD` reaches the handler as `HEAD`.
|
|
182
|
+
- `req.url` is the full public URL, including scheme, host, path, and query, on managed subdomains, deployment hosts, and verified custom domains. Derive OAuth callback URLs from `new URL(req.url).origin`.
|
|
183
|
+
- `req.headers` is a Fetch `Headers` object. Cookie data is available through the `cookie` header.
|
|
184
|
+
- `await req.text()`, `await req.json()`, and `await req.arrayBuffer()` read the buffered request body, capped at 6 MiB.
|
|
185
|
+
|
|
186
|
+
Response behavior:
|
|
187
|
+
- Return a Web `Response` with status 200 through 599 except `101 Switching Protocols`.
|
|
188
|
+
- Append each cookie with `headers.append("Set-Cookie", value)`; Run402 preserves multiple `Set-Cookie` values as separate browser headers.
|
|
189
|
+
- Redirects are ordinary 3xx responses with a `Location` header. `HEAD` responses send headers without body bytes.
|
|
190
|
+
- Request and response bodies are capped at 6 MiB. WebSockets, `101 Switching Protocols`, streaming, and SSE are not supported in Phase 1.
|
|
191
|
+
|
|
192
|
+
Limits and defaults: Run402 does not add wildcard CORS. Run402 does not store routed dynamic responses in a shared cache; if your function sets no `Cache-Control`, the gateway adds `Cache-Control: private, no-store` and `x-run402-cache: dynamic-bypass`.
|
|
193
|
+
|
|
194
|
+
Security notes: application auth, authorization, sessions, OAuth callbacks, CORS, and CSRF belong in your function code. For cookie-authenticated `POST`, `PUT`, `PATCH`, or `DELETE`, validate a CSRF token or an equivalent same-site defense. Do not trust spoofable forwarding headers for authorization.
|
|
212
195
|
|
|
213
|
-
|
|
196
|
+
The raw `run402.routed_http.v1` envelope is an internal gateway transport. Low-level `routedHttp` helpers and `RoutedHttpRequestV1` / `RoutedHttpResponseV1` types remain exported for tests and gateway-adjacent utilities, but browser route handlers should use Fetch `Request` and `Response`.
|
|
214
197
|
|
|
215
|
-
|
|
198
|
+
Runtime route failure codes to branch on: `ROUTE_MANIFEST_LOAD_FAILED` (manifest/propagation), `ROUTED_INVOKE_WORKER_SECRET_MISSING` (custom-domain Worker secret), `ROUTED_INVOKE_AUTH_FAILED` (internal invoke signature), `ROUTED_ROUTE_STALE` (selected route failed release revalidation), `ROUTE_METHOD_NOT_ALLOWED` (method mismatch), and `ROUTED_RESPONSE_TOO_LARGE` (body over 6 MiB).
|
|
216
199
|
|
|
217
200
|
## Imports auto-resolved
|
|
218
201
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@run402/functions",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.64.0",
|
|
4
4
|
"description": "In-function helper library for Run402 serverless functions — db, adminDb, getUser, email, ai. Auto-bundled into deployed functions; also installable for local TypeScript autocomplete.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|