Search code examples
nestjs

NestJS: Custom decorator `applyDecorators()` not working with `HttpCode` and `AuthGuard` used together


Scenerio: I have created two custom decorators as a way to cleanup my controllers by applying all the common swagger decorators, at one place. They are as following.

    export function AuthorizedEndpoint(header_key?: string) {
        return applyDecorators(
            // HttpCode(200),  // @Todo Why is it not working?
            UseGuards(AuthGuard),
            ApiBearerAuth(header_key),
            ApiOkResponse({ description: ResponseMessageEnum.R_SUCCESS as string }),
            ApiUnprocessableEntityResponse({ description: ResponseMessageEnum.R_BAD_REQUEST as string }),
            ApiForbiddenResponse({ description: ResponseMessageEnum.R_UNAUTHORIZED as string }),
            ApiNotFoundResponse({ description: ResponseMessageEnum.R_NOT_FOUND as string })

            );
        }

    export function OpenAccessEndpoint() {
        return applyDecorators(
            HttpCode(200),
            ApiOkResponse({ description: ResponseMessageEnum.R_SUCCESS as string }),
            ApiUnprocessableEntityResponse({ description: ResponseMessageEnum.R_BAD_REQUEST as string }),
            ApiForbiddenResponse({ description: ResponseMessageEnum.R_UNAUTHORIZED as string }),
            ApiNotFoundResponse({ description: ResponseMessageEnum.R_NOT_FOUND as string })

            );

All my controllers are POST, and nestjs sends 201 as response code. But I want to send 200 instead. Therefore, I used the @HttpCode(200) to send required response code. It is working when using on controllers directly.

ISSUE:

In the custom decorator, which does not implement AuthGuard, HttpCode decorator is working as expected, but in the Authorized Decorator, If I use @HttpCode decorator, I get the following message. If I comment it out, it works as expected and sends 201 default response.

[11:30:25 AM] File change detected. Starting incremental compilation...

[11:30:25 AM] Found 0 errors. Watching for file changes.


C: \Users\Lenovo\Project\node_modules\reflect - metadata\Reflect.js: 541;
var decorated = decorator(target);
                                ^
    TypeError: Cannot read properties of undefined(reading 'value')
    at C: \Users\Lenovo\Project\node_modules\@nestjs\common\decorators\http\http - code.decorator.js: 17: 87
    at C: \Users\Lenovo\Project\node_modules\@nestjs\common\decorators\core\apply - decorators.js: 17: 17
    at DecorateConstructor(C: \Users\Lenovo\Project\node_modules\reflect - metadata\Reflect.js: 541: 33)
    at Reflect.decorate(C: \Users\Lenovo\Project\node_modules\reflect - metadata\Reflect.js: 130: 24)
    at __decorate(C: \Users\Lenovo\Project\dist\administration\controllers\organization.controller.js: 4: 92)
    at Object.<anonymous>(C: \Users\Lenovo\Project\src\administration\controllers\organization.controller.ts: 14: 37)
    at Module._compile(node: internal / modules / cjs / loader: 1239: 14)
    at Object.Module._extensions..js(node: internal / modules / cjs / loader: 1293: 10)
    at Module.load(node: internal / modules / cjs / loader: 1096: 32)
    at Function.Module._load(node: internal / modules / cjs / loader: 935: 12);

Question: Is this a bug, or some misconfiguration from my end? What is the explaination of above error message? How do I move ahead from it?


Solution

  • Turns out @HttpCode() is a method decorator and therefore cannot be applied to class.

    Therefore either we can not include @HttpCode() in custom decorator, and use it manually on each route method, allowing us to use our custom decorator at class level.

    Or we can include it in our custom decorator, and loose the ability of using the decorator at class level.