feat: 网关上传转对象存储(FS 适配器、8MB 上限、防路径穿越)
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import { mkdtempSync, rmSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import { beforeAll, afterAll, describe, expect, it } from 'vitest';
|
||||
import { buildApp } from '../../src/app/app';
|
||||
import { makeToken, setupTestJwks } from '../support/token';
|
||||
|
||||
const dir = mkdtempSync(join(tmpdir(), 'bpos-store-'));
|
||||
|
||||
describe('upload', () => {
|
||||
let token = '';
|
||||
beforeAll(async () => {
|
||||
process.env.OBJECT_STORE_DIR = dir;
|
||||
await setupTestJwks();
|
||||
token = await makeToken({ roles: ['user'], aud: 'api-gateway' });
|
||||
});
|
||||
afterAll(() => rmSync(dir, { recursive: true, force: true }));
|
||||
|
||||
it('上传→取回一致;越权 401;超 8MB 413', async () => {
|
||||
const app = buildApp();
|
||||
const payload = new TextEncoder().encode('原件字节');
|
||||
const up = await app.request('/api/upload', {
|
||||
method: 'POST',
|
||||
headers: { authorization: `Bearer ${token}`, 'content-type': 'text/plain', 'x-filename': 'a.txt' },
|
||||
body: payload,
|
||||
});
|
||||
expect(up.status).toBe(201);
|
||||
const { ref } = (await up.json()) as { ref: string };
|
||||
const back = await app.request(`/api/upload/${ref}`, { headers: { authorization: `Bearer ${token}` } });
|
||||
expect(back.status).toBe(200);
|
||||
expect(back.headers.get('content-type')).toContain('text/plain');
|
||||
expect(new Uint8Array(await back.arrayBuffer())).toEqual(payload);
|
||||
|
||||
expect((await app.request('/api/upload', { method: 'POST' })).status).toBe(401);
|
||||
|
||||
const big = new Uint8Array(8 * 1024 * 1024 + 1);
|
||||
const tooBig = await app.request('/api/upload', {
|
||||
method: 'POST', headers: { authorization: `Bearer ${token}` }, body: big,
|
||||
});
|
||||
expect(tooBig.status).toBe(413);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user