Hi, i've tried all now:
How do you mount an app in this framework? It's the most simple thing in express app.use(otherApp).
As I understand Middlewares are supposed to be just that, but with more nest features. So i try consumer.apply(mySubApp).forRoutes({path: '/', method: RequestMethod.ALL }); in my AppModule but it doesn't work. Help would be appreciated!
Is it possible to just inject the express app into the module? To bypass some of the magic?
Hi @Kamshak,
Could you share your module file? 馃槂
sure
import { AppSettings } from './app.settings';
import { DeploymentController } from './deployment/deployment.controller';
import { KubernetesComponent } from './kubernetes.component';
import { Module, MiddlewaresConsumer, RequestMethod, HttpStatus } from '@nestjs/common';
import { PrerenderComponent } from './prerender/prerender.component';
import { SiteDeploymentComponent } from './deployment/site-deployment.component';
import { MetaController } from './meta.controller';
import { HttpException } from '@nestjs/core';
import { ArenaController } from './arena.module';
import * as Arena from 'bull-arena';
import { Observable } from 'rxjs';
import { interval } from "rxjs/observable/interval";
import { flatMap, map } from "rxjs/operators";
import * as express from 'express';
@Module({
modules: [],
components: [
KubernetesComponent,
PrerenderComponent,
SiteDeploymentComponent,
AppSettings
],
controllers: [
DeploymentController,
MetaController,
ArenaController
],
exports: [ KubernetesComponent ]
})
export class ApplicationModule {
arena: express.Application;
constructor(
private appSettings: AppSettings,
private kube: KubernetesComponent
) {
this.arena = Arena({}, { disableListen: true });
const queueNames$ = interval(500).pipe(
flatMap(() => this.kube.batchApi.listNamespacedJob(this.appSettings.kubernetes.namespace, null, null, null, null, "prerender-queue.type=worker")),
map(result => result.body.items.map(item => {
item.metadata.labels['prerender-queue.queue-name']
}))
).subscribe(queueList => {
const queueConfig = queueList.map(queueName => ({
type: 'bee',
name: queueName,
url: this.appSettings.redisClient
}));
this.arena.locals.Queues.setConfig(queueConfig);
});
}
configure(consumer: MiddlewaresConsumer) {
consumer.apply((req, res, next) => {
if (req.query.apiKey === this.appSettings.apiKey) {
next();
} else {
next(new HttpException('Unauthorized', HttpStatus.UNAUTHORIZED));
}
}).forRoutes({ path: '/deployments', method: RequestMethod.ALL });
consumer.apply(this.arena).forRoutes({path: '/', method: RequestMethod.ALL });
}
}
@Kamshak let's try to move all the code from constructor to configure
Doesn't change it unfortunately. In the end it just creates the app in constructor then applies it a bit further down.
What I've done for now is just put the app as a static member and initialize it in the constructor (since i need some DI things to configure it). I then mount it in server.ts where the app is bootstrapped. Not pretty but it works.
Still wonder why it doesn't work as normal middleware, any clue? You can test this quite easily by simply doing something like
const app = express.app();
app.get('/hello', (req, res) => res.send("hello world"));
consumer.apply(app).forRoutes({path: '/', method: RequestMethod.ALL });
Now NestApplication provides a set of wrappers around express native methods like use() or set().
@kamilmysliwiec
Now
NestApplicationprovides a set of wrappers around express native methods likeuse()orset().
I'm using app.use method to mount Arena as middleware but it hangs and app.listen is never reached.
This looks like a bug. Could you take it a look? thanks Kamil.
My code:
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import * as helmet from 'helmet';
import * as bodyParser from 'body-parser';
import * as compression from 'compression';
import * as rateLimit from 'express-rate-limit';
import * as Sentry from '@sentry/node';
import Arena from 'bull-arena';
import { AppModule } from './modules/app/app.module';
import { Logger } from './common/logger';
import APP_CONFIG from './modules/app/app.config';
const logger = new Logger('Bootstrap');
const { PORT, HOST, SENTRY_DSN, APP_MODE, SERVER_NAME } = APP_CONFIG;
async function bootstrap() {
Sentry.init({
dsn: SENTRY_DSN,
environment: APP_MODE,
serverName: SERVER_NAME,
});
const app = await NestFactory.create<NestExpressApplication>(AppModule);
app.enableCors();
app.use(helmet());
app.use(compression());
app.use(bodyParser.json({ limit: '1mb' }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(new rateLimit({ max: 1000, windowMs: 15 * 60 * 1000 }));
app.use(
'/bull-arena',
Arena(
{
queues: [
{
name: 'queue',
hostId: 'Worker',
port: 6381,
host: '127.0.0.1',
},
],
},
{
disableListen: true,
},
),
);
await app.listen(PORT, HOST, () => {
logger.info(`listening on ${HOST}:${PORT}`);
});
}
bootstrap();
@alfonmga try to add basePath option in the listening object
it'll looks like :
app.use(
'/bull-arena',
Arena(
{
queues: [
{
name: 'queue',
hostId: 'Worker',
port: 6381,
host: '127.0.0.1',
},
],
},
{
basePath: '/'
disableListen: true,
},
),
);
Now you you should be able to access you arena dashboard from '/bull-arena/' unless there is
other problem e.g redis connection not correctly configured.
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.
Most helpful comment
Now
NestApplicationprovides a set of wrappers around express native methods likeuse()orset().