Skip to content

Commit f850ae8

Browse files
yidongwAlan Wang
and
Alan Wang
authored
CLS Context is lost after using multer middleware (#695)
related issue: expressjs/multer#814 Used the solution described in the above link to fix the issue Co-authored-by: Alan Wang <[email protected]>
1 parent d7a3345 commit f850ae8

File tree

1 file changed

+49
-42
lines changed

1 file changed

+49
-42
lines changed

src/middlewares/openapi.multipart.ts

+49-42
Original file line numberDiff line numberDiff line change
@@ -20,51 +20,58 @@ export function multipart(
2020
): OpenApiRequestHandler {
2121
const mult = multer(options.multerOpts);
2222
const Ajv = createRequestAjv(apiDoc, { ...options.ajvOpts });
23-
return (req, res, next) => {
23+
return async (req, res, next) => {
2424
// TODO check that format: binary (for upload) else do not use multer.any()
2525
// use multer.none() if no binary parameters exist
2626
if (shouldHandle(Ajv, req)) {
27-
mult.any()(req, res, (err) => {
28-
if (err) {
29-
next(error(req, err));
30-
} else {
31-
// TODO:
32-
// If a form parameter 'file' is defined to take file value, but the user provides a string value instead
33-
// req.files will be empty and req.body.file will be populated with a string
34-
// This will incorrectly PASS validation.
35-
// Instead, we should return a 400 with an invalid type e.g. file expects a file, but found string.
36-
//
37-
// In order to support this, we likely need to inspect the schema directly to find the type.
38-
// For example, if param with type: 'string', format: 'binary' is defined, we expect to see it in
39-
// req.files. If it's not present we should throw a 400
40-
//
41-
// This is a bit complex because the schema may be defined inline (easy) or via a $ref (complex) in which
42-
// case we must follow the $ref to check the type.
43-
44-
if (req.files) {
45-
// to handle single and multiple file upload at the same time, let us this initialize this count variable
46-
// for example { "files": 5 }
47-
const count_by_fieldname = (<Express.Multer.File[]>req.files)
48-
.map((file) => file.fieldname)
49-
.reduce((acc, curr) => {
50-
acc[curr] = (acc[curr] || 0) + 1;
51-
return acc;
52-
}, {});
53-
54-
// add file(s) to body
55-
Object.entries(count_by_fieldname).forEach(
56-
([fieldname, count]: [string, number]) => {
57-
// TODO maybe also check in the api doc if it is a single upload or multiple
58-
const is_multiple = count > 1;
59-
req.body[fieldname] = is_multiple
60-
? new Array(count).fill('')
61-
: '';
62-
},
63-
);
64-
}
65-
next();
66-
}
67-
});
27+
try {
28+
await new Promise<void>((resolve, reject) => {
29+
mult.any()(req, res, (err) => {
30+
if (err) {
31+
reject(error(req, err));
32+
} else {
33+
// TODO:
34+
// If a form parameter 'file' is defined to take file value, but the user provides a string value instead
35+
// req.files will be empty and req.body.file will be populated with a string
36+
// This will incorrectly PASS validation.
37+
// Instead, we should return a 400 with an invalid type e.g. file expects a file, but found string.
38+
//
39+
// In order to support this, we likely need to inspect the schema directly to find the type.
40+
// For example, if param with type: 'string', format: 'binary' is defined, we expect to see it in
41+
// req.files. If it's not present we should throw a 400
42+
//
43+
// This is a bit complex because the schema may be defined inline (easy) or via a $ref (complex) in which
44+
// case we must follow the $ref to check the type.
45+
46+
if (req.files) {
47+
// to handle single and multiple file upload at the same time, let us this initialize this count variable
48+
// for example { "files": 5 }
49+
const count_by_fieldname = (<Express.Multer.File[]>req.files)
50+
.map((file) => file.fieldname)
51+
.reduce((acc, curr) => {
52+
acc[curr] = (acc[curr] || 0) + 1;
53+
return acc;
54+
}, {});
55+
56+
// add file(s) to body
57+
Object.entries(count_by_fieldname).forEach(
58+
([fieldname, count]: [string, number]) => {
59+
// TODO maybe also check in the api doc if it is a single upload or multiple
60+
const is_multiple = count > 1;
61+
req.body[fieldname] = is_multiple
62+
? new Array(count).fill('')
63+
: '';
64+
},
65+
);
66+
}
67+
resolve();
68+
}
69+
});
70+
});
71+
next()
72+
} catch (error) {
73+
next(error);
74+
}
6875
} else {
6976
next();
7077
}

0 commit comments

Comments
 (0)