Skip to content

Commit ad8fea5

Browse files
committed
feat(server): use multer
1 parent bb8b485 commit ad8fea5

6 files changed

Lines changed: 232 additions & 49 deletions

File tree

game/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
},
1212
"dependencies": {
1313
"@citizenfx/http-wrapper": "^0.2.2",
14+
"@koa/router": "^13.1.0",
1415
"form-data": "^4.0.1",
1516
"koa": "^2.15.4",
1617
"koa-body": "^6.0.1",
1718
"koa-router": "^13.0.1",
19+
"multer": "1.4.5-lts.1",
1820
"nanoid": "^5.0.8",
1921
"node-fetch": "^3.3.2"
2022
},
@@ -25,6 +27,8 @@
2527
"@types/formidable": "^3.4.5",
2628
"@types/koa": "^2.15.0",
2729
"@types/koa-router": "^7.4.8",
30+
"@types/koa__router": "^12.0.4",
31+
"@types/multer": "^1.4.12",
2832
"@types/node": "^22.8.6",
2933
"colorette": "^2.0.20",
3034
"esbuild": "^0.24.0",

game/pnpm-lock.yaml

Lines changed: 0 additions & 25 deletions
This file was deleted.

game/scripts/esbuild.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ const shouldRestart = process.argv.findIndex((arg) => arg === '--restart') !== -
99
const buildConfig = {
1010
server: {
1111
platform: 'node',
12-
target: ['node16'],
13-
format: 'cjs',
12+
target: ['node21'],
13+
format: 'cjs'
1414
},
1515
client: {
1616
platform: 'browser',

game/server/koa-router.ts

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
import Koa from 'koa';
2-
import { koaBody } from 'koa-body';
3-
import Router from 'koa-router';
2+
import Router from '@koa/router';
3+
import { multer } from './multer'
4+
45
// @ts-ignore - no types
56
import { setHttpCallback } from '@citizenfx/http-wrapper';
67

78
import FormData from 'form-data';
89
import fetch from 'node-fetch';
910
import { CaptureOptions, DataType } from './types';
1011
import { UploadStore } from './upload-store';
11-
import { readFile, unlink } from 'fs/promises';
1212

1313
export async function createServer(uploadStore: UploadStore) {
1414
const app = new Koa();
1515
const router = new Router();
16+
const upload = multer({
17+
storage: multer.memoryStorage()
18+
});
1619

17-
router.post('/image', async (ctx) => {
20+
router.post('/image', upload.single("file") as any, async (ctx) => {
1821
const token = ctx.request.headers['x-screencapture-token'] as string;
1922
if (!token) {
2023
ctx.status = 401;
@@ -25,25 +28,16 @@ export async function createServer(uploadStore: UploadStore) {
2528
const { callback, dataType, isRemote, remoteConfig, url, playerSource, correlationId } =
2629
uploadStore.getUpload(token);
2730

28-
const files = ctx.request.files;
29-
if (!files) {
30-
ctx.status = 400;
31-
ctx.body = { status: 'error', message: 'No files provided' };
32-
return;
33-
}
34-
35-
// dont blame me, but node runtime does not like formidable for some reason
36-
const file = files['file'] as any;
31+
const file = ctx.file;
3732
if (!file) {
3833
ctx.status = 400;
3934
ctx.body = { status: 'error', message: 'No file provided' };
4035
return;
4136
}
4237

4338
try {
44-
const d = await readFile(file.filepath);
45-
const buf = await buffer(dataType, d);
46-
await unlink(file.filepath);
39+
40+
const buf = await buffer(dataType, file.buffer);
4741

4842
if (isRemote) {
4943
const response = await uploadFile(url, remoteConfig, buf, dataType);
@@ -71,12 +65,7 @@ export async function createServer(uploadStore: UploadStore) {
7165
}
7266
});
7367

74-
const koaMiddle = koaBody({
75-
multipart: true,
76-
patchKoa: true,
77-
});
78-
79-
app.use(koaMiddle).use(router.routes()).use(router.allowedMethods());
68+
app.use(router.routes()).use(router.allowedMethods());
8069

8170
setHttpCallback(app.callback());
8271
}

game/server/multer.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import originalMulter, { Options, Multer } from 'multer';
2+
3+
export function multer(options: Options): Multer {
4+
const m = originalMulter(options);
5+
6+
makePromise(m, 'any');
7+
makePromise(m, 'array');
8+
makePromise(m, 'fields');
9+
makePromise(m, 'none');
10+
makePromise(m, 'single');
11+
12+
return m;
13+
}
14+
15+
function makePromise(multer: any, name: any): any {
16+
if (!multer[name]) return;
17+
18+
const fn = multer[name];
19+
20+
multer[name] = function () {
21+
const middleware = Reflect.apply(fn, this, arguments);
22+
23+
return async (ctx: any, next: any) => {
24+
await new Promise((resolve, reject) => {
25+
middleware(ctx.req, ctx.res, (err: any) => {
26+
if (err) return reject(err);
27+
if ('request' in ctx) {
28+
if (ctx.req.body) {
29+
ctx.request.body = ctx.req.body;
30+
delete ctx.req.body;
31+
}
32+
33+
if (ctx.req.file) {
34+
ctx.request.file = ctx.req.file;
35+
ctx.file = ctx.req.file;
36+
delete ctx.req.file;
37+
}
38+
39+
if (ctx.req.files) {
40+
ctx.request.files = ctx.req.files;
41+
ctx.files = ctx.req.files;
42+
delete ctx.req.files;
43+
}
44+
}
45+
46+
resolve(ctx);
47+
});
48+
});
49+
50+
return next();
51+
};
52+
};
53+
}
54+
55+
multer.diskStorage = originalMulter.diskStorage;
56+
multer.memoryStorage = originalMulter.memoryStorage;

0 commit comments

Comments
 (0)