[ ] 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',
});
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
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 implementsHttpServer
interface:The
HTTP_SERVER_REF
is exported from@nestjs/core
whileHttpServer
interface from@nestjs/common
. Also, this instance exposesgetHttpServer()
method that allows picking up the underlying object (express instance by default).