Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
d2e8e57
fix(server): use weak comparison for If-None-Match
Boyeep Jul 26, 2026
e527192
feat(server): support static asset byte ranges
Boyeep Jul 26, 2026
4db2e69
fix(server): validate If-Range HTTP dates
Boyeep Jul 26, 2026
932bfc8
chore: retrigger CI
Boyeep Jul 26, 2026
a61586f
chore: retrigger CI
Boyeep Jul 26, 2026
08a4f00
chore: retrigger flaky E2E
Boyeep Jul 26, 2026
9ce704a
fix(server): validate conditional static requests
james-elicx Jul 27, 2026
f11c2f9
fix(server): tighten entity-tag parsing
james-elicx Jul 27, 2026
1c0b44e
test(server): document entity-tag comma behavior
james-elicx Jul 27, 2026
1e2d403
fix(dev): weak-match public asset etags
james-elicx Jul 27, 2026
233099b
fix(dev): normalize public etag lookup paths
james-elicx Jul 27, 2026
7f52c55
fix(server): preserve byte range wire semantics
james-elicx Jul 27, 2026
0d30107
fix(server): preserve partial response validators
james-elicx Jul 27, 2026
4c95813
fix(dev): canonicalize conditional public assets
james-elicx Jul 27, 2026
ea7dbd5
fix(server): resolve obsolete HTTP date years
james-elicx Jul 27, 2026
510f8e0
fix(dev): honor Vite public file identity
james-elicx Jul 27, 2026
1b3c835
fix(dev): mirror Vite public filesystem semantics
james-elicx Jul 27, 2026
b395c75
fix(dev): refresh public filesystem capabilities
james-elicx Jul 27, 2026
b4dfe41
fix(dev): verify public path aliases
james-elicx Jul 27, 2026
9e13f24
refactor(server): share strict HTTP date parsing
james-elicx Jul 27, 2026
ecc9fad
fix(dev): index verified public request aliases
james-elicx Jul 27, 2026
0db6645
fix(dev): compose verified public path aliases
james-elicx Jul 27, 2026
99babf4
fix(dev): resolve Unicode public path classes
james-elicx Jul 27, 2026
bdb00b8
fix(dev): use Unicode simple case matching
james-elicx Jul 27, 2026
a8df551
fix(dev): match Unicode expansion tokens
james-elicx Jul 27, 2026
29d95eb
Merge remote-tracking branch 'origin/main' into codex/pr2710-ready
james-elicx Jul 27, 2026
35e80a8
Merge PR #2710 into static byte ranges
james-elicx Jul 27, 2026
ae2ad77
Merge latest main into static byte ranges
james-elicx Jul 27, 2026
d7c238e
Merge final PR #2710 head into static byte ranges
james-elicx Jul 27, 2026
a8a36f3
fix(dev): keep public ETag trie internal
james-elicx Jul 27, 2026
4175bc8
fix(dev): keep public path node private
james-elicx Jul 27, 2026
aee5021
Merge remote-tracking branch 'origin/main' into codex/pr2710-ready
james-elicx Jul 27, 2026
14ada51
Merge remote-tracking branch 'origin/main' into codex/pr2710-ready
james-elicx Jul 27, 2026
7cdf5d3
Merge updated PR #2710 head into static byte ranges
james-elicx Jul 27, 2026
1eb997d
fix(dev): resolve public-root symlink redirects
james-elicx Jul 27, 2026
26f315d
fix(dev): resolve public-root symlink redirects
james-elicx Jul 27, 2026
f076a56
Merge commit '26f315db8f0c39a493fcee7150eb7a492eb5b180' into codex/pr…
james-elicx Jul 27, 2026
220fffc
Merge remote-tracking branch 'origin/main' into codex/pr2711-owner
james-elicx Jul 27, 2026
a256627
fix(dev): fail closed on conflicting public redirects
james-elicx Jul 27, 2026
36c5f76
Merge remote-tracking branch 'origin/main' into codex/pr2711-owner
james-elicx Jul 27, 2026
ec3ec0b
Merge remote-tracking branch 'origin/main' into codex/pr2711-owner
james-elicx Jul 27, 2026
454c1c1
Merge remote-tracking branch 'origin/main' into agent/sync-pr2711
Boyeep Jul 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions packages/vinext/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,11 @@ import { createWasmModuleImportPlugin } from "./plugins/wasm-module-import.js";
import { getTypeofWindowReplacement, replaceTypeofWindow } from "./plugins/typeof-window.js";
import { hasMdxFiles } from "./utils/mdx-scan.js";
import { scanPublicFileRoutes } from "./utils/public-routes.js";
import {
createDevPublicFileEtags,
resolveDevPublicIfNoneMatch,
updateDevPublicFileEtag,
} from "./server/dev-public-etag.js";
import { publicFilePathVariants } from "./utils/public-file-path.js";
import { methodNotAllowedResponse } from "./server/http-error-responses.js";
import type { Options as VitePluginReactOptions } from "@vitejs/plugin-react";
Expand Down Expand Up @@ -4279,11 +4284,50 @@ export const loadServerActionClient = ${
},

configureServer(server: ViteDevServer) {
const etagPublicDir = server.config.publicDir || undefined;
let devPublicFileEtags = etagPublicDir
? createDevPublicFileEtags(etagPublicDir)
: undefined;

server.middlewares.use((req, _res, next) => {
req.__vinextOriginalEncodedUrl ??= req.url;
if (!devPublicFileEtags) {
next();
return;
}
const normalizedIfNoneMatch = resolveDevPublicIfNoneMatch(
req.method,
req.url,
req.headers["if-none-match"],
devPublicFileEtags,
nextConfig?.basePath,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor the resolved Vite base during ETag lookup

When an application configures Vite's base directly (for example, base: "/docs/") without setting Next's basePath, this passes an empty base path to the lookup. A request for /docs/asset.js therefore misses the indexed /asset.js; Vite subsequently strips /docs and serves the public file, but strong, list, or wildcard If-None-Match validators are left unnormalized and return 200 instead of 304. The Pages request handler already treats server.config.base as the fallback routing base, so this middleware should derive the same resolved base path.

Useful? React with 👍 / 👎.

);
if (normalizedIfNoneMatch) {
// sirv compares If-None-Match to its generated weak ETag as an
// exact string. Resolve RFC weak/list/wildcard matching here, then
// give sirv the exact value so its normal 304 path handles the body.
req.headers["if-none-match"] = normalizedIfNoneMatch;
}
next();
});

const updateDevPublicEtag = (filePath: string) => {
if (!devPublicFileEtags || !etagPublicDir) return;
if (!updateDevPublicFileEtag(devPublicFileEtags, filePath)) {
devPublicFileEtags = createDevPublicFileEtags(
etagPublicDir,
undefined,
undefined,
devPublicFileEtags.viteUsesStatLookup,
);
}
};
server.watcher.on("add", updateDevPublicEtag);
server.watcher.on("change", updateDevPublicEtag);
server.watcher.on("unlink", updateDevPublicEtag);
server.watcher.on("addDir", updateDevPublicEtag);
server.watcher.on("unlinkDir", updateDevPublicEtag);

// Watch route files for additions/removals to invalidate route cache.
const pageExtensions = fileMatcher.extensionRegex;

Expand Down
Loading
Loading