@jakuta-inc/worker-proxy 2.1.0 → 4.0.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/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/same-origin-proxy.d.ts +41 -2
- package/dist/same-origin-proxy.d.ts.map +1 -1
- package/dist/same-origin-proxy.js +97 -6
- package/dist/same-origin-proxy.js.map +1 -1
- package/package.json +28 -28
- package/dist/same-origin-proxy.test.d.ts +0 -2
- package/dist/same-origin-proxy.test.d.ts.map +0 -1
- package/dist/same-origin-proxy.test.js +0 -194
- package/dist/same-origin-proxy.test.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
export { ADMIN_API_BASE,
|
|
1
|
+
export type { VentureProxyConfig, CentralAdminProxyConfig, ProxyOutcome, ProxyHandler, ProxyError } from "./same-origin-proxy.js";
|
|
2
|
+
export { ADMIN_API_BASE, createVentureProxyHandler, createCentralAdminProxyHandler } from "./same-origin-proxy.js";
|
|
3
3
|
//# 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,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAClI,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { ADMIN_API_BASE,
|
|
1
|
+
export { ADMIN_API_BASE, createVentureProxyHandler, createCentralAdminProxyHandler } from "./same-origin-proxy.js";
|
|
2
2
|
//# 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":"AACA,OAAO,EAAE,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -3,10 +3,18 @@ export declare const ADMIN_API_BASE = "https://jakuta-admin-api.fly.dev";
|
|
|
3
3
|
* @field ventureApiBase - Origin of the venture's Fly.io backend (e.g. "https://venoble-backend.fly.dev")
|
|
4
4
|
* @field adminApiBase - Origin of the jakuta-admin API on Fly.io (e.g. "https://jakuta-admin-api.fly.dev")
|
|
5
5
|
*/
|
|
6
|
-
export interface
|
|
6
|
+
export interface VentureProxyConfig {
|
|
7
7
|
ventureApiBase: string;
|
|
8
8
|
adminApiBase: string;
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* @field adminApiBase - Origin of the jakuta-admin API on Fly.io. The central
|
|
12
|
+
* admin frontend has no venture backend — /api/* resolves to the admin API
|
|
13
|
+
* directly.
|
|
14
|
+
*/
|
|
15
|
+
export interface CentralAdminProxyConfig {
|
|
16
|
+
adminApiBase: string;
|
|
17
|
+
}
|
|
10
18
|
export type ProxyOutcome = {
|
|
11
19
|
readonly proxied: true;
|
|
12
20
|
readonly proxiedResponse: Response;
|
|
@@ -30,8 +38,39 @@ export interface ProxyHandler {
|
|
|
30
38
|
handleRequest(workerRequest: Request): Promise<ProxyOutcome>;
|
|
31
39
|
}
|
|
32
40
|
/**
|
|
41
|
+
* Venture frontend proxy handler. Routes `/api/*` to the venture's own
|
|
42
|
+
* backend and `/auth/*` to the admin backend (rewriting `/auth/*` to
|
|
43
|
+
* `/api/auth/*`). This is the correct handler for every venture frontend.
|
|
44
|
+
*
|
|
45
|
+
* # Cookie-to-header handoff (venture `/api/*` branch)
|
|
46
|
+
*
|
|
47
|
+
* On every inbound request the handler unconditionally strips any
|
|
48
|
+
* `X-Admin-Session` header a client may have set — the header is an
|
|
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
|
+
*
|
|
33
60
|
* @param proxyConfig - Backend origins to proxy to; bound once at Worker startup
|
|
34
61
|
* @returns ProxyHandler that routes /api/*, /auth/*, and /_proxy/health requests
|
|
35
62
|
*/
|
|
36
|
-
export declare function
|
|
63
|
+
export declare function createVentureProxyHandler(proxyConfig: VentureProxyConfig): ProxyHandler;
|
|
64
|
+
/**
|
|
65
|
+
* Central admin frontend proxy handler. Routes `/api/*` to the admin backend
|
|
66
|
+
* with cookies preserved — the central admin frontend IS the admin frontend,
|
|
67
|
+
* so its `admin_session` cookie must reach `jakuta-admin-api` unmodified.
|
|
68
|
+
* Does NOT handle `/auth/*` because the central admin frontend calls
|
|
69
|
+
* `/api/auth/*` directly; any `/auth/*` hit falls through to the Next.js
|
|
70
|
+
* handler.
|
|
71
|
+
*
|
|
72
|
+
* @param proxyConfig - Admin backend origin to proxy to; bound once at Worker startup
|
|
73
|
+
* @returns ProxyHandler that routes /api/* and /_proxy/health requests
|
|
74
|
+
*/
|
|
75
|
+
export declare function createCentralAdminProxyHandler(proxyConfig: CentralAdminProxyConfig): ProxyHandler;
|
|
37
76
|
//# 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;;;GAGG;AACH,MAAM,WAAW,
|
|
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;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,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;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,qBAAqB,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,SAAS,GAAG,OAAO,CAAC;CAClC,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,aAAa,CAAC,aAAa,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC9D;AA8ID;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,kBAAkB,GAAG,YAAY,CAiDvF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,8BAA8B,CAC5C,WAAW,EAAE,uBAAuB,GACnC,YAAY,CAgCd"}
|
|
@@ -21,16 +21,48 @@ async function probeHealth(baseUrl) {
|
|
|
21
21
|
return { status: "error", probeUrl };
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
const ADMIN_SESSION_COOKIE_NAME = "admin_session";
|
|
25
|
+
const ADMIN_SESSION_HANDOFF_HEADER = "X-Admin-Session";
|
|
26
|
+
function findAdminSessionCookieValue(cookieHeader) {
|
|
27
|
+
const prefix = ADMIN_SESSION_COOKIE_NAME + "=";
|
|
28
|
+
for (const cookieSegment of cookieHeader.split(";")) {
|
|
29
|
+
const trimmed = cookieSegment.trim();
|
|
30
|
+
if (trimmed.startsWith(prefix)) {
|
|
31
|
+
return { kind: "found", sessionValue: trimmed.slice(prefix.length) };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return { kind: "absent" };
|
|
35
|
+
}
|
|
36
|
+
function readCookieHeader(headers) {
|
|
37
|
+
const value = headers.get("cookie");
|
|
38
|
+
if (value === null) {
|
|
39
|
+
return { kind: "absent" };
|
|
40
|
+
}
|
|
41
|
+
return { kind: "present", value };
|
|
42
|
+
}
|
|
43
|
+
function buildVentureForwardedHeaders(originalHeaders) {
|
|
44
|
+
const forwarded = new Headers(originalHeaders);
|
|
45
|
+
forwarded.delete(ADMIN_SESSION_HANDOFF_HEADER);
|
|
46
|
+
const cookieLookup = readCookieHeader(forwarded);
|
|
47
|
+
forwarded.delete("cookie");
|
|
48
|
+
if (cookieLookup.kind === "present") {
|
|
49
|
+
const sessionLookup = findAdminSessionCookieValue(cookieLookup.value);
|
|
50
|
+
if (sessionLookup.kind === "found") {
|
|
51
|
+
forwarded.set(ADMIN_SESSION_HANDOFF_HEADER, sessionLookup.sessionValue);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return forwarded;
|
|
55
|
+
}
|
|
56
|
+
function stripInboundHandoffHeader(originalHeaders) {
|
|
57
|
+
const stripped = new Headers(originalHeaders);
|
|
58
|
+
stripped.delete(ADMIN_SESSION_HANDOFF_HEADER);
|
|
27
59
|
return stripped;
|
|
28
60
|
}
|
|
29
61
|
async function forwardToBackend(forwardInput) {
|
|
30
62
|
const targetUrl = new URL(forwardInput.targetPath + forwardInput.originalUrl.search, forwardInput.targetBase);
|
|
31
63
|
const forwardedHeaders = forwardInput.backendName === "venture"
|
|
32
|
-
?
|
|
33
|
-
: forwardInput.originalRequest.headers;
|
|
64
|
+
? buildVentureForwardedHeaders(forwardInput.originalRequest.headers)
|
|
65
|
+
: stripInboundHandoffHeader(forwardInput.originalRequest.headers);
|
|
34
66
|
try {
|
|
35
67
|
return await fetch(new Request(targetUrl, {
|
|
36
68
|
method: forwardInput.originalRequest.method,
|
|
@@ -57,10 +89,29 @@ async function forwardToBackend(forwardInput) {
|
|
|
57
89
|
}
|
|
58
90
|
}
|
|
59
91
|
/**
|
|
92
|
+
* Venture frontend proxy handler. Routes `/api/*` to the venture's own
|
|
93
|
+
* backend and `/auth/*` to the admin backend (rewriting `/auth/*` to
|
|
94
|
+
* `/api/auth/*`). This is the correct handler for every venture frontend.
|
|
95
|
+
*
|
|
96
|
+
* # Cookie-to-header handoff (venture `/api/*` branch)
|
|
97
|
+
*
|
|
98
|
+
* On every inbound request the handler unconditionally strips any
|
|
99
|
+
* `X-Admin-Session` header a client may have set — the header is an
|
|
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.
|
|
106
|
+
*
|
|
107
|
+
* If no cookie is present, no header is injected, and venture-api returns
|
|
108
|
+
* 401. There is deliberately no fallback path — see the integration guide
|
|
109
|
+
* section 13 for the full trust model.
|
|
110
|
+
*
|
|
60
111
|
* @param proxyConfig - Backend origins to proxy to; bound once at Worker startup
|
|
61
112
|
* @returns ProxyHandler that routes /api/*, /auth/*, and /_proxy/health requests
|
|
62
113
|
*/
|
|
63
|
-
export function
|
|
114
|
+
export function createVentureProxyHandler(proxyConfig) {
|
|
64
115
|
const ventureBase = stripTrailingSlash(proxyConfig.ventureApiBase);
|
|
65
116
|
const adminBase = stripTrailingSlash(proxyConfig.adminApiBase);
|
|
66
117
|
return {
|
|
@@ -105,4 +156,44 @@ export function createProxyHandler(proxyConfig) {
|
|
|
105
156
|
},
|
|
106
157
|
};
|
|
107
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Central admin frontend proxy handler. Routes `/api/*` to the admin backend
|
|
161
|
+
* with cookies preserved — the central admin frontend IS the admin frontend,
|
|
162
|
+
* so its `admin_session` cookie must reach `jakuta-admin-api` unmodified.
|
|
163
|
+
* Does NOT handle `/auth/*` because the central admin frontend calls
|
|
164
|
+
* `/api/auth/*` directly; any `/auth/*` hit falls through to the Next.js
|
|
165
|
+
* handler.
|
|
166
|
+
*
|
|
167
|
+
* @param proxyConfig - Admin backend origin to proxy to; bound once at Worker startup
|
|
168
|
+
* @returns ProxyHandler that routes /api/* and /_proxy/health requests
|
|
169
|
+
*/
|
|
170
|
+
export function createCentralAdminProxyHandler(proxyConfig) {
|
|
171
|
+
const adminBase = stripTrailingSlash(proxyConfig.adminApiBase);
|
|
172
|
+
return {
|
|
173
|
+
async handleRequest(workerRequest) {
|
|
174
|
+
const requestUrl = new URL(workerRequest.url);
|
|
175
|
+
const pathname = requestUrl.pathname;
|
|
176
|
+
if (pathname === "/_proxy/health") {
|
|
177
|
+
const admin = await probeHealth(adminBase);
|
|
178
|
+
const healthStatus = { admin };
|
|
179
|
+
const proxiedResponse = new Response(JSON.stringify(healthStatus), {
|
|
180
|
+
status: admin.status === "ok" ? 200 : 503,
|
|
181
|
+
headers: { "content-type": "application/json" },
|
|
182
|
+
});
|
|
183
|
+
return { proxied: true, proxiedResponse };
|
|
184
|
+
}
|
|
185
|
+
if (pathname === "/api" || pathname.startsWith("/api/")) {
|
|
186
|
+
const proxiedResponse = await forwardToBackend({
|
|
187
|
+
originalRequest: workerRequest,
|
|
188
|
+
originalUrl: requestUrl,
|
|
189
|
+
targetBase: adminBase,
|
|
190
|
+
targetPath: pathname,
|
|
191
|
+
backendName: "admin",
|
|
192
|
+
});
|
|
193
|
+
return { proxied: true, proxiedResponse };
|
|
194
|
+
}
|
|
195
|
+
return { proxied: false };
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
}
|
|
108
199
|
//# sourceMappingURL=same-origin-proxy.js.map
|
|
@@ -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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"}
|
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": "4.0.0",
|
|
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 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"same-origin-proxy.test.d.ts","sourceRoot":"","sources":["../src/same-origin-proxy.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
-
import { createProxyHandler } from "./same-origin-proxy";
|
|
3
|
-
const VENTURE_BASE = "https://venture.fly.dev";
|
|
4
|
-
const ADMIN_BASE = "https://admin.fly.dev";
|
|
5
|
-
function makeHandler() {
|
|
6
|
-
return createProxyHandler({
|
|
7
|
-
ventureApiBase: VENTURE_BASE,
|
|
8
|
-
adminApiBase: ADMIN_BASE,
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
function makeHandlerWithTrailingSlash() {
|
|
12
|
-
return createProxyHandler({
|
|
13
|
-
ventureApiBase: "https://venture.fly.dev/",
|
|
14
|
-
adminApiBase: ADMIN_BASE,
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
function stubFetchOk() {
|
|
18
|
-
const fetchSpy = vi.fn().mockResolvedValue(new Response("ok"));
|
|
19
|
-
vi.stubGlobal("fetch", fetchSpy);
|
|
20
|
-
return fetchSpy;
|
|
21
|
-
}
|
|
22
|
-
function stubFetchError() {
|
|
23
|
-
const fetchSpy = vi.fn().mockRejectedValue(new TypeError("fetch failed"));
|
|
24
|
-
vi.stubGlobal("fetch", fetchSpy);
|
|
25
|
-
return fetchSpy;
|
|
26
|
-
}
|
|
27
|
-
function stubFetchHealthOk() {
|
|
28
|
-
const fetchSpy = vi.fn().mockResolvedValue(new Response(JSON.stringify({ status: "ok" }), { status: 200 }));
|
|
29
|
-
vi.stubGlobal("fetch", fetchSpy);
|
|
30
|
-
return fetchSpy;
|
|
31
|
-
}
|
|
32
|
-
function extractForwardedUrl(fetchSpy) {
|
|
33
|
-
const firstCallFirstArg = fetchSpy.mock.calls[0][0];
|
|
34
|
-
return firstCallFirstArg.url;
|
|
35
|
-
}
|
|
36
|
-
beforeEach(() => {
|
|
37
|
-
vi.restoreAllMocks();
|
|
38
|
-
});
|
|
39
|
-
describe("venture backend routing (/api/*)", () => {
|
|
40
|
-
it("forwards /api/catalog to ventureApiBase/api/catalog", async () => {
|
|
41
|
-
const fetchSpy = stubFetchOk();
|
|
42
|
-
const handler = makeHandler();
|
|
43
|
-
const result = await handler.handleRequest(new Request("https://example.com/api/catalog"));
|
|
44
|
-
expect(result.proxied).toBe(true);
|
|
45
|
-
expect(fetchSpy).toHaveBeenCalledOnce();
|
|
46
|
-
expect(extractForwardedUrl(fetchSpy)).toBe("https://venture.fly.dev/api/catalog");
|
|
47
|
-
});
|
|
48
|
-
it("forwards /api/admin/indices without double /api", async () => {
|
|
49
|
-
const fetchSpy = stubFetchOk();
|
|
50
|
-
const handler = makeHandler();
|
|
51
|
-
await handler.handleRequest(new Request("https://example.com/api/admin/indices"));
|
|
52
|
-
expect(extractForwardedUrl(fetchSpy)).toBe("https://venture.fly.dev/api/admin/indices");
|
|
53
|
-
});
|
|
54
|
-
it("preserves query string on /api/* routes", async () => {
|
|
55
|
-
const fetchSpy = stubFetchOk();
|
|
56
|
-
const handler = makeHandler();
|
|
57
|
-
await handler.handleRequest(new Request("https://example.com/api/catalog?page=2"));
|
|
58
|
-
expect(extractForwardedUrl(fetchSpy)).toBe("https://venture.fly.dev/api/catalog?page=2");
|
|
59
|
-
});
|
|
60
|
-
it("returns 502 with backend_unreachable when venture fetch throws", async () => {
|
|
61
|
-
stubFetchError();
|
|
62
|
-
const handler = makeHandler();
|
|
63
|
-
const result = await handler.handleRequest(new Request("https://example.com/api/catalog"));
|
|
64
|
-
expect(result.proxied).toBe(true);
|
|
65
|
-
if (!result.proxied)
|
|
66
|
-
return;
|
|
67
|
-
expect(result.proxiedResponse.status).toBe(502);
|
|
68
|
-
const body = await result.proxiedResponse.json();
|
|
69
|
-
expect(body.error).toBe("backend_unreachable");
|
|
70
|
-
expect(body.backend).toBe("venture");
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
describe("admin backend routing (/auth/*)", () => {
|
|
74
|
-
it("rewrites /auth/session to adminApiBase/api/auth/session", async () => {
|
|
75
|
-
const fetchSpy = stubFetchOk();
|
|
76
|
-
const handler = makeHandler();
|
|
77
|
-
await handler.handleRequest(new Request("https://example.com/auth/session"));
|
|
78
|
-
expect(extractForwardedUrl(fetchSpy)).toBe("https://admin.fly.dev/api/auth/session");
|
|
79
|
-
});
|
|
80
|
-
it("rewrites /auth/login to adminApiBase/api/auth/login", async () => {
|
|
81
|
-
const fetchSpy = stubFetchOk();
|
|
82
|
-
const handler = makeHandler();
|
|
83
|
-
await handler.handleRequest(new Request("https://example.com/auth/login"));
|
|
84
|
-
expect(extractForwardedUrl(fetchSpy)).toBe("https://admin.fly.dev/api/auth/login");
|
|
85
|
-
});
|
|
86
|
-
it("rewrites /auth/logout to adminApiBase/api/auth/logout", async () => {
|
|
87
|
-
const fetchSpy = stubFetchOk();
|
|
88
|
-
const handler = makeHandler();
|
|
89
|
-
await handler.handleRequest(new Request("https://example.com/auth/logout"));
|
|
90
|
-
expect(extractForwardedUrl(fetchSpy)).toBe("https://admin.fly.dev/api/auth/logout");
|
|
91
|
-
});
|
|
92
|
-
it("preserves query string on /auth/* routes", async () => {
|
|
93
|
-
const fetchSpy = stubFetchOk();
|
|
94
|
-
const handler = makeHandler();
|
|
95
|
-
await handler.handleRequest(new Request("https://example.com/auth/session?foo=bar"));
|
|
96
|
-
expect(extractForwardedUrl(fetchSpy)).toBe("https://admin.fly.dev/api/auth/session?foo=bar");
|
|
97
|
-
});
|
|
98
|
-
it("returns 502 with backend=admin when admin fetch throws", async () => {
|
|
99
|
-
stubFetchError();
|
|
100
|
-
const handler = makeHandler();
|
|
101
|
-
const result = await handler.handleRequest(new Request("https://example.com/auth/session"));
|
|
102
|
-
expect(result.proxied).toBe(true);
|
|
103
|
-
if (!result.proxied)
|
|
104
|
-
return;
|
|
105
|
-
expect(result.proxiedResponse.status).toBe(502);
|
|
106
|
-
const body = await result.proxiedResponse.json();
|
|
107
|
-
expect(body.error).toBe("backend_unreachable");
|
|
108
|
-
expect(body.backend).toBe("admin");
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
describe("trailing slash on config base URLs", () => {
|
|
112
|
-
it("strips trailing slash from ventureApiBase", async () => {
|
|
113
|
-
const fetchSpy = stubFetchOk();
|
|
114
|
-
const handler = makeHandlerWithTrailingSlash();
|
|
115
|
-
await handler.handleRequest(new Request("https://example.com/api/catalog"));
|
|
116
|
-
expect(extractForwardedUrl(fetchSpy)).toBe("https://venture.fly.dev/api/catalog");
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
describe("non-proxied routes", () => {
|
|
120
|
-
it("returns proxied: false for /", async () => {
|
|
121
|
-
const handler = makeHandler();
|
|
122
|
-
const result = await handler.handleRequest(new Request("https://example.com/"));
|
|
123
|
-
expect(result.proxied).toBe(false);
|
|
124
|
-
});
|
|
125
|
-
it("returns proxied: false for /dashboard", async () => {
|
|
126
|
-
const handler = makeHandler();
|
|
127
|
-
const result = await handler.handleRequest(new Request("https://example.com/dashboard"));
|
|
128
|
-
expect(result.proxied).toBe(false);
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
describe("cookie stripping on venture requests", () => {
|
|
132
|
-
function extractForwardedRequest(fetchSpy) {
|
|
133
|
-
return fetchSpy.mock.calls[0][0];
|
|
134
|
-
}
|
|
135
|
-
it("strips the cookie header on venture /api/* requests", async () => {
|
|
136
|
-
const fetchSpy = stubFetchOk();
|
|
137
|
-
const handler = makeHandler();
|
|
138
|
-
await handler.handleRequest(new Request("https://example.com/api/catalog", {
|
|
139
|
-
headers: { cookie: "admin_session=abc123" },
|
|
140
|
-
}));
|
|
141
|
-
const forwardedRequest = extractForwardedRequest(fetchSpy);
|
|
142
|
-
expect(forwardedRequest.headers.has("cookie")).toBe(false);
|
|
143
|
-
});
|
|
144
|
-
it("preserves the cookie header on admin /auth/* requests", async () => {
|
|
145
|
-
const fetchSpy = stubFetchOk();
|
|
146
|
-
const handler = makeHandler();
|
|
147
|
-
await handler.handleRequest(new Request("https://example.com/auth/session", {
|
|
148
|
-
headers: { cookie: "admin_session=abc123" },
|
|
149
|
-
}));
|
|
150
|
-
const forwardedRequest = extractForwardedRequest(fetchSpy);
|
|
151
|
-
expect(forwardedRequest.headers.get("cookie")).toBe("admin_session=abc123");
|
|
152
|
-
});
|
|
153
|
-
it("strips cookie but preserves other headers on venture requests", async () => {
|
|
154
|
-
const fetchSpy = stubFetchOk();
|
|
155
|
-
const handler = makeHandler();
|
|
156
|
-
await handler.handleRequest(new Request("https://example.com/api/catalog", {
|
|
157
|
-
headers: {
|
|
158
|
-
cookie: "admin_session=abc123",
|
|
159
|
-
"x-request-id": "test-123",
|
|
160
|
-
"content-type": "application/json",
|
|
161
|
-
},
|
|
162
|
-
}));
|
|
163
|
-
const forwardedRequest = extractForwardedRequest(fetchSpy);
|
|
164
|
-
expect(forwardedRequest.headers.has("cookie")).toBe(false);
|
|
165
|
-
expect(forwardedRequest.headers.get("x-request-id")).toBe("test-123");
|
|
166
|
-
expect(forwardedRequest.headers.get("content-type")).toBe("application/json");
|
|
167
|
-
});
|
|
168
|
-
it("forwards venture requests without errors when no cookie header is present", async () => {
|
|
169
|
-
const fetchSpy = stubFetchOk();
|
|
170
|
-
const handler = makeHandler();
|
|
171
|
-
const result = await handler.handleRequest(new Request("https://example.com/api/catalog"));
|
|
172
|
-
expect(result.proxied).toBe(true);
|
|
173
|
-
expect(fetchSpy).toHaveBeenCalledOnce();
|
|
174
|
-
expect(extractForwardedUrl(fetchSpy)).toBe("https://venture.fly.dev/api/catalog");
|
|
175
|
-
const forwardedRequest = extractForwardedRequest(fetchSpy);
|
|
176
|
-
expect(forwardedRequest.headers.has("cookie")).toBe(false);
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
describe("/_proxy/health", () => {
|
|
180
|
-
it("returns proxied: true with health JSON", async () => {
|
|
181
|
-
stubFetchHealthOk();
|
|
182
|
-
const handler = makeHandler();
|
|
183
|
-
const result = await handler.handleRequest(new Request("https://example.com/_proxy/health"));
|
|
184
|
-
expect(result.proxied).toBe(true);
|
|
185
|
-
if (!result.proxied)
|
|
186
|
-
return;
|
|
187
|
-
const body = await result.proxiedResponse.json();
|
|
188
|
-
expect(body).toHaveProperty("venture");
|
|
189
|
-
expect(body).toHaveProperty("admin");
|
|
190
|
-
expect(body.venture.status).toBe("ok");
|
|
191
|
-
expect(body.admin.status).toBe("ok");
|
|
192
|
-
});
|
|
193
|
-
});
|
|
194
|
-
//# sourceMappingURL=same-origin-proxy.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"same-origin-proxy.test.js","sourceRoot":"","sources":["../src/same-origin-proxy.test.ts"],"names":[],"mappings":"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"}
|