fix(tauri): return 404 for missing subresource assets instead of SPA index.html fallback - #15939
fix(tauri): return 404 for missing subresource assets instead of SPA index.html fallback#15939gronke wants to merge 4 commits into
Conversation
…index.html fallback A request for a missing path with a static subresource extension (.js, .css, images, fonts, ...) previously resolved to index.html with 200 text/html, breaking ES module imports with an opaque MIME error that names neither the URL nor the cause. Applies to the tauri:// protocol and the CLI's built-in dev server; the SPA fallback for extensionless paths now logs a warning.
Package Changes Through 8cef582There are 14 changes which include tauri with minor, tauri-cli with minor, @tauri-apps/cli with minor, tauri-build with minor, tauri-runtime with minor, tauri-runtime-wry with minor, tauri-utils with minor, tauri-bundler with minor, tauri-macos-sign with minor, @tauri-apps/api with minor, tauri-codegen with minor, tauri-macros with minor, tauri-plugin with minor, tauri-driver with minor Planned Package VersionsThe following package releases are the planned based on the context of changes in this pull request.
Add another change file through the GitHub UI by following this link. Read about change files or the docs at github.com/jbolda/covector |
…_test_module Canonicalize the test dist dir like start() does; the scope check broke on the macOS /var symlink and Windows short names. Move the test module to the end of the file.
3438f2b to
4009af1
Compare
| // a missing subresource (script, style, image, ...) must never resolve to | ||
| // an HTML document; skipping the fallback chain lets the protocol handler | ||
| // answer 404 instead of `index.html` with a misleading mime type | ||
| let use_fallbacks = !tauri_utils::mime_type::has_subresource_extension(&path); |
There was a problem hiding this comment.
I'm not the most convinced with this, the whole point of this fallback is to always allow the client to react to the URL. Unless we can be sure that this is not from a navigation request, we should not do this.
There was a problem hiding this comment.
Good catch, and you are right that the extension heuristic could not answer it; a navigation to /reports/2024.pdf would have 404'd.
Reworked to decide from the request destination rather than the URL.
Measured what actually reaches the tauri:// handler on WebKitGTK 2.52.3: no Sec-Fetch-Dest for custom protocols, but Accept is text/html,application/xhtml+xml,… for navigations (including /reports/2024.pdf) and */* or image/… for scripts, images and fetch.
The rule is now: Sec-Fetch-Dest when the webview sends it (document/iframe/frame → navigation), otherwise Accept containing text/html, and if neither header is present the request counts as a navigation so the fallback is preserved. Navigations therefore always reach the frontend router, and only a request that does not present itself as a document load can 404.
This also removes the extension allowlist entirely, and AssetResolver keeps the old behaviour since it has no request to classify.
Only navigations resolve to the SPA index.html fallback, decided by Sec-Fetch-Dest where the webview sends it and by the Accept header otherwise, with no header evidence meaning navigation. Replaces the subresource extension allowlist, so a navigation to a document-looking path such as /reports/2024.pdf still reaches the frontend router while a missing script, style or image gets a 404. AssetResolver has no request to classify and keeps the historical fallback.
A request for a path missing from the bundled assets returned
200 text/html(the SPAindex.htmlfallback), so a failed ES module import surfaced only as'text/html' is not a valid JavaScript MIME type, naming neither the URL nor the cause.AppManager::get_assetskips the whole fallback chain when the requested path has a static subresource extension (conservative allowlist intauri_utils::mime_type::has_subresource_extension; dotted SPA routes like/product/v1.2keep the fallback).tauri://protocol answers404text/plainnaming the path; other errors keep the 500 path.on_web_resource_requestcan still override.index.htmlfor a missing path.get_asset's error path that made the boxed error non-downcastable totauri::Error.Header-based detection (
Sec-Fetch-Dest) was deliberately not used; it is unreliable on WebKitGTK custom schemes. First unit tests for theget_assetchain (map-backedAssetsimpl) and the dev-server resolution helper.Closes #15938