Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(server): ensure consistency for url to file mapping in importAnalysis and static middleware #6518

Merged
merged 7 commits into from Mar 3, 2022
7 changes: 3 additions & 4 deletions packages/vite/src/node/plugins/importAnalysis.ts
Expand Up @@ -21,7 +21,8 @@ import {
normalizePath,
removeImportQuery,
unwrapId,
moduleListContains
moduleListContains,
fsPathFromUrl
} from '../utils'
import {
debugHmr,
Expand Down Expand Up @@ -399,9 +400,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
let url = normalizedUrl

// record as safe modules
server?.moduleGraph.safeModulesPath.add(
cleanUrl(url).slice(4 /* '/@fs'.length */)
)
server?.moduleGraph.safeModulesPath.add(fsPathFromUrl(url))

// rewrite
if (url !== specifier) {
Expand Down
4 changes: 2 additions & 2 deletions packages/vite/src/node/server/index.ts
Expand Up @@ -33,7 +33,7 @@ import { timeMiddleware } from './middlewares/time'
import type { ModuleNode } from './moduleGraph'
import { ModuleGraph } from './moduleGraph'
import type { Connect } from 'types/connect'
import { ensureLeadingSlash, normalizePath } from '../utils'
import { normalizePath } from '../utils'
import { errorMiddleware, prepareError } from './middlewares/error'
import type { HmrOptions } from './hmr'
import { handleHMRUpdate, handleFileAddUnlink } from './hmr'
Expand Down Expand Up @@ -693,7 +693,7 @@ function createServerCloseFn(server: http.Server | null) {
}

function resolvedAllowDir(root: string, dir: string): string {
return ensureLeadingSlash(normalizePath(path.resolve(root, dir)))
return normalizePath(path.resolve(root, dir))
}

export function resolveServerOptions(
Expand Down
6 changes: 2 additions & 4 deletions packages/vite/src/node/server/middlewares/static.ts
Expand Up @@ -4,12 +4,11 @@ import type { Options } from 'sirv'
import sirv from 'sirv'
import type { Connect } from 'types/connect'
import type { ViteDevServer } from '../..'
import { normalizePath } from '../..'
import { FS_PREFIX } from '../../constants'
import {
cleanUrl,
ensureLeadingSlash,
fsPathFromId,
fsPathFromUrl,
isImportRequest,
isInternalRequest,
isWindows,
Expand Down Expand Up @@ -148,8 +147,7 @@ export function isFileServingAllowed(
): boolean {
if (!server.config.server.fs.strict) return true

const cleanedUrl = cleanUrl(url)
const file = ensureLeadingSlash(normalizePath(cleanedUrl))
const file = fsPathFromUrl(url)

if (server.config.server.fs.deny.some((i) => isMatch(file, i, _matchOptions)))
return false
Expand Down
38 changes: 35 additions & 3 deletions packages/vite/src/node/utils.ts
Expand Up @@ -9,7 +9,8 @@ import {
DEFAULT_EXTENSIONS,
VALID_ID_PREFIX,
CLIENT_PUBLIC_PATH,
ENV_PUBLIC_PATH
ENV_PUBLIC_PATH,
CLIENT_ENTRY
} from './constants'
import resolve from 'resolve'
import { builtinModules } from 'module'
Expand Down Expand Up @@ -139,20 +140,51 @@ export function createDebugger(
}
}

function testCaseInsensitiveFS() {
if (!CLIENT_ENTRY.endsWith('client.mjs')) {
throw new Error(
`cannot test case insensitive FS, CLIENT_ENTRY const doesn't contain client.mjs`
)
}
if (!fs.existsSync(CLIENT_ENTRY)) {
throw new Error(
'cannot test case insensitive FS, CLIENT_ENTRY does not point to an existing file: ' +
CLIENT_ENTRY
)
}
return fs.existsSync(CLIENT_ENTRY.replace('client.mjs', 'cLiEnT.mjs'))
}

export const isCaseInsensitiveFS = testCaseInsensitiveFS()

export const isWindows = os.platform() === 'win32'

const VOLUME_RE = /^[A-Z]:/i

export function normalizePath(id: string): string {
return path.posix.normalize(isWindows ? slash(id) : id)
let normalized = path.normalize(id)
if (isCaseInsensitiveFS) {
normalized = normalized.toLowerCase()
}
Copy link
Member

Choose a reason for hiding this comment

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

I think we shouldn't do the normalization to lowercase in this PR. We had a few requests to do so before but decided that it was better to ask the user to properly name paths. Something may work in windows but fail in linux if we had this in. Touching normalizePath is also quite a big change. Let's check the rest of the issues without it

if (isWindows) {
normalized = slash(normalized)
}
return normalized
}

export function fsPathFromId(id: string): string {
const fsPath = normalizePath(id.slice(FS_PREFIX.length))
const fsPath = normalizePath(
id.startsWith(FS_PREFIX) ? id.slice(FS_PREFIX.length) : id
)
return fsPath.startsWith('/') || fsPath.match(VOLUME_RE)
? fsPath
: `/${fsPath}`
}

export function fsPathFromUrl(url: string): string {
return fsPathFromId(cleanUrl(url))
}

export function ensureVolumeInPath(file: string): string {
return isWindows ? path.resolve(file) : file
}
Expand Down