Skip to content

Commit

Permalink
fix: implement for preview as well
Browse files Browse the repository at this point in the history
  • Loading branch information
benmccann committed Oct 17, 2022
1 parent e830803 commit bed03db
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 39 deletions.
42 changes: 28 additions & 14 deletions packages/vite/src/node/preview.ts
@@ -1,3 +1,4 @@
import fs from 'node:fs'
import path from 'node:path'
import type * as http from 'node:http'
import sirv from 'sirv'
Expand All @@ -15,7 +16,7 @@ import {
import { openBrowser } from './server/openBrowser'
import compression from './server/middlewares/compression'
import { proxyMiddleware } from './server/middlewares/proxy'
import { resolveHostname, resolveServerUrls } from './utils'
import { hasCorrectCase, resolveHostname, resolveServerUrls } from './utils'
import { printServerUrls } from './logger'
import { resolveConfig } from '.'
import type { InlineConfig, ResolvedConfig } from '.'
Expand Down Expand Up @@ -112,21 +113,34 @@ export async function preview(
// static assets
const distDir = path.resolve(config.root, config.build.outDir)
const headers = config.preview.headers
app.use(
previewBase,
sirv(distDir, {
etag: true,
dev: true,
single: config.appType === 'spa',
setHeaders(res) {
if (headers) {
for (const name in headers) {
res.setHeader(name, headers[name]!)
}
const asset_server = sirv(distDir, {
etag: true,
dev: true,
single: config.appType === 'spa',
setHeaders(res) {
if (headers) {
for (const name in headers) {
res.setHeader(name, headers[name]!)
}
}
})
)
}
})
app.use(previewBase, async (req, res, next) => {
// TODO: why is this necessary? what's screwing up the request URL?
const fixedUrl = req.url!.startsWith('//')
? req.url!.substring(1)
: req.url!
const url = new URL(fixedUrl, 'http://example.com')
const pathname = decodeURIComponent(url.pathname)
const file = distDir + pathname
if (
!fs.existsSync(file) ||
(!fs.statSync(file).isDirectory() && !hasCorrectCase(file, distDir))
) {
return next()
}
asset_server(req, res, next)
})

// apply post server hooks from plugins
postHooks.forEach((fn) => fn && fn())
Expand Down
30 changes: 5 additions & 25 deletions packages/vite/src/node/server/middlewares/static.ts
Expand Up @@ -10,6 +10,7 @@ import {
cleanUrl,
fsPathFromId,
fsPathFromUrl,
hasCorrectCase,
isFileReadable,
isImportRequest,
isInternalRequest,
Expand Down Expand Up @@ -49,19 +50,16 @@ export function servePublicMiddleware(

// Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`
return function viteServePublicMiddleware(req, res, next) {
const url = req.url!
// skip import request and internal requests `/@fs/ /@vite-client` etc...
if (isImportRequest(url) || isInternalRequest(url)) {
if (isImportRequest(req.url!) || isInternalRequest(req.url!)) {
return next()
}
const queryStringIdx = url.indexOf('?')
const pathname =
queryStringIdx >= 0 ? url.substring(0, queryStringIdx) : url
const url = new URL(req.url!, 'http://example.com')
const pathname = decodeURIComponent(url.pathname)
const file = dir + pathname
if (
!fs.existsSync(file) ||
fs.statSync(file).isDirectory() ||
!hasCorrectCase(file, dir)
(!fs.statSync(file).isDirectory() && !hasCorrectCase(file, dir))
) {
return next()
}
Expand Down Expand Up @@ -230,21 +228,3 @@ function renderRestrictedErrorHTML(msg: string): string {
</body>
`
}

/**
* Determine if a file is being requested with the correct case, to ensure
* consistent behaviour between dev and prod and across operating systems.
* Note that we can't use realpath here, because we don't want to follow
* symlinks.
*/
function hasCorrectCase(file: string, assets: string): boolean {
if (file === assets) return true

const parent = path.dirname(file)

if (fs.readdirSync(parent).includes(path.basename(file))) {
return hasCorrectCase(parent, assets)
}

return false
}
18 changes: 18 additions & 0 deletions packages/vite/src/node/utils.ts
Expand Up @@ -1190,3 +1190,21 @@ export const isNonDriveRelativeAbsolutePath = (p: string): boolean => {
if (!isWindows) return p.startsWith('/')
return windowsDrivePathPrefixRE.test(p)
}

/**
* Determine if a file is being requested with the correct case, to ensure
* consistent behaviour between dev and prod and across operating systems.
* Note that we can't use realpath here, because we don't want to follow
* symlinks.
*/
export function hasCorrectCase(file: string, assets: string): boolean {
if (file === assets) return true

const parent = path.dirname(file)

if (fs.readdirSync(parent).includes(path.basename(file))) {
return hasCorrectCase(parent, assets)
}

return false
}

0 comments on commit bed03db

Please sign in to comment.