epicweb-dev / epicweb-dev/epic-stack

/img/* and /favicons/* 404 handler prevents static file serving when placed before dev/prod middleware

オープン
#1,079 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
TypeScript
スター
5.5k
フォーク
460
平均マージ
2時間 43分
マージ済み PR(30日)
1

説明

Problem
The 404 handler for /img/* and /favicons/* routes intercepts requests before the static file serving middleware can handle them, causing images and favicons to return 404 errors.

```
app.get(['/img/*splat', '/favicons/*splat'], (_req, res) => {
// if we made it past the express.static for these, then we're missing something.
// So we'll just send a 404 and won't bother calling other middleware.
res.status(404).send('Not found')
})

```
Current Behavior
When this handler is placed before the dev/prod server setup static files at /img/* and /favicons/* paths return 404 errors, unless the full /public/img path is used.

Expected Behavior
The 404 handler should only trigger after Express has attempted to serve static files from the public directory.

Solution

The 404 handler needs to be moved after the static file middleware setup block , so that:

In development: Vite middleware attempts to serve the files first
In production: express.static attempts to serve the files first
Only if neither finds the file, the 404 handler responds

Example:
```
if (IS_DEV) {
console.log('Starting development server')
const viteDevServer = await import('vite').then((vite) =>
vite.createServer({
server: { middlewareMode: true },
// We tell Vite we are running a custom app instead of
// the SPA default so it doesn't run HTML middleware
appType: 'custom',
}),
)
app.use(viteDevServer.middlewares)
app.use(async (req, res, next) => {
try {
const source = await viteDevServer.ssrLoadModule('./server/app.ts')
return await source.app(req, res, next)
} catch (error) {
if (typeof error === 'object' && error instanceof Error) {
viteDevServer.ssrFixStacktrace(error)
}
next(error)
}
})
} else {
console.log('Starting production server')
// React Router fingerprints its assets so we can cache forever.
app.use(
'/assets',
express.static('build/client/assets', {
immutable: true,
maxAge: '1y',
fallthrough: false,
}),
)
// Everything else (like favicon.ico) is cached for an hour. You may want to be
// more aggressive with this caching.
app.use(express.static('build/client', { maxAge: '1h' }))
app.use(await import(BUILD_PATH).then((mod) => mod.app))
}

app.get(['/img/*splat', '/favicons/*splat'], (_req, res) => {
// if we made it past the express.static for these, then we're missing something.
// So we'll just send a 404 and won't bother calling other middleware.
res.status(404).send('Not found')
})
```

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

IS_DEV を含む開発/本番用ミドルウェアブロックがあるサーバーエントリから始め、開発時に server/app.ts をどのように読み込むかを確認します。Vite または express.static がフォールバックハンドラーの前に /img/* と /favicons/* を処理することを検証します。既存の静的ファイルが配信され、存在しないファイルには引き続き 404 レスポンスが返されれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
express, typescript, vite
領域
backend, web-dev
issue の種類
バグ
難易度
2/5
見積もり時間
1〜3時間
活発さ
停滞
明瞭さ
明確に書かれている
初心者へのやさしさ
55/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。