






















@@ -218,6 +218,49 @@ async function sendRawHttpRequest(params: {
218218});
219219}
220220221+type CanvasGatewayListener = Awaited<ReturnType<typeof listen>>;
222+223+function canvasUrl(listener: CanvasGatewayListener, path = CANVAS_HOST_PATH): string {
224+return `http://127.0.0.1:${listener.port}${path}`;
225+}
226+227+async function fetchCanvasHost(
228+listener: CanvasGatewayListener,
229+init?: RequestInit,
230+): Promise<Response> {
231+return await fetchCanvas(canvasUrl(listener), init);
232+}
233+234+async function expectMalformedRequestTargetsRejected(params: {
235+listener: CanvasGatewayListener;
236+headers?: readonly string[];
237+}): Promise<void> {
238+for (const requestTarget of ["//", "///", "//${jndi:ldap://example}.action"]) {
239+const response = await sendRawHttpRequest({
240+host: "127.0.0.1",
241+port: params.listener.port,
242+ requestTarget,
243+ ...(params.headers ? { headers: params.headers } : {}),
244+});
245+expect(response).toMatch(/^HTTP\/1\.1 401 /);
246+}
247+248+const res = await fetchCanvasHost(params.listener);
249+expect(res.status).toBe(401);
250+}
251+252+async function expectRepeatedCanvasAuthAttemptsRateLimited(
253+listener: CanvasGatewayListener,
254+headers: Record<string, string>,
255+): Promise<Response> {
256+const first = await fetchCanvasHost(listener, { headers });
257+expect(first.status).toBe(401);
258+259+const second = await fetchCanvasHost(listener, { headers });
260+expect(second.status).toBe(429);
261+return second;
262+}
263+221264function makeWsClient(params: {
222265connId: string;
223266clientIp: string;
@@ -463,17 +506,7 @@ describe("gateway plugin node capability auth", () => {
463506resolvedAuth: tokenResolvedAuth,
464507handleHttpRequest: allowCanvasHostHttp,
465508run: async ({ listener }) => {
466-for (const requestTarget of ["//", "///", "//${jndi:ldap://example}.action"]) {
467-const response = await sendRawHttpRequest({
468-host: "127.0.0.1",
469-port: listener.port,
470- requestTarget,
471-});
472-expect(response).toMatch(/^HTTP\/1\.1 401 /);
473-}
474-475-const res = await fetchCanvas(`http://127.0.0.1:${listener.port}${CANVAS_HOST_PATH}/`);
476-expect(res.status).toBe(401);
509+await expectMalformedRequestTargetsRejected({ listener });
477510},
478511});
479512}, 60_000);
@@ -483,24 +516,16 @@ describe("gateway plugin node capability auth", () => {
483516resolvedAuth: tokenResolvedAuth,
484517handleHttpRequest: allowCanvasHostHttp,
485518run: async ({ listener }) => {
486-for (const requestTarget of ["//", "///", "//${jndi:ldap://example}.action"]) {
487-const response = await sendRawHttpRequest({
488-host: "127.0.0.1",
489-port: listener.port,
490- requestTarget,
491-headers: [
492-"Host: localhost",
493-"Upgrade: websocket",
494-"Connection: Upgrade",
495-"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==",
496-"Sec-WebSocket-Version: 13",
497-],
498-});
499-expect(response).toMatch(/^HTTP\/1\.1 401 /);
500-}
501-502-const res = await fetchCanvas(`http://127.0.0.1:${listener.port}${CANVAS_HOST_PATH}/`);
503-expect(res.status).toBe(401);
519+await expectMalformedRequestTargetsRejected({
520+ listener,
521+headers: [
522+"Host: localhost",
523+"Upgrade: websocket",
524+"Connection: Upgrade",
525+"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==",
526+"Sec-WebSocket-Version: 13",
527+],
528+});
504529},
505530});
506531}, 60_000);
@@ -638,18 +663,7 @@ describe("gateway plugin node capability auth", () => {
638663authorization: "Bearer wrong",
639664"x-forwarded-for": "203.0.113.99",
640665};
641-const first = await fetchCanvas(`http://127.0.0.1:${listener.port}${CANVAS_HOST_PATH}/`, {
642- headers,
643-});
644-expect(first.status).toBe(401);
645-646-const second = await fetchCanvas(
647-`http://127.0.0.1:${listener.port}${CANVAS_HOST_PATH}/`,
648-{
649- headers,
650-},
651-);
652-expect(second.status).toBe(429);
666+const second = await expectRepeatedCanvasAuthAttemptsRateLimited(listener, headers);
653667expect(second.headers.get("retry-after")).toMatch(/^\d+$/);
654668655669await expectWsRejected(`ws://127.0.0.1:${listener.port}${CANVAS_WS_PATH}`, headers, 429);
@@ -683,21 +697,7 @@ describe("gateway plugin node capability auth", () => {
683697host: "localhost",
684698"x-forwarded-for": "127.0.0.1, 203.0.113.24",
685699};
686-const first = await fetchCanvas(
687-`http://127.0.0.1:${listener.port}${CANVAS_HOST_PATH}/`,
688-{
689- headers,
690-},
691-);
692-expect(first.status).toBe(401);
693-694-const second = await fetchCanvas(
695-`http://127.0.0.1:${listener.port}${CANVAS_HOST_PATH}/`,
696-{
697- headers,
698-},
699-);
700-expect(second.status).toBe(429);
700+await expectRepeatedCanvasAuthAttemptsRateLimited(listener, headers);
701701},
702702});
703703},
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。