Nest: [Question or Feature Request] 404 error handling or sendFile on non existed route

Created on 10 Dec 2017  路  18Comments  路  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.

Current behavior


How to handle 404 when route not existed or how to sendFile on non existed routes?

Expected behavior


I want to handle 404 not found properly. In pure express application I just add (after all routes):

  server.get('*', function (req, res) {
    res.send('not found');
  });

and it's works for all routes except previously defined by other routes. When I request non defined route I got 'not found'.

Minimal reproduction of the problem with instructions


I found a solution how to implement what I need, but it's not a _'Nest' way_:

import * as http from 'http';
import * as express from 'express';

import { NestFactory } from '@nestjs/core';
import { ApplicationModule } from './modules/app.module';

const server = express();

async function bootstrap() {

  const app = await NestFactory.create(ApplicationModule, server);
  await app.init();

  http.createServer(server).listen(3000);

  server.get('*', function (req, res) {
    res.send('Not Found');
  });
}
bootstrap();

What is the motivation / use case for changing the behavior?

I want to implement that in Nest Way. I want to possibility to create some controller with '*' which can be loaded as latest route controller for catching all non existed requests for handling 404 or for sendFile aka static for frontend:

  // catch all unused routes to serve frontend
  server.get('*', function (req, res) {
    res.sendFile(path.join(__dirname, '../dist/index.html'));
  });

Environment


Nest version: 4.4.2


For Tooling issues:
- Node version: 8.9.0
- Platform:  Mac

Others:

type

Most helpful comment

If someone interested about how to do it.

not-found-exception.filter.ts:

import * as path from 'path';
import { ExceptionFilter, Catch, NotFoundException } from '@nestjs/common';
import { HttpException } from '@nestjs/core';

@Catch(NotFoundException)
export class NotFoundExceptionFilter implements ExceptionFilter {
  catch(exception: NotFoundException, response) {
    response.sendFile(path.join(__dirname, '../../../../dist/index.html'));
  }
}

server.ts

async function bootstrap() {
  const app = await NestFactory.create(ApplicationModule);
  app.useGlobalFilters(new NotFoundExceptionFilter());
  await app.listen(3000);
}
bootstrap();

All 18 comments

You can use an interceptor to check if a response was sent back, and if it wasn't, send the error.

@wbhob Main reason is to sendFile for all not existed routes.

There isn't a good 'nest way' to do this because it maps all the URLs before the requests are instantiated, so there isn't an apparent hierarchy. You could try to maybe make a controller with the route * and make it the VERY last controller in your array.

How I can do it as very last controller?

Just make it the last one in your controllers array

@wbhob hope, I understand you, but I use modules. Each Module contain routes for example: /cars routes in CarsModule and /drivers in DriversModule.

I test your solution, and it works, but because I use modules, I need dedicated module and controller for it for using it as last module in app.module modules array. Thanks. Will be good if someone add that solution to documentation because too many people want to use Nest for API and also serve frontend on all unused routes (for example angular).

Hi @pumano,
In the nearest update, Nest will throw NotFoundException when the non-existed route would be called. You'll be able to catch this exception in the exception filter, thus you can sendFile to the user then. Does it cover your requirements :)?

This is not the place for this type of question @ToporDon. please open a new issue, or better yet, as on Gitter.

@kamilmysliwiec good idea! Thank you!

Also will be good if you add docs (or I can help with it via pull request) about that NotFoundException and examples about how to catch NotFoundException and how to serve frontend via sendFile on NotFoundException. Hope it will be useful for Nest users.

Hi @pumano,
Let's update your package into 4.5.0. I'll update the docs as soon as possible 馃檪

If someone interested about how to do it.

not-found-exception.filter.ts:

import * as path from 'path';
import { ExceptionFilter, Catch, NotFoundException } from '@nestjs/common';
import { HttpException } from '@nestjs/core';

@Catch(NotFoundException)
export class NotFoundExceptionFilter implements ExceptionFilter {
  catch(exception: NotFoundException, response) {
    response.sendFile(path.join(__dirname, '../../../../dist/index.html'));
  }
}

server.ts

async function bootstrap() {
  const app = await NestFactory.create(ApplicationModule);
  app.useGlobalFilters(new NotFoundExceptionFilter());
  await app.listen(3000);
}
bootstrap();

Thanks for sharing @pumano! 馃檪

Hi, @pumano, do you use app.setGlobalPrefix?

When I use it, this solution doesnt work, but without global prefix its works

@silvelo, no, I don't use app.setGlobalPrefix. maybe it's bug?

Yes, maybe global configs make that issue.

Actually, it's not a bug. The setGlobalPrefix mounts the Nest application on the applied 'global path'. You have to look forward for this RouterModule https://github.com/nestjs/nest/issues/255

So at the moment I have two options:

  • Use the old way.
  • Delete global prefix.

Because my NestApplication doesnt response to any url wihtout that prefix.

Thanks @kamilmysliwiec

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

breitsmiley picture breitsmiley  路  3Comments

menme95 picture menme95  路  3Comments

artaommahe picture artaommahe  路  3Comments

KamGor picture KamGor  路  3Comments

VRspace4 picture VRspace4  路  3Comments