feat: npm run setup (yt-dlp + deps + build); lift upload size limit

scripts/setup.mjs runs `npm install`, downloads the platform-specific
yt-dlp binary from GitHub releases to ./bin/yt-dlp (which src/youtube.ts
already prefers), checks for ffmpeg and prints install hints, then runs
`tsc`. One command replaces three for fresh checkouts.

While verifying setup, hit `MulterError: File too large` (LIMIT_FILE_SIZE)
on a 10 GB mkv upload, and ETXTBSY on freshly downloaded yt-dlp.

- ETXTBSY: the redirect path in downloadFile opened a writestream to the
  destination before following the redirect, so the (unused) outer stream
  still held the file open when the post-download spawnSync ran. Split
  redirect-following from file writing so only the final 200 response
  opens the destination file.
- LIMIT_FILE_SIZE: removed the hard-coded 4 GB cap. Upload limit now
  defaults to Infinity and is configurable via UPLOAD_MAX_BYTES.
  Wrapped multer's middleware so its errors (LIMIT_FILE_SIZE etc.) come
  back as a clean 413 JSON instead of a stack trace from the global
  error handler.
- Also disabled Node's default 5 minute requestTimeout so 10 GB uploads
  over slow links don't get cut mid-stream. Configurable via
  HTTP_REQUEST_TIMEOUT_MS.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-15 17:13:47 +09:00
parent bb116f5c24
commit cb9406d88e
6 changed files with 213 additions and 7 deletions

View File

@@ -72,10 +72,14 @@ async function main(): Promise<void> {
res.status(500).send(`서버 오류: ${message}`)
})
app.listen(PORT, HOST, () => {
const server = app.listen(PORT, HOST, () => {
console.log(`[server] http://${HOST}:${PORT}`)
console.log(`[server] views: ${path.relative(process.cwd(), viewsDir)}`)
})
// 10GB 같은 큰 영상 업로드가 Node 의 기본 requestTimeout(5분) 에 걸려 끊기는 걸 막는다.
// 0 = 무제한. 필요하면 HTTP_REQUEST_TIMEOUT_MS 환경변수로 조정.
server.requestTimeout = Number(process.env.HTTP_REQUEST_TIMEOUT_MS ?? 0)
// 헤더 단계 타임아웃은 짧게 유지(기본 60초). 0 으로 해버리면 slowloris 류에 취약.
}
main().catch((err) => {