fix(frontend): upload asset lolos proxy — BODY_SIZE_LIMIT 8M + proxy 413 jelas
Body upload (JSON base64, ~7 MiB untuk file 5 MiB) ditolak default adapter-node 512K sebelum sampai backend Flask, lalu error itu terlapor sebagai 502 'Backend tidak tersedia'. - podman-compose: BODY_SIZE_LIMIT=8M untuk elemes-frontend - hooks.server: SvelteKitError body-size (413) dipisah dari kegagalan koneksi — balas 413 'Ukuran file terlalu besar' bukan 502 - test: proxy balas 413 untuk body melebihi limit
This commit is contained in:
parent
c127309dd8
commit
8fd39d6e1a
|
|
@ -57,6 +57,39 @@ describe('hooks.server handle', () => {
|
|||
expect(response.headers.get('Cross-Origin-Resource-Policy')).toBe('cross-origin');
|
||||
});
|
||||
|
||||
it('should return 413 with size message when body exceeds adapter limit', async () => {
|
||||
// SvelteKitError dari adapter-node saat body POST melebihi BODY_SIZE_LIMIT.
|
||||
// Proxy harus balas 413 dengan pesan ukuran — bukan 502 "Backend tidak tersedia".
|
||||
const arrayBufferMock = vi.fn().mockRejectedValue(
|
||||
Object.assign(new Error('Content-length of 947488 exceeds limit of 524288 bytes.'), { status: 413 })
|
||||
);
|
||||
const mockEvent: any = {
|
||||
request: {
|
||||
method: 'POST',
|
||||
headers: new Headers({ 'content-type': 'application/json' }),
|
||||
arrayBuffer: arrayBufferMock
|
||||
},
|
||||
url: new URL('https://sinau-c-dev.manakin-gentoo.ts.net/api/content/assets/upload')
|
||||
};
|
||||
|
||||
const origFetch = global.fetch;
|
||||
global.fetch = vi.fn() as any;
|
||||
|
||||
try {
|
||||
const resolve = vi.fn();
|
||||
const response = await handle({ event: mockEvent, resolve });
|
||||
|
||||
expect(response.status).toBe(413);
|
||||
const body = await response.json();
|
||||
expect(body.success).toBe(false);
|
||||
expect(body.message).toMatch(/terlalu besar/i);
|
||||
// Tidak boleh dikirim ke backend sama sekali
|
||||
expect(global.fetch).not.toHaveBeenCalled();
|
||||
} finally {
|
||||
global.fetch = origFetch;
|
||||
}
|
||||
});
|
||||
|
||||
it('should read body as arrayBuffer when proxying POST requests', async () => {
|
||||
const arrayBufferMock = vi.fn().mockResolvedValue(new Uint8Array([1, 2, 3]).buffer);
|
||||
const mockEvent: any = {
|
||||
|
|
|
|||
|
|
@ -77,9 +77,28 @@ export const handle: Handle = async ({ event, resolve }) => {
|
|||
status: res.status,
|
||||
headers: resHeaders,
|
||||
});
|
||||
} catch (err) {
|
||||
} catch (err: any) {
|
||||
// adapter-node melempar SvelteKitError saat body POST melebihi
|
||||
// BODY_SIZE_LIMIT — bukan berarti backend mati. Laporkan sebagai 413
|
||||
// dengan pesan yang jelas, jangan 502 "Backend tidak tersedia".
|
||||
const isBodyTooLarge =
|
||||
err?.status === 413 || /exceeds limit/i.test(String(err?.message ?? ''));
|
||||
if (isBodyTooLarge) {
|
||||
console.warn(`[hooks] Body too large for ${event.request.method} ${event.url.pathname}`);
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
success: false,
|
||||
error: 'Payload too large',
|
||||
message: 'Ukuran file terlalu besar (maksimum 5 MiB per asset)'
|
||||
}),
|
||||
{
|
||||
status: 413,
|
||||
headers: { 'content-type': 'application/json' }
|
||||
}
|
||||
);
|
||||
}
|
||||
console.error(`API proxy error (${backendUrl}):`, err);
|
||||
return new Response(JSON.stringify({ error: 'Backend unavailable' }), {
|
||||
return new Response(JSON.stringify({ success: false, error: 'Backend unavailable', message: 'Backend tidak tersedia' }), {
|
||||
status: 502,
|
||||
headers: { 'content-type': 'application/json' },
|
||||
});
|
||||
|
|
|
|||
|
|
@ -83,6 +83,9 @@ services:
|
|||
environment:
|
||||
- ORIGIN=${ORIGIN:-http://localhost:3000}
|
||||
- API_BACKEND=http://127.0.0.1:5000
|
||||
# Backend menerima asset ≤ 5 MiB (JSON base64 ≈ 7 MiB di wire).
|
||||
# Default adapter-node 512K menolak upload gambar sebelum sampai backend.
|
||||
- BODY_SIZE_LIMIT=8M
|
||||
- PUBLIC_APP_BAR_TITLE=${APP_BAR_TITLE}
|
||||
- PUBLIC_COPYRIGHT_TEXT=${COPYRIGHT_TEXT}
|
||||
- PUBLIC_PAGE_TITLE_SUFFIX=${PAGE_TITLE_SUFFIX}
|
||||
|
|
|
|||
Loading…
Reference in New Issue