fix(gateway): proxy browser server functions to workspace apps
This commit is contained in:
@@ -4,6 +4,7 @@ import {
|
||||
defaultGatewayHostname,
|
||||
forwardAuthFailure,
|
||||
forwardAuthHeaders,
|
||||
gatewayBrowserRpcHeaders,
|
||||
gatewayProxyHeaders,
|
||||
gatewayWebSocketBackendHeaders,
|
||||
stripUntrustedInternalHeaders,
|
||||
@@ -176,13 +177,40 @@ test("nested SSO proxy keeps the protected app's original request headers", () =
|
||||
expect(proxied.get("x-original-uri")).toBe("/settings");
|
||||
});
|
||||
|
||||
test("the reserved RPC prefix is refused at the gateway before any proxying", () => {
|
||||
expect(isRpcGatewayPath(RPC_PATH_PREFIX)).toBe(true);
|
||||
test("the gateway proxies browser server functions but refuses private RPC routes", () => {
|
||||
expect(isRpcGatewayPath(RPC_PATH_PREFIX)).toBe(false);
|
||||
expect(isRpcGatewayPath(`${RPC_PATH_PREFIX}/billing/createInvoice`)).toBe(true);
|
||||
expect(isRpcGatewayPath("/api/billing")).toBe(false);
|
||||
expect(isRpcGatewayPath("/__wrnexus/rpcfoo")).toBe(false);
|
||||
});
|
||||
|
||||
test("browser RPC proxy preserves CSRF credentials and trusts only the internal hop", () => {
|
||||
const request = new Request(`http://web.localhost:3000${RPC_PATH_PREFIX}`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
host: "web.localhost:3000",
|
||||
origin: "http://web.localhost:3000",
|
||||
cookie: "wrn-csrf=token",
|
||||
"x-csrf-token": "token",
|
||||
[RPC_INTERNAL_HEADER]: "forged",
|
||||
},
|
||||
});
|
||||
const headers = gatewayBrowserRpcHeaders(
|
||||
request,
|
||||
new URL(request.url),
|
||||
"127.0.0.1",
|
||||
true,
|
||||
"http://127.0.0.1:3001",
|
||||
);
|
||||
|
||||
expect(headers.get("origin")).toBe("http://127.0.0.1:3001");
|
||||
expect(headers.get("cookie")).toBe("wrn-csrf=token");
|
||||
expect(headers.get("x-csrf-token")).toBe("token");
|
||||
expect(headers.get("x-forwarded-host")).toBe("web.localhost:3000");
|
||||
expect(headers.has(RPC_INTERNAL_HEADER)).toBe(false);
|
||||
expect(headers.has("host")).toBe(false);
|
||||
});
|
||||
|
||||
test("an inbound internal-marker header from outside is stripped regardless of casing", () => {
|
||||
for (const name of [
|
||||
RPC_INTERNAL_HEADER,
|
||||
|
||||
Reference in New Issue
Block a user