73 lines
2.1 KiB
TypeScript
73 lines
2.1 KiB
TypeScript
export const MAX_CAD_BYTES = 50 * 1024 * 1024;
|
|
export const CAD_FETCH_TIMEOUT_MS = 15_000;
|
|
|
|
export function assertCadByteLength(byteLength: number): void {
|
|
if (!Number.isFinite(byteLength) || byteLength < 0) {
|
|
throw new Error('CAD 파일 크기를 확인할 수 없습니다.');
|
|
}
|
|
if (byteLength > MAX_CAD_BYTES) {
|
|
throw new Error('CAD 파일은 50 MiB 이하여야 합니다.');
|
|
}
|
|
}
|
|
|
|
export function resolveCadUrl(input: string, base: URL): URL {
|
|
const url = new URL(input, base);
|
|
if (!['http:', 'https:'].includes(url.protocol)) {
|
|
throw new Error('CAD URL은 HTTP(S)만 허용합니다.');
|
|
}
|
|
if (url.origin !== base.origin) {
|
|
throw new Error('CAD URL은 viewer와 같은 origin만 허용합니다.');
|
|
}
|
|
return url;
|
|
}
|
|
|
|
export async function fetchCadBuffer(url: URL): Promise<ArrayBuffer> {
|
|
const controller = new AbortController();
|
|
const timeout = window.setTimeout(() => controller.abort(), CAD_FETCH_TIMEOUT_MS);
|
|
|
|
try {
|
|
const response = await fetch(url, {
|
|
credentials: 'same-origin',
|
|
signal: controller.signal,
|
|
});
|
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
|
|
const declaredLength = Number(response.headers.get('content-length'));
|
|
if (Number.isFinite(declaredLength) && declaredLength > 0) {
|
|
assertCadByteLength(declaredLength);
|
|
}
|
|
|
|
if (!response.body) {
|
|
const buffer = await response.arrayBuffer();
|
|
assertCadByteLength(buffer.byteLength);
|
|
return buffer;
|
|
}
|
|
|
|
const reader = response.body.getReader();
|
|
const chunks: Uint8Array[] = [];
|
|
let total = 0;
|
|
while (true) {
|
|
const { done, value } = await reader.read();
|
|
if (done) break;
|
|
total += value.byteLength;
|
|
assertCadByteLength(total);
|
|
chunks.push(value);
|
|
}
|
|
|
|
const data = new Uint8Array(total);
|
|
let offset = 0;
|
|
for (const chunk of chunks) {
|
|
data.set(chunk, offset);
|
|
offset += chunk.byteLength;
|
|
}
|
|
return data.buffer;
|
|
} catch (error) {
|
|
if (controller.signal.aborted) {
|
|
throw new Error('CAD 파일 요청 시간이 초과되었습니다.');
|
|
}
|
|
throw error;
|
|
} finally {
|
|
window.clearTimeout(timeout);
|
|
}
|
|
}
|