installer-rp: decode data: URL images instead of crashing

사진 URL 에 data: URI 가 들어오면 http/https 만 처리하는 다운로더가
'Protocol "data:" not supported' 로 설치 전체를 중단시키던 문제 수정.
data: URL 은 이미지 바이트를 직접 품고 있으므로 base64/percent-encoding
을 디코드해 Buffer 로 바로 반환한다. 잘못된 형식은 명확한 메시지로 거절.
This commit is contained in:
2026-06-05 15:58:22 +09:00
parent 3baf84cfd1
commit d9ba2b0f35
2 changed files with 24 additions and 0 deletions

View File

@@ -63,13 +63,36 @@ function fetchBuffer(url: string, redirects = 0): Promise<Buffer> {
})
}
/**
* data: URL 이면 그 안에 들어 있는 바이트를 바로 Buffer 로 디코드한다.
* data: URL 은 이미지 데이터 자체를 품고 있어 네트워크 요청이 필요 없으며,
* http/https 만 다루는 fetchBuffer 에 넘기면 `Protocol "data:" not supported`
* 로 터지므로 여기서 가로챈다. data: URL 이 아니면 null.
*/
function decodeDataUrl(url: string): Buffer | null {
if (!/^data:/i.test(url)) return null
const comma = url.indexOf(',')
if (comma < 0) throw new Error(t('errors.imageDataUrlInvalid'))
const meta = url.slice(5, comma)
const data = url.slice(comma + 1)
// `;base64` 가 있으면 base64, 없으면 percent-encoding 된 텍스트.
const buf = /;base64/i.test(meta)
? Buffer.from(data, 'base64')
: Buffer.from(decodeURIComponent(data), 'utf8')
if (buf.length === 0) throw new Error(t('errors.imageDataUrlInvalid'))
return buf
}
/**
* 이미지 URL 을 다운로드해 Buffer 로 돌려준다.
* - data: URL 이면 내장 바이트를 바로 디코드 (네트워크 없음).
* - 유튜브 영상 URL 이면 `i.ytimg.com/vi/<id>/maxresdefault.jpg` 1차 →
* 실패하면 `hqdefault.jpg` 로 폴백.
* - 그 외 URL 은 HTTP GET 으로 그대로 받음.
*/
export async function downloadImage(rawUrl: string): Promise<Buffer> {
const dataBuf = decodeDataUrl(rawUrl)
if (dataBuf) return dataBuf
const ytId = ytIdFromUrl(rawUrl)
if (ytId) {
try {