diff --git a/packages/playground/assets/index.html b/packages/playground/assets/index.html
index cc0b8fd33c8250..01307801abc054 100644
--- a/packages/playground/assets/index.html
+++ b/packages/playground/assets/index.html
@@ -13,6 +13,9 @@
Raw References from publicDir
Raw CSS from publicDir should load (this should be red)
+
+
+
Asset Imports from JS
diff --git a/packages/playground/assets/static/white space.png b/packages/playground/assets/static/white space.png
new file mode 100644
index 00000000000000..4388bfdca3d4d7
Binary files /dev/null and b/packages/playground/assets/static/white space.png differ
diff --git a/packages/vite/src/node/server/index.ts b/packages/vite/src/node/server/index.ts
index 8cd0ba158c4eb2..538994c2903941 100644
--- a/packages/vite/src/node/server/index.ts
+++ b/packages/vite/src/node/server/index.ts
@@ -25,6 +25,7 @@ import {
indexHtmlMiddleware
} from './middlewares/indexHtml'
import history from 'connect-history-api-fallback'
+import { decodeURIMiddleware } from './middlewares/decodeURI'
import {
serveRawFsMiddleware,
servePublicMiddleware,
@@ -416,6 +417,9 @@ export async function createServer(
// hmr reconnect ping
middlewares.use('/__vite_ping', (_, res) => res.end('pong'))
+ //decode request url
+ middlewares.use(decodeURIMiddleware())
+
// serve static files under /public
// this applies before the transform middleware so that these files are served
// as-is without transforms.
diff --git a/packages/vite/src/node/server/middlewares/decodeURI.ts b/packages/vite/src/node/server/middlewares/decodeURI.ts
new file mode 100644
index 00000000000000..b44a66f8be3ee1
--- /dev/null
+++ b/packages/vite/src/node/server/middlewares/decodeURI.ts
@@ -0,0 +1,18 @@
+import { Connect } from 'types/connect'
+
+export function decodeURIMiddleware(): Connect.NextHandleFunction {
+ return (req, _, next) => {
+ // #2195
+ req.url = decodeURI(req.url!)
+
+ // `sirv` middleware uses the req._parsedUrl values to find the file,
+ // so decode it all together.
+ // @ts-ignore
+ const parsedUrl = req._parsedUrl
+ for (const key of Object.keys(parsedUrl)) {
+ const val = parsedUrl[key]
+ if (val) parsedUrl[key] = decodeURI(val)
+ }
+ next()
+ }
+}
diff --git a/packages/vite/src/node/server/middlewares/static.ts b/packages/vite/src/node/server/middlewares/static.ts
index 38916d252a0b5c..fe0ebaadd435d1 100644
--- a/packages/vite/src/node/server/middlewares/static.ts
+++ b/packages/vite/src/node/server/middlewares/static.ts
@@ -36,9 +36,6 @@ export function serveStaticMiddleware(
return next()
}
- // #1426
- url = req.url = decodeURI(url)
-
// apply aliases to static requests as well
let redirected: string | undefined
for (const { find, replacement } of config.resolve.alias) {
@@ -74,7 +71,6 @@ export function serveRawFsMiddleware(): Connect.NextHandleFunction {
if (url.startsWith(FS_PREFIX)) {
url = url.slice(FS_PREFIX.length)
if (isWin) url = url.replace(/^[A-Z]:/i, '')
- req.url = decodeURI(url)
serveFromRoot(req, res, next)
} else {
next()
diff --git a/packages/vite/src/node/server/middlewares/transform.ts b/packages/vite/src/node/server/middlewares/transform.ts
index 0759ee7dbe49db..bf123bb93b9033 100644
--- a/packages/vite/src/node/server/middlewares/transform.ts
+++ b/packages/vite/src/node/server/middlewares/transform.ts
@@ -54,10 +54,7 @@ export function transformMiddleware(
let url
try {
- url = decodeURI(removeTimestampQuery(req.url!)).replace(
- NULL_BYTE_PLACEHOLDER,
- '\0'
- )
+ url = removeTimestampQuery(req.url!).replace(NULL_BYTE_PLACEHOLDER, '\0')
} catch (err) {
// if it starts with %PUBLIC%, someone's migrating from something
// like create-react-app