@jakuta-inc/worker-proxy 4.0.0 → 5.0.1
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/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/same-origin-proxy.d.ts +131 -45
- package/dist/same-origin-proxy.d.ts.map +1 -1
- package/dist/same-origin-proxy.js +112 -91
- package/dist/same-origin-proxy.js.map +1 -1
- package/dist/venture_api_route.d.ts +13 -0
- package/dist/venture_api_route.d.ts.map +1 -0
- package/dist/venture_api_route.js +21 -0
- package/dist/venture_api_route.js.map +1 -0
- package/package.json +28 -28
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
export { ADMIN_API_BASE,
|
|
1
|
+
export type { Backend, PathRewrite, Route, HealthProbeResult, ProxyHealthCheck, ProxyHandlerConfig, ProxyOutcome, ProxyHandler, ProxyError, } from "./same-origin-proxy.js";
|
|
2
|
+
export { ADMIN_API_BASE, createProxyHandler, createAdminAuthRoute, } from "./same-origin-proxy.js";
|
|
3
|
+
export { VENTURE_API_PREFIX, createVentureApiRoute, } from "./venture_api_route.js";
|
|
3
4
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,OAAO,EACP,WAAW,EACX,KAAK,EACL,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,UAAU,GACX,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export { ADMIN_API_BASE,
|
|
1
|
+
export { ADMIN_API_BASE, createProxyHandler, createAdminAuthRoute, } from "./same-origin-proxy.js";
|
|
2
|
+
export { VENTURE_API_PREFIX, createVentureApiRoute, } from "./venture_api_route.js";
|
|
2
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC"}
|
|
@@ -1,20 +1,107 @@
|
|
|
1
1
|
export declare const ADMIN_API_BASE = "https://jakuta-admin-api.fly.dev";
|
|
2
|
+
interface BackendBase {
|
|
3
|
+
readonly base: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* A backend identity. The `kind` discriminant determines the cookie-transform
|
|
7
|
+
* policy applied when forwarding a request to this backend:
|
|
8
|
+
*
|
|
9
|
+
* - `"admin"` — the admin backend owns the `admin_session` cookie, so the
|
|
10
|
+
* inbound `Cookie` header is preserved verbatim on the outbound hop. Any
|
|
11
|
+
* inbound `X-Admin-Session` header is stripped first, because that header
|
|
12
|
+
* is a proxy-internal trust boundary and a client that sets it is
|
|
13
|
+
* attempting forgery.
|
|
14
|
+
* - `"venture"` — a venture backend must never see the raw `admin_session`
|
|
15
|
+
* cookie. The proxy deletes the `Cookie` header and, if an `admin_session`
|
|
16
|
+
* was present, injects `X-Admin-Session: <session_id>` carrying the raw
|
|
17
|
+
* session id for `admin-client`'s `extract_session_from_handoff_header`.
|
|
18
|
+
* Any inbound `X-Admin-Session` header is stripped first (forgery defense).
|
|
19
|
+
*
|
|
20
|
+
* Cookie-transform semantics are an attribute of the Backend, not of the
|
|
21
|
+
* Route. There is no per-route override. Any caller that could point a route
|
|
22
|
+
* at the admin backend while running the venture cookie-stripping transform
|
|
23
|
+
* would break web session restore on admin-api; attaching the transform to
|
|
24
|
+
* backend identity makes that state unrepresentable.
|
|
25
|
+
*/
|
|
26
|
+
export type Backend = (BackendBase & {
|
|
27
|
+
readonly kind: "admin";
|
|
28
|
+
}) | (BackendBase & {
|
|
29
|
+
readonly kind: "venture";
|
|
30
|
+
});
|
|
2
31
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
32
|
+
* A path-rewrite policy applied to the incoming pathname before forwarding.
|
|
33
|
+
* Either an identity passthrough or an explicit transform function. Encoded
|
|
34
|
+
* as a discriminated union so `createProxyHandler` callers cannot omit the
|
|
35
|
+
* decision — every Route states its rewrite policy explicitly.
|
|
5
36
|
*/
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
37
|
+
export type PathRewrite = {
|
|
38
|
+
readonly kind: "identity";
|
|
39
|
+
} | {
|
|
40
|
+
readonly kind: "transform";
|
|
41
|
+
readonly apply: (incomingPath: string) => string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* A single proxy route. Matched by `pathPrefix` as exact-equal OR
|
|
45
|
+
* prefix-followed-by-slash (so `/api` matches `/api` and `/api/foo` but not
|
|
46
|
+
* `/apiary`). First match in the route list wins.
|
|
47
|
+
*
|
|
48
|
+
* @field pathPrefix - Path prefix to match against the incoming request pathname
|
|
49
|
+
* @field target - Backend to forward matched requests to
|
|
50
|
+
* @field rewrite - Path rewrite policy applied before forwarding
|
|
51
|
+
*/
|
|
52
|
+
export interface Route {
|
|
53
|
+
readonly pathPrefix: string;
|
|
54
|
+
readonly target: Backend;
|
|
55
|
+
readonly rewrite: PathRewrite;
|
|
9
56
|
}
|
|
10
57
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
58
|
+
* Result of probing a backend's `/health` endpoint.
|
|
59
|
+
*
|
|
60
|
+
* @field status - `"ok"` if the backend responded with a 2xx, `"error"` on non-2xx or network failure
|
|
61
|
+
* @field probeUrl - The full URL that was probed, useful for error reporting
|
|
14
62
|
*/
|
|
15
|
-
export interface
|
|
16
|
-
|
|
63
|
+
export interface HealthProbeResult {
|
|
64
|
+
readonly status: "ok" | "error";
|
|
65
|
+
readonly probeUrl: string;
|
|
17
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Health-check hook configuration. The unified proxy handler probes every
|
|
69
|
+
* backend in `probeTargets` in parallel and hands the results to
|
|
70
|
+
* `buildHealthResponse`, which is responsible for shaping the final response
|
|
71
|
+
* JSON and status code. Different frontends want different health payload
|
|
72
|
+
* shapes — the venture frontend reports both venture and admin, the central
|
|
73
|
+
* admin frontend reports admin only — so the handler does not hardcode a
|
|
74
|
+
* shape.
|
|
75
|
+
*
|
|
76
|
+
* The `results` map is keyed by backend kind (`"admin"` or `"venture"`). A
|
|
77
|
+
* `probeTargets` list that contains two backends of the same kind will have
|
|
78
|
+
* the later probe overwrite the earlier one in the map — do not pass
|
|
79
|
+
* duplicates.
|
|
80
|
+
*/
|
|
81
|
+
export type ProxyHealthCheck = {
|
|
82
|
+
readonly kind: "disabled";
|
|
83
|
+
} | {
|
|
84
|
+
readonly kind: "enabled";
|
|
85
|
+
readonly path: string;
|
|
86
|
+
readonly probeTargets: readonly Backend[];
|
|
87
|
+
readonly buildHealthResponse: (results: Record<string, HealthProbeResult>) => Response;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Declarative configuration for `createProxyHandler`.
|
|
91
|
+
*
|
|
92
|
+
* @field routes - Ordered list of routes; first match wins
|
|
93
|
+
* @field healthCheck - Health-check hook configuration (use `{ kind: "disabled" }` to skip)
|
|
94
|
+
*/
|
|
95
|
+
export interface ProxyHandlerConfig {
|
|
96
|
+
readonly routes: readonly Route[];
|
|
97
|
+
readonly healthCheck: ProxyHealthCheck;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Outcome of `ProxyHandler.handleRequest`. Either the request was proxied
|
|
101
|
+
* (in which case the caller should return `proxiedResponse` to the client)
|
|
102
|
+
* or it was not matched by any route (in which case the caller should fall
|
|
103
|
+
* through to its next handler, typically OpenNext/Next.js).
|
|
104
|
+
*/
|
|
18
105
|
export type ProxyOutcome = {
|
|
19
106
|
readonly proxied: true;
|
|
20
107
|
readonly proxiedResponse: Response;
|
|
@@ -22,55 +109,54 @@ export type ProxyOutcome = {
|
|
|
22
109
|
readonly proxied: false;
|
|
23
110
|
};
|
|
24
111
|
/**
|
|
112
|
+
* A structured proxy-internal error surfaced as a JSON 502 to the client.
|
|
113
|
+
*
|
|
25
114
|
* @field kind - Discriminant tag for the error variant
|
|
26
115
|
* @field target - Full URL that the proxy attempted to reach
|
|
27
|
-
* @field
|
|
116
|
+
* @field backendKind - Kind of backend that was unreachable
|
|
28
117
|
*/
|
|
29
|
-
export
|
|
30
|
-
kind: "backend_unreachable";
|
|
31
|
-
target: string;
|
|
32
|
-
|
|
33
|
-
}
|
|
118
|
+
export interface ProxyError {
|
|
119
|
+
readonly kind: "backend_unreachable";
|
|
120
|
+
readonly target: string;
|
|
121
|
+
readonly backendKind: Backend["kind"];
|
|
122
|
+
}
|
|
34
123
|
/**
|
|
124
|
+
* The public proxy interface. Built by `createProxyHandler`.
|
|
125
|
+
*
|
|
35
126
|
* @field handleRequest - Route an incoming worker request through the proxy, returning a proxied response or fall-through signal
|
|
36
127
|
*/
|
|
37
128
|
export interface ProxyHandler {
|
|
38
129
|
handleRequest(workerRequest: Request): Promise<ProxyOutcome>;
|
|
39
130
|
}
|
|
40
131
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
132
|
+
* Build a `Route` that proxies `/auth/*` to the admin backend's `/api/auth/*`
|
|
133
|
+
* surface with cookies preserved. Every frontend that renders admin-shell's
|
|
134
|
+
* login UI needs this route, because admin-shell's `AdminRoute.*` constants
|
|
135
|
+
* (`/auth/login`, `/auth/logout`, `/auth/session`) are the single source of
|
|
136
|
+
* truth for the browser-facing path — the admin-api surface lives at
|
|
137
|
+
* `/api/auth/*`, and the rewrite connects the two.
|
|
44
138
|
*
|
|
45
|
-
*
|
|
139
|
+
* Spread the result into your `routes` array; do not hand-maintain the
|
|
140
|
+
* rewrite.
|
|
46
141
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* internal trust boundary and a client that tries to set it is attempting
|
|
50
|
-
* forgery. On the venture-api hop the handler then reads the
|
|
51
|
-
* `admin_session` cookie, strips it (so venture backends never see it),
|
|
52
|
-
* and — if present — injects an `X-Admin-Session: <session_id>` header
|
|
53
|
-
* carrying the raw value for `jakuta-admin-client`'s
|
|
54
|
-
* `extract_session_from_handoff_header` to consume on the Rust side.
|
|
55
|
-
*
|
|
56
|
-
* If no cookie is present, no header is injected, and venture-api returns
|
|
57
|
-
* 401. There is deliberately no fallback path — see the integration guide
|
|
58
|
-
* section 13 for the full trust model.
|
|
59
|
-
*
|
|
60
|
-
* @param proxyConfig - Backend origins to proxy to; bound once at Worker startup
|
|
61
|
-
* @returns ProxyHandler that routes /api/*, /auth/*, and /_proxy/health requests
|
|
142
|
+
* @param adminBase - Origin of the jakuta-admin API (e.g. ADMIN_API_BASE)
|
|
143
|
+
* @returns A Route that matches `/auth` / `/auth/*` and forwards to `adminBase/api/auth/*`
|
|
62
144
|
*/
|
|
63
|
-
export declare function
|
|
145
|
+
export declare function createAdminAuthRoute(adminBase: string): Route;
|
|
64
146
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
147
|
+
* Build a `ProxyHandler` from a declarative `ProxyHandlerConfig`. This is the
|
|
148
|
+
* single handler constructor — there is no separate venture or central-admin
|
|
149
|
+
* handler. Consumers express their routing topology as a list of
|
|
150
|
+
* `Route`s pointing at `Backend`s, and the handler dispatches by first-match.
|
|
151
|
+
*
|
|
152
|
+
* The cookie transform applied on each hop is determined by the target
|
|
153
|
+
* backend's `kind` (`"admin"` → preserve cookie, `"venture"` → cookie-to-header
|
|
154
|
+
* handoff). There is no per-route override. See the `Backend` doc comment for
|
|
155
|
+
* why this is unrepresentable state, not a missing feature.
|
|
71
156
|
*
|
|
72
|
-
* @param
|
|
73
|
-
* @returns ProxyHandler
|
|
157
|
+
* @param config - Declarative route list and health-check hook
|
|
158
|
+
* @returns A ProxyHandler whose `handleRequest` dispatches the inbound request
|
|
74
159
|
*/
|
|
75
|
-
export declare function
|
|
160
|
+
export declare function createProxyHandler(config: ProxyHandlerConfig): ProxyHandler;
|
|
161
|
+
export {};
|
|
76
162
|
//# sourceMappingURL=same-origin-proxy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"same-origin-proxy.d.ts","sourceRoot":"","sources":["../src/same-origin-proxy.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,qCAAqC,CAAC;AAEjE
|
|
1
|
+
{"version":3,"file":"same-origin-proxy.d.ts","sourceRoot":"","sources":["../src/same-origin-proxy.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,qCAAqC,CAAC;AAEjE,UAAU,WAAW;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,MAAM,OAAO,GACf,CAAC,WAAW,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,GAC1C,CAAC,WAAW,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAAE,GAC7B;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE,CAAC;AAErF;;;;;;;;GAQG;AACH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;CAC/B;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAAE,GAC7B;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,SAAS,OAAO,EAAE,CAAC;IAC1C,QAAQ,CAAC,mBAAmB,EAAE,CAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,KACvC,QAAQ,CAAC;CACf,CAAC;AAEN;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC;CACxC;AAED;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,eAAe,EAAE,QAAQ,CAAA;CAAE,GAC9D;IAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC;AAEhC;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CACvC;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,aAAa,CAAC,aAAa,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC9D;AAuMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,KAAK,CAS7D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY,CA+C3E"}
|
|
@@ -59,8 +59,9 @@ function stripInboundHandoffHeader(originalHeaders) {
|
|
|
59
59
|
return stripped;
|
|
60
60
|
}
|
|
61
61
|
async function forwardToBackend(forwardInput) {
|
|
62
|
-
const
|
|
63
|
-
const
|
|
62
|
+
const target = forwardInput.target;
|
|
63
|
+
const targetUrl = new URL(forwardInput.targetPath + forwardInput.originalUrl.search, target.base);
|
|
64
|
+
const forwardedHeaders = target.kind === "venture"
|
|
64
65
|
? buildVentureForwardedHeaders(forwardInput.originalRequest.headers)
|
|
65
66
|
: stripInboundHandoffHeader(forwardInput.originalRequest.headers);
|
|
66
67
|
try {
|
|
@@ -75,122 +76,142 @@ async function forwardToBackend(forwardInput) {
|
|
|
75
76
|
const proxyError = {
|
|
76
77
|
kind: "backend_unreachable",
|
|
77
78
|
target: targetUrl.toString(),
|
|
78
|
-
|
|
79
|
+
backendKind: target.kind,
|
|
79
80
|
};
|
|
80
81
|
return jsonErrorResponse({
|
|
81
82
|
httpStatus: 502,
|
|
82
83
|
errorBody: {
|
|
83
84
|
error: proxyError.kind,
|
|
84
85
|
target: proxyError.target,
|
|
85
|
-
backend: proxyError.
|
|
86
|
-
message: `Proxy couldn't reach the ${proxyError.
|
|
86
|
+
backend: proxyError.backendKind,
|
|
87
|
+
message: `Proxy couldn't reach the ${proxyError.backendKind} backend at ${proxyError.target}. Check the configured health path to verify the backend is reachable.`,
|
|
87
88
|
},
|
|
88
89
|
});
|
|
89
90
|
}
|
|
90
91
|
}
|
|
92
|
+
function matchPathPrefix(params) {
|
|
93
|
+
if (params.pathname === params.prefix) {
|
|
94
|
+
return { kind: "match" };
|
|
95
|
+
}
|
|
96
|
+
if (params.pathname.startsWith(params.prefix + "/")) {
|
|
97
|
+
return { kind: "match" };
|
|
98
|
+
}
|
|
99
|
+
return { kind: "no_match" };
|
|
100
|
+
}
|
|
101
|
+
function assertNeverPathRewrite(rewrite) {
|
|
102
|
+
throw new Error(`unreachable PathRewrite variant: ${JSON.stringify(rewrite)}`);
|
|
103
|
+
}
|
|
104
|
+
function applyPathRewrite(params) {
|
|
105
|
+
switch (params.rewrite.kind) {
|
|
106
|
+
case "identity":
|
|
107
|
+
return params.incomingPath;
|
|
108
|
+
case "transform":
|
|
109
|
+
return params.rewrite.apply(params.incomingPath);
|
|
110
|
+
default:
|
|
111
|
+
return assertNeverPathRewrite(params.rewrite);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function normalizeBackend(backend) {
|
|
115
|
+
return { kind: backend.kind, base: stripTrailingSlash(backend.base) };
|
|
116
|
+
}
|
|
117
|
+
function normalizeRoute(route) {
|
|
118
|
+
return {
|
|
119
|
+
pathPrefix: route.pathPrefix,
|
|
120
|
+
target: normalizeBackend(route.target),
|
|
121
|
+
rewrite: route.rewrite,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function assertNeverHealthCheck(healthCheck) {
|
|
125
|
+
throw new Error(`unreachable ProxyHealthCheck variant: ${JSON.stringify(healthCheck)}`);
|
|
126
|
+
}
|
|
127
|
+
function normalizeHealthCheck(healthCheck) {
|
|
128
|
+
switch (healthCheck.kind) {
|
|
129
|
+
case "disabled":
|
|
130
|
+
return healthCheck;
|
|
131
|
+
case "enabled":
|
|
132
|
+
return {
|
|
133
|
+
kind: "enabled",
|
|
134
|
+
path: healthCheck.path,
|
|
135
|
+
probeTargets: healthCheck.probeTargets.map(normalizeBackend),
|
|
136
|
+
buildHealthResponse: healthCheck.buildHealthResponse,
|
|
137
|
+
};
|
|
138
|
+
default:
|
|
139
|
+
return assertNeverHealthCheck(healthCheck);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
91
142
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
143
|
+
* Build a `Route` that proxies `/auth/*` to the admin backend's `/api/auth/*`
|
|
144
|
+
* surface with cookies preserved. Every frontend that renders admin-shell's
|
|
145
|
+
* login UI needs this route, because admin-shell's `AdminRoute.*` constants
|
|
146
|
+
* (`/auth/login`, `/auth/logout`, `/auth/session`) are the single source of
|
|
147
|
+
* truth for the browser-facing path — the admin-api surface lives at
|
|
148
|
+
* `/api/auth/*`, and the rewrite connects the two.
|
|
97
149
|
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* internal trust boundary and a client that tries to set it is attempting
|
|
101
|
-
* forgery. On the venture-api hop the handler then reads the
|
|
102
|
-
* `admin_session` cookie, strips it (so venture backends never see it),
|
|
103
|
-
* and — if present — injects an `X-Admin-Session: <session_id>` header
|
|
104
|
-
* carrying the raw value for `jakuta-admin-client`'s
|
|
105
|
-
* `extract_session_from_handoff_header` to consume on the Rust side.
|
|
150
|
+
* Spread the result into your `routes` array; do not hand-maintain the
|
|
151
|
+
* rewrite.
|
|
106
152
|
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* section 13 for the full trust model.
|
|
110
|
-
*
|
|
111
|
-
* @param proxyConfig - Backend origins to proxy to; bound once at Worker startup
|
|
112
|
-
* @returns ProxyHandler that routes /api/*, /auth/*, and /_proxy/health requests
|
|
153
|
+
* @param adminBase - Origin of the jakuta-admin API (e.g. ADMIN_API_BASE)
|
|
154
|
+
* @returns A Route that matches `/auth` / `/auth/*` and forwards to `adminBase/api/auth/*`
|
|
113
155
|
*/
|
|
114
|
-
export function
|
|
115
|
-
const ventureBase = stripTrailingSlash(proxyConfig.ventureApiBase);
|
|
116
|
-
const adminBase = stripTrailingSlash(proxyConfig.adminApiBase);
|
|
156
|
+
export function createAdminAuthRoute(adminBase) {
|
|
117
157
|
return {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
probeHealth(ventureBase),
|
|
124
|
-
probeHealth(adminBase),
|
|
125
|
-
]);
|
|
126
|
-
const healthStatus = { venture, admin };
|
|
127
|
-
const allOk = venture.status === "ok" && admin.status === "ok";
|
|
128
|
-
const proxiedResponse = new Response(JSON.stringify(healthStatus), {
|
|
129
|
-
status: allOk ? 200 : 503,
|
|
130
|
-
headers: { "content-type": "application/json" },
|
|
131
|
-
});
|
|
132
|
-
return { proxied: true, proxiedResponse };
|
|
133
|
-
}
|
|
134
|
-
if (pathname === "/api" || pathname.startsWith("/api/")) {
|
|
135
|
-
const proxiedResponse = await forwardToBackend({
|
|
136
|
-
originalRequest: workerRequest,
|
|
137
|
-
originalUrl: requestUrl,
|
|
138
|
-
targetBase: ventureBase,
|
|
139
|
-
targetPath: pathname,
|
|
140
|
-
backendName: "venture",
|
|
141
|
-
});
|
|
142
|
-
return { proxied: true, proxiedResponse };
|
|
143
|
-
}
|
|
144
|
-
if (pathname === "/auth" || pathname.startsWith("/auth/")) {
|
|
145
|
-
const adminPath = "/api" + pathname;
|
|
146
|
-
const proxiedResponse = await forwardToBackend({
|
|
147
|
-
originalRequest: workerRequest,
|
|
148
|
-
originalUrl: requestUrl,
|
|
149
|
-
targetBase: adminBase,
|
|
150
|
-
targetPath: adminPath,
|
|
151
|
-
backendName: "admin",
|
|
152
|
-
});
|
|
153
|
-
return { proxied: true, proxiedResponse };
|
|
154
|
-
}
|
|
155
|
-
return { proxied: false };
|
|
158
|
+
pathPrefix: "/auth",
|
|
159
|
+
target: { kind: "admin", base: stripTrailingSlash(adminBase) },
|
|
160
|
+
rewrite: {
|
|
161
|
+
kind: "transform",
|
|
162
|
+
apply: (incomingPath) => "/api" + incomingPath,
|
|
156
163
|
},
|
|
157
164
|
};
|
|
158
165
|
}
|
|
159
166
|
/**
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
167
|
+
* Build a `ProxyHandler` from a declarative `ProxyHandlerConfig`. This is the
|
|
168
|
+
* single handler constructor — there is no separate venture or central-admin
|
|
169
|
+
* handler. Consumers express their routing topology as a list of
|
|
170
|
+
* `Route`s pointing at `Backend`s, and the handler dispatches by first-match.
|
|
171
|
+
*
|
|
172
|
+
* The cookie transform applied on each hop is determined by the target
|
|
173
|
+
* backend's `kind` (`"admin"` → preserve cookie, `"venture"` → cookie-to-header
|
|
174
|
+
* handoff). There is no per-route override. See the `Backend` doc comment for
|
|
175
|
+
* why this is unrepresentable state, not a missing feature.
|
|
166
176
|
*
|
|
167
|
-
* @param
|
|
168
|
-
* @returns ProxyHandler
|
|
177
|
+
* @param config - Declarative route list and health-check hook
|
|
178
|
+
* @returns A ProxyHandler whose `handleRequest` dispatches the inbound request
|
|
169
179
|
*/
|
|
170
|
-
export function
|
|
171
|
-
const
|
|
180
|
+
export function createProxyHandler(config) {
|
|
181
|
+
const normalizedRoutes = config.routes.map(normalizeRoute);
|
|
182
|
+
const normalizedHealthCheck = normalizeHealthCheck(config.healthCheck);
|
|
172
183
|
return {
|
|
173
184
|
async handleRequest(workerRequest) {
|
|
174
185
|
const requestUrl = new URL(workerRequest.url);
|
|
175
186
|
const pathname = requestUrl.pathname;
|
|
176
|
-
if (
|
|
177
|
-
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
187
|
+
if (normalizedHealthCheck.kind === "enabled" &&
|
|
188
|
+
pathname === normalizedHealthCheck.path) {
|
|
189
|
+
const probeResults = await Promise.all(normalizedHealthCheck.probeTargets.map(async (backend) => {
|
|
190
|
+
const result = await probeHealth(backend.base);
|
|
191
|
+
return [backend.kind, result];
|
|
192
|
+
}));
|
|
193
|
+
const resultsByKind = {};
|
|
194
|
+
for (const [kind, result] of probeResults) {
|
|
195
|
+
resultsByKind[kind] = result;
|
|
196
|
+
}
|
|
197
|
+
const proxiedResponse = normalizedHealthCheck.buildHealthResponse(resultsByKind);
|
|
183
198
|
return { proxied: true, proxiedResponse };
|
|
184
199
|
}
|
|
185
|
-
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
200
|
+
for (const route of normalizedRoutes) {
|
|
201
|
+
const match = matchPathPrefix({ pathname, prefix: route.pathPrefix });
|
|
202
|
+
if (match.kind === "match") {
|
|
203
|
+
const rewrittenPath = applyPathRewrite({
|
|
204
|
+
rewrite: route.rewrite,
|
|
205
|
+
incomingPath: pathname,
|
|
206
|
+
});
|
|
207
|
+
const proxiedResponse = await forwardToBackend({
|
|
208
|
+
originalRequest: workerRequest,
|
|
209
|
+
originalUrl: requestUrl,
|
|
210
|
+
target: route.target,
|
|
211
|
+
targetPath: rewrittenPath,
|
|
212
|
+
});
|
|
213
|
+
return { proxied: true, proxiedResponse };
|
|
214
|
+
}
|
|
194
215
|
}
|
|
195
216
|
return { proxied: false };
|
|
196
217
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"same-origin-proxy.js","sourceRoot":"","sources":["../src/same-origin-proxy.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"same-origin-proxy.js","sourceRoot":"","sources":["../src/same-origin-proxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Route } from "./same-origin-proxy.js";
|
|
2
|
+
export declare const VENTURE_API_PREFIX = "/api";
|
|
3
|
+
/**
|
|
4
|
+
* @why Builds the canonical venture-api route from a venture origin so
|
|
5
|
+
* every venture Worker proxy mounts `/api/*` the same way, keeping the
|
|
6
|
+
* Worker-side path contract aligned with the Rust `VENTURE_API_PREFIX`
|
|
7
|
+
* constant.
|
|
8
|
+
*
|
|
9
|
+
* @param ventureBase - Origin of the venture backend (scheme + host, no path).
|
|
10
|
+
* @returns A Route that matches `/api` / `/api/*` and forwards to `ventureBase`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createVentureApiRoute(ventureBase: string): Route;
|
|
13
|
+
//# sourceMappingURL=venture_api_route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"venture_api_route.d.ts","sourceRoot":"","sources":["../src/venture_api_route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAKpD,eAAO,MAAM,kBAAkB,SAAS,CAAC;AAEzC;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,KAAK,CAMhE"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Mirror of `crates/jakuta-cli-core/src/venture_api_prefix.rs` — the two
|
|
2
|
+
// constants MUST stay byte-identical so venture backends, venture plugins,
|
|
3
|
+
// and venture Worker proxies all agree on where the admin surface is nested.
|
|
4
|
+
export const VENTURE_API_PREFIX = "/api";
|
|
5
|
+
/**
|
|
6
|
+
* @why Builds the canonical venture-api route from a venture origin so
|
|
7
|
+
* every venture Worker proxy mounts `/api/*` the same way, keeping the
|
|
8
|
+
* Worker-side path contract aligned with the Rust `VENTURE_API_PREFIX`
|
|
9
|
+
* constant.
|
|
10
|
+
*
|
|
11
|
+
* @param ventureBase - Origin of the venture backend (scheme + host, no path).
|
|
12
|
+
* @returns A Route that matches `/api` / `/api/*` and forwards to `ventureBase`.
|
|
13
|
+
*/
|
|
14
|
+
export function createVentureApiRoute(ventureBase) {
|
|
15
|
+
return {
|
|
16
|
+
pathPrefix: VENTURE_API_PREFIX,
|
|
17
|
+
target: { kind: "venture", base: ventureBase },
|
|
18
|
+
rewrite: { kind: "identity" },
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=venture_api_route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"venture_api_route.js","sourceRoot":"","sources":["../src/venture_api_route.ts"],"names":[],"mappings":"AAEA,yEAAyE;AACzE,2EAA2E;AAC3E,6EAA6E;AAC7E,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAEzC;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CAAC,WAAmB;IACrD,OAAO;QACH,UAAU,EAAE,kBAAkB;QAC9B,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE;QAC9C,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;KAChC,CAAC;AACN,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@jakuta-inc/worker-proxy",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Same-origin reverse proxy for Jakuta admin panel Cloudflare Workers",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "dist/index.js",
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
8
|
-
"files": [
|
|
9
|
-
"dist"
|
|
10
|
-
],
|
|
11
|
-
"scripts": {
|
|
12
|
-
"build": "tsc",
|
|
13
|
-
"prepublishOnly": "tsc",
|
|
14
|
-
"test": "vitest run"
|
|
15
|
-
},
|
|
16
|
-
"publishConfig": {
|
|
17
|
-
"access": "restricted"
|
|
18
|
-
},
|
|
19
|
-
"repository": {
|
|
20
|
-
"type": "git",
|
|
21
|
-
"url": "https://github.com/Jakuta-Inc/jakuta-admin.git",
|
|
22
|
-
"directory": "packages/worker-proxy"
|
|
23
|
-
},
|
|
24
|
-
"devDependencies": {
|
|
25
|
-
"@cloudflare/workers-types": "^4.20250327.0",
|
|
26
|
-
"typescript": "^5.7.0"
|
|
27
|
-
}
|
|
28
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@jakuta-inc/worker-proxy",
|
|
3
|
+
"version": "5.0.1",
|
|
4
|
+
"description": "Same-origin reverse proxy for Jakuta admin panel Cloudflare Workers",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"prepublishOnly": "tsc",
|
|
14
|
+
"test": "vitest run"
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "restricted"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/Jakuta-Inc/jakuta-admin.git",
|
|
22
|
+
"directory": "packages/worker-proxy"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@cloudflare/workers-types": "^4.20250327.0",
|
|
26
|
+
"typescript": "^5.7.0"
|
|
27
|
+
}
|
|
28
|
+
}
|