Skip to content

Commit a9a8808

Browse files
committed
fix(client): avoid double slash when joining dynamicPublicPath (#2348)
* fix(client): avoid double slash when joining dynamicPublicPath When output.publicPath ends with a slash (the common case) and the SSE path starts with one, the naive concatenation produced URLs like `https://host//__webpack_hmr`, which never match the server-side pathname check. Ref webpack/webpack-hot-middleware#366 * fix(client): append path to the public path like a filename in dynamicPublicPath The default `path` starts with "/", so the naive concatenation with a public path ending in "/" produced URLs like `https://host//__webpack_hmr`, which never match the server-side pathname check. Strip the leading slash from `path` and concatenate without any other normalization: the public path itself is left untouched (intentional double slashes, e.g. nginx rewrites, are preserved) and is expected to end with "/". Ref webpack/webpack-hot-middleware#366
1 parent e5e4177 commit a9a8808

3 files changed

Lines changed: 42 additions & 2 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ entry: [
384384
| `logging` | `string` | `"info"` | Logger level — one of `"none"`, `"error"`, `"warn"`, `"info"`, `"log"`, `"verbose"`. Uses webpack's runtime logger. |
385385
| `name` | `string` | `""` | Restrict updates to a specific compilation name (useful with multi-compiler). |
386386
| `autoConnect` | `boolean` | `true` | Connect on load; set to `false` and call `setOptionsAndConnect()` manually. |
387-
| `dynamicPublicPath` | `boolean` | `false` | Prefix `path` with `__webpack_public_path__` at runtime. |
387+
| `dynamicPublicPath` | `boolean` | `false` | Prefix `path` with `__webpack_public_path__` at runtime. The leading slash of `path` is stripped and no other normalization is applied, so the public path should end with `/`. |
388388

389389
### Programmatic API
390390

client-src/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,9 @@ function setOverrides(overrides) {
113113
}
114114

115115
if (overrides.dynamicPublicPath) {
116-
options.path = __webpack_public_path__ + options.path;
116+
// `path` is appended like a filename (no leading slash); the public path
117+
// itself is not normalized.
118+
options.path = __webpack_public_path__ + options.path.replace(/^\//, "");
117119
}
118120

119121
setLogLevel(options.logging);

test/client.test.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,44 @@ describe("client", () => {
702702
});
703703
});
704704

705+
describe("with dynamicPublicPath", () => {
706+
let EventSourceStub;
707+
708+
beforeEach(() => {
709+
EventSourceStub = makeEventSourceStub();
710+
globalThis.EventSource = EventSourceStub;
711+
jest.spyOn(console, "info").mockImplementation(() => {});
712+
jest.spyOn(console, "log").mockImplementation(() => {});
713+
});
714+
715+
afterEach(() => {
716+
delete globalThis.__webpack_public_path__;
717+
jest.restoreAllMocks();
718+
});
719+
720+
it("appends the SSE path to the public path like webpack appends filenames", () => {
721+
globalThis.__webpack_public_path__ = "/assets/";
722+
loadClient("?dynamicPublicPath=true");
723+
expect(EventSourceStub.lastInstance().url).toBe("/assets/__webpack_hmr");
724+
});
725+
726+
it("preserves intentional double slashes inside the public path", () => {
727+
globalThis.__webpack_public_path__ = "https://host//rewritten/";
728+
loadClient("?dynamicPublicPath=true");
729+
expect(EventSourceStub.lastInstance().url).toBe(
730+
"https://host//rewritten/__webpack_hmr",
731+
);
732+
});
733+
734+
it("does not produce a double slash when the public path has a trailing slash", () => {
735+
globalThis.__webpack_public_path__ = "https://localhost:3000/assets/";
736+
loadClient("?dynamicPublicPath=true");
737+
expect(EventSourceStub.lastInstance().url).toBe(
738+
"https://localhost:3000/assets/__webpack_hmr",
739+
);
740+
});
741+
});
742+
705743
describe("connection lifecycle", () => {
706744
let EventSourceStub;
707745
let client;

0 commit comments

Comments
 (0)