#javascript #node.js #typescript #nestjs
#javascript #node.js #typescript #nestjs
Вопрос:
NestJS использует проверку с помощью каналов проверки и
@UsePipes(ValidationPipe)
Если это не удается, выдается исключение. Это нормально для REST API, которые возвращают JSON.
Как можно проверить параметры при использовании рендеринга HTML и вернуть
{ errors: ['First error'] }
для шаблона hbs?
Комментарии:
1. Есть ли у вас один шаблон ошибки hbs, который вы хотите отобразить при ошибках, или ошибка должна отображаться в шаблоне hbs маршрута?
2. Ошибки должны отображаться в шаблоне hbs (в форме).
Ответ №1:
Вы можете создать Interceptor
, который преобразует ошибку проверки в ответ на ошибку:
@Injectable()
export class ErrorsInterceptor implements NestInterceptor {
intercept(
context: ExecutionContext,
call$: Observable<any>,
): Observable<any> {
return call$.pipe(
// Here you can map (or rethrow) errors
catchError(err => ({errors: [err.message]}),
),
);
}
}
Вы можете использовать его, добавив @UseInterceptors(ErrorsInterceptor)
в свой контроллер или его методы.
Ответ №2:
Я сводил себя с ума, пытаясь найти «гнездовой» способ сделать это, сохраняя при этом некоторую степень настраиваемости, и я думаю, что наконец-то у меня это получилось. Во-первых, нам нужна ошибка, которая имеет ссылку на существующие class-validator
ошибки, поэтому мы создаем пользовательский класс ошибок следующим образом:
import { ValidationError } from 'class-validator';
export class ValidationFailedError extends Error {
validationErrors: ValidationError[];
target: any;
constructor(validationErrors) {
super();
this.validationErrors = validationErrors;
this.target = validationErrors[0].target
}
}
(У нас также есть ссылка на класс, который мы пытались проверить, поэтому мы можем вернуть наш объект соответствующим образом)
Затем, в main.ts
, мы можем установить пользовательскую фабрику исключений следующим образом:
app.useGlobalPipes(
new ValidationPipe({
exceptionFactory: (validationErrors: ValidationError[] = []) => {
return new ValidationFailedError(validationErrors);
},
}),
);
Далее мы создаем ExceptionFilter
, чтобы перехватить нашу пользовательскую ошибку, вот так:
@Catch(ValidationFailedError)
export class ValidationExceptionFilter implements ExceptionFilter {
view: string
objectName: string
constructor(view: string, objectName: string) {
this.view = view;
this.objectName = objectName;
}
async catch(exception: ValidationFailedError, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
response.render(this.view, {
errors: exception.validationErrors,
[this.objectName]: exception.target,
url: request.url,
});
}
}
Мы также добавляем инициализатор, чтобы мы могли указать, какой вид отображать и каково имя объекта, чтобы мы могли настроить наш фильтр для метода контроллера следующим образом:
@Post(':postID')
@UseFilters(new ValidationExceptionFilter('blog-posts/edit', 'blogPost'))
@Redirect('/blog-posts', 301)
async update(
@Param('id') postID: string,
@Body() editBlogPostDto: EditBlogPostDto,
) {
await this.blogPostsService.update(postID, editBlogPostDto);
}
Надеюсь, это поможет некоторым людям, потому что мне нравится NestJS, но, похоже, документация и руководства гораздо лучше настроены для JSON API, чем для более традиционных CRUD-приложений с полным стеком.