From 634662258772c18a39b76db1faaef330fb3ba559 Mon Sep 17 00:00:00 2001 From: Gabriel Massadas Date: Thu, 21 Nov 2024 15:01:52 +0000 Subject: [PATCH 1/4] Update local AI fetcher to forward method and pathname to upstream --- .changeset/stupid-moons-juggle.md | 5 +++++ packages/wrangler/src/ai/fetcher.ts | 10 ++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 .changeset/stupid-moons-juggle.md diff --git a/.changeset/stupid-moons-juggle.md b/.changeset/stupid-moons-juggle.md new file mode 100644 index 000000000000..529e9c6886d0 --- /dev/null +++ b/.changeset/stupid-moons-juggle.md @@ -0,0 +1,5 @@ +--- +"wrangler": minor +--- + +Update local AI fetcher to forward method and url to upstream diff --git a/packages/wrangler/src/ai/fetcher.ts b/packages/wrangler/src/ai/fetcher.ts index 6660bb048ade..2fe8685c5636 100644 --- a/packages/wrangler/src/ai/fetcher.ts +++ b/packages/wrangler/src/ai/fetcher.ts @@ -16,12 +16,14 @@ export default function (env) { export async function AIFetcher(request: Request): Promise { const accountId = await getAccountId(); - request.headers.delete("Host"); - request.headers.delete("Content-Length"); + const reqHeaders = new Headers(request.headers); + reqHeaders.delete("Host"); + reqHeaders.delete("Content-Length"); + reqHeaders.set("x-url", request.url); const res = await performApiFetch(`/accounts/${accountId}/ai/run/proxy`, { - method: "POST", - headers: Object.fromEntries(request.headers.entries()), + method: request.method, + headers: Object.fromEntries(reqHeaders.entries()), body: request.body, duplex: "half", }); From 7e38dd18d23a91aaa3e74d2278ef2ede58fdd26b Mon Sep 17 00:00:00 2001 From: Gabriel Massadas Date: Thu, 21 Nov 2024 19:22:56 +0000 Subject: [PATCH 2/4] Add unit test to cover changes --- .../wrangler/src/__tests__/ai.local.test.ts | 41 +++++++++++++++++++ packages/wrangler/src/ai/fetcher.ts | 2 +- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 packages/wrangler/src/__tests__/ai.local.test.ts diff --git a/packages/wrangler/src/__tests__/ai.local.test.ts b/packages/wrangler/src/__tests__/ai.local.test.ts new file mode 100644 index 000000000000..7b11bf8eb8bb --- /dev/null +++ b/packages/wrangler/src/__tests__/ai.local.test.ts @@ -0,0 +1,41 @@ +import { Request } from "miniflare"; +import { http, HttpResponse } from "msw"; +import { AIFetcher } from "../ai/fetcher"; +import { msw } from "./helpers/msw"; + +describe("ai", () => { + describe("fetcher", () => { + describe("local", () => { + it("should send x-forwarded-host header", async () => { + mockAIProxyRequest(); + + const url = "http://internal.ai/ai/test/path?version=123"; + const resp = await AIFetcher( + new Request(url, { + method: 'PATCH', + headers: { + "x-example": "test", + }, + }) + ); + + expect(await resp.json()).toEqual({ xForwardedFor: url, method: 'PATCH' }); + }); + }); + }); +}); + +function mockAIProxyRequest() { + msw.use( + http.get( + "*/accounts/:accountId/ai/run/proxy", + (c) => { + return HttpResponse.json({ + xForwardedFor: c.request.headers.get("X-Forwarded-Host"), + method: c.request.method + }); + }, + { once: true } + ) + ); +} diff --git a/packages/wrangler/src/ai/fetcher.ts b/packages/wrangler/src/ai/fetcher.ts index 2fe8685c5636..9ef41fecc993 100644 --- a/packages/wrangler/src/ai/fetcher.ts +++ b/packages/wrangler/src/ai/fetcher.ts @@ -19,7 +19,7 @@ export async function AIFetcher(request: Request): Promise { const reqHeaders = new Headers(request.headers); reqHeaders.delete("Host"); reqHeaders.delete("Content-Length"); - reqHeaders.set("x-url", request.url); + reqHeaders.set("X-Forwarded-Host", request.url); const res = await performApiFetch(`/accounts/${accountId}/ai/run/proxy`, { method: request.method, From 8d93ebcf037726fcc4cabf06caf89a252ae397d8 Mon Sep 17 00:00:00 2001 From: Gabriel Massadas Date: Thu, 21 Nov 2024 19:27:58 +0000 Subject: [PATCH 3/4] Lint files --- .../wrangler/src/__tests__/ai.local.test.ts | 68 +++++++++++++------ 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/packages/wrangler/src/__tests__/ai.local.test.ts b/packages/wrangler/src/__tests__/ai.local.test.ts index 7b11bf8eb8bb..1949e558391f 100644 --- a/packages/wrangler/src/__tests__/ai.local.test.ts +++ b/packages/wrangler/src/__tests__/ai.local.test.ts @@ -1,41 +1,69 @@ import { Request } from "miniflare"; -import { http, HttpResponse } from "msw"; +import { HttpResponse } from "msw"; import { AIFetcher } from "../ai/fetcher"; -import { msw } from "./helpers/msw"; +import * as internal from "../cfetch/internal"; +import * as user from "../user"; +import type { RequestInit } from "undici"; describe("ai", () => { describe("fetcher", () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + describe("local", () => { it("should send x-forwarded-host header", async () => { - mockAIProxyRequest(); + vi.spyOn(user, "getAccountId").mockImplementation(async () => "123"); + vi.spyOn(internal, "performApiFetch").mockImplementation( + async (resource: string, init: RequestInit = {}) => { + const headers = new Headers(init.headers); + return HttpResponse.json({ + xForwardedFor: headers.get("X-Forwarded-Host"), + method: init.method, + }); + } + ); + + const url = "http://internal.ai/ai/test/path?version=123"; + const resp = await AIFetcher( + new Request(url, { + method: "PATCH", + headers: { + "x-example": "test", + }, + }) + ); + + expect(await resp.json()).toEqual({ + xForwardedFor: url, + method: "PATCH", + }); + }); + + it("account id should be set", async () => { + vi.spyOn(user, "getAccountId").mockImplementation(async () => "123"); + vi.spyOn(internal, "performApiFetch").mockImplementation( + async (resource: string) => { + return HttpResponse.json({ + resource: resource, + }); + } + ); const url = "http://internal.ai/ai/test/path?version=123"; const resp = await AIFetcher( new Request(url, { - method: 'PATCH', + method: "PATCH", headers: { "x-example": "test", }, }) ); - expect(await resp.json()).toEqual({ xForwardedFor: url, method: 'PATCH' }); + expect(await resp.json()).toEqual({ + resource: "/accounts/123/ai/run/proxy", + }); }); }); }); }); - -function mockAIProxyRequest() { - msw.use( - http.get( - "*/accounts/:accountId/ai/run/proxy", - (c) => { - return HttpResponse.json({ - xForwardedFor: c.request.headers.get("X-Forwarded-Host"), - method: c.request.method - }); - }, - { once: true } - ) - ); -} From fb0b5a40fa43629a4a603ad93ad3e25311fb013f Mon Sep 17 00:00:00 2001 From: Gabriel Massadas Date: Fri, 22 Nov 2024 11:18:21 +0000 Subject: [PATCH 4/4] Rename x-forward-for to x-forward header name --- packages/wrangler/src/__tests__/ai.local.test.ts | 6 +++--- packages/wrangler/src/ai/fetcher.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/wrangler/src/__tests__/ai.local.test.ts b/packages/wrangler/src/__tests__/ai.local.test.ts index 1949e558391f..7451fbe507b7 100644 --- a/packages/wrangler/src/__tests__/ai.local.test.ts +++ b/packages/wrangler/src/__tests__/ai.local.test.ts @@ -12,13 +12,13 @@ describe("ai", () => { }); describe("local", () => { - it("should send x-forwarded-host header", async () => { + it("should send x-forwarded header", async () => { vi.spyOn(user, "getAccountId").mockImplementation(async () => "123"); vi.spyOn(internal, "performApiFetch").mockImplementation( async (resource: string, init: RequestInit = {}) => { const headers = new Headers(init.headers); return HttpResponse.json({ - xForwardedFor: headers.get("X-Forwarded-Host"), + xForwarded: headers.get("X-Forwarded"), method: init.method, }); } @@ -35,7 +35,7 @@ describe("ai", () => { ); expect(await resp.json()).toEqual({ - xForwardedFor: url, + xForwarded: url, method: "PATCH", }); }); diff --git a/packages/wrangler/src/ai/fetcher.ts b/packages/wrangler/src/ai/fetcher.ts index 9ef41fecc993..9d8d8e32168d 100644 --- a/packages/wrangler/src/ai/fetcher.ts +++ b/packages/wrangler/src/ai/fetcher.ts @@ -19,7 +19,7 @@ export async function AIFetcher(request: Request): Promise { const reqHeaders = new Headers(request.headers); reqHeaders.delete("Host"); reqHeaders.delete("Content-Length"); - reqHeaders.set("X-Forwarded-Host", request.url); + reqHeaders.set("X-Forwarded", request.url); const res = await performApiFetch(`/accounts/${accountId}/ai/run/proxy`, { method: request.method,