Open hgranlund opened 3 years ago
The same issue!
I am having a similar issue. However, I am trying to setup @body to accept a json object from the request, but reject if an array is passed. So far it will run validation on the request body if a json object is passed, but not run validation if an array is passed.
example:
public async exampleFunction(
@Body({ required: true }) requestBody: RequestValidator
)
@NoNameProvided I believe this is similar to Issue 371
Any updates on this?
any update ?
This is I think a typescript limitation at the moment. Reflector is not capable of returning the subtypes, it only emits that your type is an array, which is not enough for class-transformer to instantiate your desired target class. There could a solution to add the type
parameter yes, but that will not solve primitive values. Since we cannot define types in the type
option, you won't be able to indicate your subtype for primitve arrays.
This is a bit tricky question since class-validator won't run for primitive types without an encapsulating class anyway.
I think we have two ways to tackle this:
Personally I would go with scenario 1.
@NoNameProvided Any thoughts on this?
Running into the same issue as @manofteal mentions. When passing an array (which I don't want), it gets passed to my controller method, unvalidated. Any update on this?
Edit: @attilaorosz I checked your two potential solutions, but shouldn't we just disable passing arrays as a body? Nest does it that way, because like you mentioned, it's a TS issue.
I had the same issue and was able to fix it by using this hack.
.data
property. So for the controller this is what the body would look like.
{
data: [{ ... }, { ... }]
}
class
and puts it as the type of its data
property. We need this as routing-controllers cannot use Generics to deduce the correct type.Let's see some code.
import bodyParser from 'body-parser';
import { NextFunction, Request, RequestHandler, Response } from 'express';
import {
BadRequestError,
ExpressMiddlewareInterface,
Middleware
} from 'routing-controllers';
import { Service } from 'typedi';
@Middleware({ type: 'before' }) @Service() class TransformArrayBody implements ExpressMiddlewareInterface { use(request: Request, response: Response, next: NextFunction): void { const json: RequestHandler = bodyParser.json(); json(request, response, () => { if (!request.body || !(request.body instanceof Array)) { return next( new BadRequestError( 'Body is invalid. Please send a valid array body.' ) ); } request.body = { data: request.body }; if (next instanceof Function) { return next(); } }); } }
export default TransformArrayBody;
* The HOC and the class blueprint it returns (That's `RequestDto<T>`).
```ts
import { Type } from 'class-transformer';
import { ValidateNested } from 'class-validator';
// Class to annotate our request body.
class RequestDto<T> {
data: T;
}
// HOC to create a dynamic class based on a class that is passed to it. This class has a "data" property which matches structure of one array item.
function CreateRequestDto<Impl, Arg>(
Class: new (arg?: Arg) => Impl
): new (arg?: Arg) => RequestDto<Impl> {
class Dto {
@Type(() => Class)
@ValidateNested()
data: Impl;
}
return Dto;
}
export { CreateRequestDto, RequestDto };
@UseBefore(TransformArrayBody)
async put(
@Body({
type: CreateRequestDto(MyClass),
required: true
})
body: RequestDto<MyClass[]>,
@Req() req: Request
): Promise<void> {
console.log(body.data); // data has the original array that the client sent which completely typed and validated! :)
}
Description
Body of type array is not validated.
Minimal code-snippet showcasing the problem
Expected behavior
The body should have been validated
Actual behavior
The body is not validated