Nest: request: expose httpServer to app context

Created on 12 Mar 2018  路  8Comments  路  Source: nestjs/nest

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

I want to be able to access the httpServer from the application context. Specifically, in my case I want to simply register a graphql subscriptions server (I saw the example, but it's too complicated and creates a new server instead of reusing the existing one)

class MyModule implements NestModule {

// ...

configure(consumer: MiddlewaresConsumer) {
  // get schema

    new SubscriptionServer({
      execute,
      subscribe,
      schema
    }, {
      // server: appHttpServer, // ?? how do I get reference to the app server?
      path: '/subscriptions',
    });
core type

Most helpful comment

You can inject HTTP server reference using HTTP_SERVER_REF token. The reference is an HTTP adapter currently used by the application. Each adapter implements HttpServer interface:

@Inject(HTTP_SERVER_REF) httpServerRef: HttpServer

The HTTP_SERVER_REF is exported from @nestjs/core while HttpServer interface from @nestjs/common. Also, this instance exposes getHttpServer() method that allows picking up the underlying object (express instance by default).

All 8 comments

my workaround:

on app creation:

const app = await NestFactory.create(ApplicationModule);

global['nestHttpServer'] = app.getHttpServer();

await app.listen(process.env.PORT);

on configure module:

configure(consumer: MiddlewaresConsumer) {
//...
new SubscriptionServer({
      execute,
      subscribe,
      schema
    }, {
      server: global['nestHttpServer'], // <--  ugly, but will do for now
      path: '/subscriptions',
    });

I think it would be more reasonable for you to expose the app to global.聽馃

@whtiehack, just a workaround... it's bad either way.

I have a suggestion for something that will help in the long term (for this issue and others):

Separate nest dependency injection into an independent module (similar to spring-integration)

than we can have a separate HttpServerModule for express/koa wrapped api (+ observable lifecycle events, such as 'listening'), and another WebServiceModule for current annotation based controllers/pipes features.

I see the 5.0 version provides interface IHttpServer,maybe it can solve your problem.馃槯

You can inject HTTP server reference using HTTP_SERVER_REF token. The reference is an HTTP adapter currently used by the application. Each adapter implements HttpServer interface:

@Inject(HTTP_SERVER_REF) httpServerRef: HttpServer

The HTTP_SERVER_REF is exported from @nestjs/core while HttpServer interface from @nestjs/common. Also, this instance exposes getHttpServer() method that allows picking up the underlying object (express instance by default).

@kamilmysliwiec This won't help: the SubscriptionClient needs the raw HTTP server - using Nest's HttpServer results in the following exception:

TypeError: this.ee.on is not a function
    at Ultron.on (E:\Logistikhelden\src\LHBackend\node_modules\ultron\index.js:42:11)
    at new WebSocketServer (E:\Logistikhelden\src\LHBackend\node_modules\ws\lib\WebSocketServer.js:83:20)
    at new SubscriptionServer (E:\Logistikhelden\src\LHBackend\node_modules\subscriptions-transport-ws\dist\server.js:23:25)
    at SubscriptionsService.createSubscriptionServer (E:\Logistikhelden\src\LHBackend\dist\src\graphql\SubscriptionsService.js:56:35)
    at GraphQLSetupModule.configureGraphQL (E:\Logistikhelden\src\LHBackend\dist\src\graphql\GraphQLSetupModule.js:31:35)
    at GraphQLSetupModule.configure (E:\Logistikhelden\src\LHBackend\dist\src\graphql\GraphQLSetupModule.js:27:14)
    at MiddlewareModule.loadConfiguration (E:\Logistikhelden\src\LHBackend\node_modules\@nestjs\core\middleware\middleware-module.js:37:18)
    at Promise.all.map (E:\Logistikhelden\src\LHBackend\node_modules\@nestjs\core\middleware\middleware-module.js:29:18)
    at Array.map (<anonymous>)
    at MiddlewareModule.resolveMiddleware (E:\Logistikhelden\src\LHBackend\node_modules\@nestjs\core\middleware\middleware-module.js:27:50)
    at MiddlewareModule.register (E:\Logistikhelden\src\LHBackend\node_modules\@nestjs\core\middleware\middleware-module.js:24:20)
    at NestApplication.registerModules (E:\Logistikhelden\src\LHBackend\node_modules\@nestjs\core\nest-application.js:82:37)
    at NestApplication.init (E:\Logistikhelden\src\LHBackend\node_modules\@nestjs\core\nest-application.js:87:20)
    at NestApplication.listen (E:\Logistikhelden\src\LHBackend\node_modules\@nestjs\core\nest-application.js:191:44)
    at exceptions_zone_1.ExceptionsZone.run (E:\Logistikhelden\src\LHBackend\node_modules\@nestjs\core\nest-factory.js:99:48)
    at Function.run (E:\Logistikhelden\src\LHBackend\node_modules\@nestjs\core\errors\exceptions-zone.js:8:13)
    at Proxy.args (E:\Logistikhelden\src\LHBackend\node_modules\@nestjs\core\nest-factory.js:98:54)
    at E:\Logistikhelden\src\LHBackend\dist\src\main.js:37:19
    at Generator.next (<anonymous>)
    at fulfilled (E:\Logistikhelden\src\LHBackend\dist\src\main.js:4:58)
    at <anonymous>
    at process._tickDomainCallback (internal/process/next_tick.js:228:7)

The express-instance is no option either.

@blissi try this.httpServerRef.getHttpServer()

@Injectable()
export class SubscriptionsService implements OnModuleDestroy {
    private subscriptionServer: SubscriptionServer;

    constructor(
        @Inject(HTTP_SERVER_REF) private readonly httpServerRef: HttpServer,
    ) {}

    createSubscriptionServer(
        schema: any,
        options: ServerOptions = {},
        socketOptions: WebSocket.ServerOptions = {},
    ) {
        this.subscriptionServer = new SubscriptionServer(
            {
                execute,
                subscribe,
                schema,
                ...options,
            },
            {
                server: this.httpServerRef.getHttpServer(),
                path: '/subscriptions',
                ...socketOptions,
            },
        );
    }

    onModuleDestroy() {
        this.subscriptionServer.close();
    }
}

See docs about this here https://docs.nestjs.com/faq/http-adapter

Was this page helpful?
0 / 5 - 0 ratings

Related issues

janckerchen picture janckerchen  路  3Comments

rlesniak picture rlesniak  路  3Comments

artaommahe picture artaommahe  路  3Comments

tronginc picture tronginc  路  3Comments

yanshuf0 picture yanshuf0  路  3Comments