Nest: Middleware : DI not working

Created on 15 Sep 2018  路  7Comments  路  Source: nestjs/nest

I'm submitting a...


[x] Bug report
[x] Documentation issue or request
## Current behavior Dependency injection is not working inside a middleware, app is not starting with following error :

web_1    | (node:819) UnhandledPromiseRejectionWarning: Error: Nest can't resolve dependencies of the undefined (?). Please make sure that the argument at index [0] is available in the current context.
web_1    |     at Injector.lookupComponentInExports (/app/node_modules/@nestjs/core/injector/injector.js:146:19)
web_1    |     at process._tickCallback (internal/process/next_tick.js:178:7)
web_1    |     at Function.Module.runMain (internal/modules/cjs/loader.js:721:11)
web_1    |     at Object. (/app/node_modules/ts-node/src/bin.ts:157:12)
web_1    |     at Module._compile (internal/modules/cjs/loader.js:678:30)
web_1    |     at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10)
web_1    |     at Module.load (internal/modules/cjs/loader.js:589:32)
web_1    |     at tryModuleLoad (internal/modules/cjs/loader.js:528:12)
web_1    |     at Function.Module._load (internal/modules/cjs/loader.js:520:3)
web_1    |     at Function.Module.runMain (internal/modules/cjs/loader.js:719:10)

Expected behavior

As mentioned in the official documentation DI should work

Minimal reproduction of the problem with instructions

HttpLoggerMiddleware

import { Injectable, MiddlewareFunction, NestMiddleware, LoggerService } from '@nestjs/common';

@Injectable()
export class HttpLoggerMiddleware implements NestMiddleware {
  constructor(private readonly logger: LoggerService) {}

  resolve(...args: any[]): MiddlewareFunction {
    return (req, res, next) => {
        this.logger.log(res);

        next();
    };
  }
}


UtilsModule

import { Module, Global, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
import { LoggerService } from './services/logger.service';
import { HttpLoggerMiddleware } from './middlewares/http-logger.middleware';

@Global()
@Module({
  providers: [LoggerService],
  exports: [LoggerService],
})
export class UtilsModule {
    configure(consumer: MiddlewareConsumer) {
        consumer
            .apply(HttpLoggerMiddleware)
            .forRoutes({ path: '*', method: RequestMethod.ALL });
    }
}


LoggerService


import { Injectable } from '@nestjs/common';

@Injectable()
export class LoggerService {
    log(message: string) {
         console.debug(message);
    }   
}

Others:

Code example is obviously a simplified version of the my project, the original goal is to have a custom http logger to send request in a precise format to ELK (gelf).
Middleware is working as soon as i remove the dependency to my LoggerService
In the case that i did something wrong, i think it can be great to add a working example of the DI in the middleware section of the documentation

Most helpful comment

Notice that:

import { Injectable, MiddlewareFunction, NestMiddleware, LoggerService } from '@nestjs/common';

and

import { LoggerService } from './services/logger.service';

are different (you are trying to inject LoggerService interface from common package)

All 7 comments

You have to inject your dependencies into the HttpLoggerMiddleware somewhere. You could try to use an inject token for your LoggerService. I am not sure how the dependency injection inside of a module (instead of a service) works, but personally I'd try to use an inject token in the constructor of your middleware

This is exactly what i'm doing with constructor(private readonly logger: LoggerService) {} from HttpLoggerMiddleware
As Logger service is declared as a provider & exported i don't understand why its not working. Same "setup" is working for controllers, services... just not working for middlewares

I don't see any usage of Inject tokens in your pasted code using @Inject()

As I already said: The context is different because you are trying to inject dependencies in a module and not in a service

@kamilmysliwiec

don't think thats a duplicate i'm using target: es6

{ "compilerOptions": { "module": "commonjs", "declaration": true, "noImplicitAny": false, "removeComments": true, "noLib": false, "allowSyntheticDefaultImports": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "target": "es6", "sourceMap": true, "outDir": "./dist", "baseUrl": "./src" }, "include": [ "src/**/*" ], "exclude": [ "node_modules", "**/*.spec.ts" ] }

And my projects deps :

"dependencies": { "@nestjs/common": "^5.1.0", "@nestjs/core": "^5.1.0", "@nestjs/mongoose": "^5.2.2", "dotenv": "^6.0.0", "mongoose": "^5.2.14", "reflect-metadata": "^0.1.12", "rxjs": "^6.2.2", "typescript": "^3.0.1", "winston": "^3.1.0" },

Notice that:

import { Injectable, MiddlewareFunction, NestMiddleware, LoggerService } from '@nestjs/common';

and

import { LoggerService } from './services/logger.service';

are different (you are trying to inject LoggerService interface from common package)

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

anyx picture anyx  路  3Comments

KamGor picture KamGor  路  3Comments

tronginc picture tronginc  路  3Comments

FranciZ picture FranciZ  路  3Comments

mishelashala picture mishelashala  路  3Comments