Skip to content

Commit

Permalink
Fix SW and Durable Object request URLs made over the service registry (
Browse files Browse the repository at this point in the history
…#1665)

* Fix SW and Durable Object request URLs made over the service registry

* Add service binding tests
  • Loading branch information
GregBrimble authored Aug 11, 2022
1 parent f650a0b commit c40fca4
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/sharp-ligers-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": patch
---

fix: Fix SW and Durable Object request URLs made over the service registry
25 changes: 19 additions & 6 deletions fixtures/service-bindings-app/package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
{
"name": "service-bindings-app",
"version": "0.0.0",
"private": true,
"description": "A test for service bindings",
"keywords": [],
"license": "ISC",
"author": "",
"main": "index.js",
"scripts": {
"dev": "npx concurrently 'wrangler dev a/index.ts --local' 'sleep 1 && wrangler dev b/index.ts --local'"
"dev": "npx concurrently -s first -k \"wrangler dev a/index.ts --local --port 8300\" \"wrangler dev b/index.ts --local --port 8301\"",
"test": "npx jest --forceExit",
"test:ci": "npx jest --forceExit"
},
"jest": {
"restoreMocks": true,
"testRegex": ".*.(test|spec)\\.[jt]sx?$",
"testTimeout": 30000,
"transform": {
"^.+\\.c?(t|j)sx?$": [
"esbuild-jest",
{
"sourcemap": true
}
]
},
"transformIgnorePatterns": [
"node_modules/(?!find-up|locate-path|p-locate|p-limit|yocto-queue|path-exists|execa|strip-final-newline|npm-run-path|path-key|onetime|mimic-fn|human-signals|is-stream)"
]
}
}
62 changes: 62 additions & 0 deletions fixtures/service-bindings-app/tests/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { spawn } from "child_process";
import * as path from "path";
import { fetch } from "undici";
import type { ChildProcess } from "child_process";
import type { Response } from "undici";

const waitUntilReady = async (url: string): Promise<Response> => {
let response: Response | undefined = undefined;

while (response === undefined) {
await new Promise((resolvePromise) => setTimeout(resolvePromise, 500));

try {
response = await fetch(url);
} catch {}
}

return response as Response;
};

const isWindows = process.platform === "win32";

describe("Pages Functions", () => {
let wranglerProcess: ChildProcess;

beforeEach(() => {
wranglerProcess = spawn("npm", ["run", "dev"], {
shell: isWindows,
cwd: path.resolve(__dirname, "../"),
env: { BROWSER: "none", ...process.env },
});
wranglerProcess.stdout?.on("data", (chunk) => {
console.log(chunk.toString());
});
wranglerProcess.stderr?.on("data", (chunk) => {
console.log(chunk.toString());
});
});

afterEach(async () => {
await new Promise((resolve, reject) => {
wranglerProcess.once("exit", (code) => {
if (!code) {
resolve(code);
} else {
reject(code);
}
});
wranglerProcess.kill("SIGTERM");
});
});

it("connects up Durable Objects and keeps state across wrangler instances", async () => {
const responseA = await waitUntilReady("http://localhost:8300/");
const textA = await responseA.text();
expect(textA).toEqual("hello world");

const responseB = await waitUntilReady("http://localhost:8301/");
const textB = (await responseB.text()) as { count: number; id: string };
expect(textB).toEqual("hello world");
});
});
5 changes: 1 addition & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions packages/wrangler/src/miniflare-cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,13 @@ async function main() {
namespace.get = (id) => {
const stub = new DurableObjectStub(factory, id);
stub.fetch = (...reqArgs) => {
const url = `http://${host}${port ? `:${port}` : ""}`;
const requestFromArgs = new MiniflareRequest(...reqArgs);
const url = new URL(requestFromArgs.url);
url.host = host;
if (port !== undefined) url.port = port.toString();
const request = new MiniflareRequest(
url,
new MiniflareRequest(...reqArgs)
url.toString(),
requestFromArgs
);
request.headers.set("x-miniflare-durable-object-name", name);
request.headers.set("x-miniflare-durable-object-id", id.toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default {
const url = new URL(reqFromArgs.url);
url.protocol = details.protocol;
url.host = details.host;
if (details.port) url.port = details.port;
if (details.port !== undefined) url.port = details.port;

const request = new Request(url.toString(), reqFromArgs);
return fetch(request);
Expand Down
17 changes: 10 additions & 7 deletions packages/wrangler/templates/service-bindings-sw-facade.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,23 @@ for (const [name, details] of Object.entries(Workers)) {
if (details) {
globalThis[name] = {
async fetch(...reqArgs) {
const reqFromArgs = new Request(...reqArgs);
if (details.headers) {
const req = new Request(...reqArgs);
for (const [key, value] of Object.entries(details.headers)) {
// In remote mode, you need to add a couple of headers
// to make sure it's talking to the 'dev' preview session
// (much like wrangler dev already does via proxy.ts)
req.headers.set(key, value);
reqFromArgs.headers.set(key, value);
}
return env[name].fetch(req);
return env[name].fetch(reqFromArgs);
}
const url = `${details.protocol}://${details.host}${
details.port ? `:${details.port}` : ""
}`;
const request = new Request(url, ...reqArgs);

const url = new URL(reqFromArgs.url);
url.protocol = details.protocol;
url.host = details.host;
if (details.port !== undefined) url.port = details.port;

const request = new Request(url.toString(), reqFromArgs);
return fetch(request);
},
};
Expand Down

0 comments on commit c40fca4

Please sign in to comment.