fix: 레거시 ID-only URL 은 전역 유일할 때만 제공하고 정규 경로 충돌 제거
폴더별 중복 ID 허용 이후, ID 만으로 영상을 찾는 레거시/공유 fallback (getVideoByIdGlobal) 이 임의의 폴더(작은 folder_id) 를 돌려줘서 엉뚱한 영상이 나올 수 있었다. 전역에서 정확히 1건일 때만 반환하고, 중복이면 null → 호출 측 404 로 거절한다. 영향: /file/video/:id, /file/video/:id/thumb, /api/video/:id(meta). 또한 죽은 레거시 라우트 /api/video/:videoId/file 를 제거했다. 이 라우트는 앱이 더는 만들지 않으면서 정규 경로 라우트 /api/video/:topName/:videoId 와 2세그먼트에서 충돌해, ID 가 리터럴 "file" 인 영상의 정규 URL 을 가로챘다. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
This commit is contained in:
@@ -100,8 +100,14 @@ function sendVideoFile(video: Video, req: Parameters<RequestHandler>[0], res: Pa
|
|||||||
/**
|
/**
|
||||||
* 영상 파일 스트리밍 (짧은 ID-only URL — 외부 공유 호환용 / 레거시).
|
* 영상 파일 스트리밍 (짧은 ID-only URL — 외부 공유 호환용 / 레거시).
|
||||||
* - GET /file/video/:videoId
|
* - GET /file/video/:videoId
|
||||||
* - GET /api/video/:videoId/file
|
* ID 가 전역에서 정확히 1건일 때만 제공한다. 같은 ID 가 여러 폴더에 있으면
|
||||||
|
* getVideoByIdGlobal 이 null 을 돌려주므로 404 (어느 폴더인지 모호).
|
||||||
|
* 폴더가 확실한 경우엔 정규 경로 URL `/api/video/폴더/[폴더/]ID` 를 쓸 것.
|
||||||
* ?edited=0 이면 원본을 강제, 기본은 편집본 있으면 편집본.
|
* ?edited=0 이면 원본을 강제, 기본은 편집본 있으면 편집본.
|
||||||
|
*
|
||||||
|
* 주의: 예전 `/api/video/:videoId/file` 레거시 라우트는 제거했다. 정규 경로
|
||||||
|
* 라우트 `/api/video/:topName/:videoId` 와 2세그먼트에서 충돌해서, ID 가
|
||||||
|
* 리터럴 "file" 인 영상의 정규 URL `/api/video/폴더/file` 을 가로챘기 때문.
|
||||||
*/
|
*/
|
||||||
const streamVideoHandler: RequestHandler = (req, res, next) => {
|
const streamVideoHandler: RequestHandler = (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
@@ -116,7 +122,6 @@ const streamVideoHandler: RequestHandler = (req, res, next) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
publicRouter.get('/file/video/:videoId', streamVideoHandler)
|
publicRouter.get('/file/video/:videoId', streamVideoHandler)
|
||||||
publicRouter.get('/api/video/:videoId/file', streamVideoHandler)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 영상 파일 스트리밍 (폴더 경로 + ID — 정규 공유 URL).
|
* 영상 파일 스트리밍 (폴더 경로 + ID — 정규 공유 URL).
|
||||||
@@ -125,9 +130,8 @@ publicRouter.get('/api/video/:videoId/file', streamVideoHandler)
|
|||||||
*
|
*
|
||||||
* 재생 페이지(/video/...)와 동일한 경로 규칙. 마지막 세그먼트가 영상 ID 이고
|
* 재생 페이지(/video/...)와 동일한 경로 규칙. 마지막 세그먼트가 영상 ID 이고
|
||||||
* 앞쪽 세그먼트는 그 영상이 실제 속한 폴더 경로와 일치해야 한다.
|
* 앞쪽 세그먼트는 그 영상이 실제 속한 폴더 경로와 일치해야 한다.
|
||||||
*
|
* (예전 `/api/video/:videoId/file` 레거시 라우트와의 2세그먼트 충돌은 그 라우트를
|
||||||
* 라우트 등록 순서 주의: 위의 `/api/video/:videoId/file` (2세그·끝이 리터럴 "file")
|
* 제거해서 해소했다 — 이제 ID 가 "file" 인 영상도 정규 URL 로 정확히 찾는다.)
|
||||||
* 보다 뒤에 둬서, 레거시 URL 이 이 경로 라우트에 가로채이지 않게 한다.
|
|
||||||
*/
|
*/
|
||||||
const streamVideoByPathHandler: RequestHandler = (req, res, next) => {
|
const streamVideoByPathHandler: RequestHandler = (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -309,15 +309,18 @@ export function getVideoInFolder(folderId: number, id: string): Video | null {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID 만으로 전역에서 첫 번째 영상을 찾는다 (폴더 경로 없는 레거시/외부공유 fallback).
|
* ID 만으로 전역에서 영상을 찾는다 (폴더 경로 없는 레거시/외부공유 fallback).
|
||||||
* 같은 ID 가 여러 폴더에 있으면 folder_id 가 작은(=먼저 만든) 쪽을 돌려준다.
|
* ID 는 이제 폴더별로만 유일하므로, 같은 ID 가 여러 폴더에 있으면 어느 쪽인지
|
||||||
|
* 모호하다. 그런 경우엔 아무 것도 돌려주지 않아 호출 측이 404 로 처리하게 한다.
|
||||||
|
* 전역에서 정확히 1건일 때만 그 영상을 돌려준다.
|
||||||
*/
|
*/
|
||||||
export function getVideoByIdGlobal(id: string): Video | null {
|
export function getVideoByIdGlobal(id: string): Video | null {
|
||||||
if (!isSafeVideoId(id)) return null
|
if (!isSafeVideoId(id)) return null
|
||||||
const r = getDb()
|
const rows = getDb()
|
||||||
.prepare(`SELECT * FROM videos WHERE id = ? ORDER BY folder_id LIMIT 1`)
|
.prepare(`SELECT * FROM videos WHERE id = ? ORDER BY folder_id LIMIT 2`)
|
||||||
.get(id) as VideoRow | undefined
|
.all(id) as VideoRow[]
|
||||||
return r ? rowToVideo(r) : null
|
if (rows.length !== 1) return null // 없음 또는 중복(모호) → 404
|
||||||
|
return rowToVideo(rows[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
export function listVideosInFolder(folderId: number): Video[] {
|
export function listVideosInFolder(folderId: number): Video[] {
|
||||||
|
|||||||
Reference in New Issue
Block a user