Lester
Lester

Reputation: 750

How can I get all the routes (from all the modules and controllers available on each module) in Nestjs?

Using Nestjs I'd like to get a list of all the available routes (controller methods) with http verbs, like this:

API:
      POST   /api/v1/user
      GET    /api/v1/user
      PUT    /api/v1/user

It seems that access to express router is required, but I haven found a way to do this in Nestjs. For express there are some libraries like "express-list-routes" or "express-list-endpoints".

Thanks in advance!

Upvotes: 27

Views: 36985

Answers (6)

oviniciusfeitosa
oviniciusfeitosa

Reputation: 1065

main.ts

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
  const server = app.getHttpAdapter().getInstance();
  const router = server.router;

  const availableRoutes: [] = router.stack
    .map(layer => {
      if (layer.route) {
        return {
          route: {
            path: layer.route?.path,
            method: layer.route?.stack[0].method,
          },
        };
      }
    })
    .filter(item => item !== undefined);
  console.log(availableRoutes);
}
bootstrap();

Upvotes: 38

Victor Dev
Victor Dev

Reputation: 11

In NestJS 10, you can do it like this:

constructor(
private readonly _discoveryService: DiscoveryService,
private readonly _reflector: Reflector){}

private async getAllEndpoints(): Promise<void> {
const getRoutes = [];
const controllers = this._discoveryService.getControllers();
controllers.forEach(wrappper => {
  const { instance } = wrappper;
  if (instance) {
    const controllerPath = this._reflector.get<string>(PATH_METADATA, instance.constructor);
    const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(instance));
    methods.forEach(methodName => {
      const methodHandler = instance[methodName];
      const methodPath = this._reflector.get<string>(PATH_METADATA, methodHandler);
      const requestMethod = this._reflector.get<RequestMethod>(METHOD_METADATA, methodHandler);
      const baseUri = `${controllerPath}  `;
      const method = RequestMethod[requestMethod];
      if (method) {
        getRoutes.push({
          path: methodPath == '/' ? baseUri : `${baseUri}/${methodPath}`,
          method: method,
        });
      }
    });
  }
});
}

Output

[  
   { path: 'auth/login', method: 'POST' },
   { path: 'auth/password/change', method: 'PATCH' }
]

Upvotes: 1

Jess&#233; Correia
Jess&#233; Correia

Reputation: 67

It works perfectly:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as expressListRoutes from 'express-list-routes';

async function getApp() {
  const app = await NestFactory.create(AppModule);

  await app.listen(3000);

  expressListRoutes(app.getHttpServer()._events.request._router);

  return app;
}

getApp();

Output:

[Nest] 11619  - 10/03/2022 19:53:56     LOG [NestApplication] Nest application successfully started +3ms
GET      /ui
GET      /ui-json
GET      /
GET      /api/v1/auth

Upvotes: -1

sonidelav
sonidelav

Reputation: 111

import { Controller, Get, Request } from "@nestjs/common";
import { Request as ExpressRequest, Router } from "express";

...

@Get()
root(@Request() req: ExpressRequest) {
    const router = req.app._router as Router;
    return {
        routes: router.stack
            .map(layer => {
                if(layer.route) {
                    const path = layer.route?.path;
                    const method = layer.route?.stack[0].method;
                    return `${method.toUpperCase()} ${path}`
                }
            })
            .filter(item => item !== undefined)
    }
}

...
{
    "routes": [
        "GET /",
        "GET /users",
        "POST /users",
        "GET /users/:id",
        "PUT /users/:id",
        "DELETE /users/:id",
    ]
}

Upvotes: 11

ekhodzitsky
ekhodzitsky

Reputation: 153

In Nest every native server is wrapped in an adapter. For those, who use Fastify:

// main.ts

app
    .getHttpAdapter()
    .getInstance()
    .addHook('onRoute', opts => {
      console.log(opts.url)
    })

More about fastify hooks here.

Upvotes: 8

Lester
Lester

Reputation: 750

I just found that Nestjs app has a "getHttpServer()" method, with this I was able to access the "router stack", here's the solution:

// main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as expressListRoutes from 'express-list-routes';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableCors();
  await app.listen(3000);


  const server = app.getHttpServer();
  const router = server._events.request._router;
  console.log(expressListRoutes({}, 'API:', router));

}
bootstrap();

Nestjs available routes!

Upvotes: 12

Related Questions