Hi @pleerock !
I have a angular application consuming a nodejs API written with routing-controllers. I need a catch all route to send the angular app for all routes not mapped but I get headers are already sent error. In order to avoid this situation I check if headers are already sent before sending the actual html.
import './api/controllers/public.controller'
import './api/misc/util.controller'
let app = express();
app.use(cors());
app.use(cookieParser(COOKIE_SALT))
app.use(bodyParser.json())
app.use(bodyParser.text({ limit: '50mb' }))
app.use(bodyParser.urlencoded({ extended: true }))
app.use(compress({}))
app.use(express.static(path.join(__dirname, '../public')));
let html = fs.readFileSync(path.join(__dirname, '../public/index.html'))
useExpressServer(app);
app.get('*', (req, res) => {
if (!res.headersSent) {
res.setHeader('Content-Type', 'text/html');
res.end(html)
}
});
app.listen(config.port);
Can this headerSent check be avoided ?
You can create a wildcard route for it in the last registered controller not?
Yes I can but I would like to have it here in server initialisation since it is a special route (kind of 404). And if the controllers are loaded automatically I do not know which is the last registered controller.
I was thinking of a configuration option like this:
createExpressServer({
catchAll: (req, res) => {
res.send(`This route is not defined`)
}
})
You can add them via class name that way you will know the order, e.g.: [UserCtr, ProductCtrl, WildcardCtrl]also you can disable the default error handler and write your own which will serve the data from your public directory if the specified path map to an existing file.
Sure it can be done but is also a workaround. I will keep my workaround for now. I tried the error handling approach and it does not seem to work (I'm using version 0.6.12)
You need to disable default exception handler (see readme how to do that) and create standard express error middleware. This should work for you.
I am closing this issue as it looks like it's solved. If you have more question, @alexproca, feel free to reopen.
If anyone is still interesting in a solution. Just create a Middleware like this (typescript).
import {ExpressMiddlewareInterface, Middleware} from "routing-controllers";
@Middleware({ type: "after" })
export class CatchAllRoutes implements ExpressMiddlewareInterface {
use(request: any, response: any, next: (err?: any) => any): any {
if (!response.headersSent) {
response.status(200).send("OK"); // change this to do your stuff.
}
next();
}
}
@leroy0211 i have exactly the same issue right now with my angular 7 app served via express in production. Although the routes get lazy loaded and my catch all route is always registered before them.
Is that middleware check with
if (!response.headersSent)
really a save way to serve the angular index.html file there?
Or should i really just add a route for @Get(*) in my last registered controller. That design smells.
This issue 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
If anyone is still interesting in a solution. Just create a Middleware like this (typescript).