I am building a REST API based on express, I want to warn the user when he used the wrong HTTP verb for his request.
Currently, I am adding
app.all('/', (req, res) => {
answer(req, res, {code: 400, error: 'Wrong method'});
});
after each routes, and it is starting to be non negligeable, I d much rather have it at one place, and list all routes I want to listen to this.
Is there a way to do something like:
app.all(['/', '/signup', '/login'], (req, res) => {
answer(req, res, {code: 400, error: 'Wrong method'});
});
so that I only have one point of failure, instead of having to check every route?
Paths can be Regular expressions too, so something along the following should work:
app.all(/(signup|login)/, (req, res) => {
answer(req, res, {code: 400, error: 'Wrong method'});
});
Express uses path-to-regexp for matching the route paths; see the path-to-regexp documentation for all the possibilities in defining route paths. Express Route Tester is a handy tool for testing basic Express routes, although it does not support pattern matching.
You can use /^(signup|login)\/(.+)/. See DOCS
In your case:
app.all(['/^(signup|login)\/(.+)/'], (req, res) => {
answer(req, res, {code: 400, error: 'Wrong method'});
});
You can define a function with your checks on url path and method and use it in a middleware you pass to the app to handle this error situation.
Just define it before your routes.
Here an example:
app.use(function(req, res, next){
if (checkIfIsWrongMethod(req)) {
answer(req, res, {code: 400, error: 'Wrong method'});
} else {
next();
}
});
Here is the expressjs FAQ.
Related
In my node app, I have routes called index and home. While trying to redirect from index to home route it throws the following error:
Error: Can't set headers after they are sent
Here is the code:
app.get('/index', function (req, res) {
res.redirect('/home');
})
app.get('/home', function (req, res) {
res.send('Welcome Home !!');
})
You can try replace '/index' with "/index". It works fine after that.
I'm using NodeJS with Express and when an Endpoint is not found Express returns
I'd like to return a Custom 404 Message instead of the above image whenever an Endpoint is miss-typed.
I've tried adding the following to app.js
app.use(function (req, res, next) {
res.status(404).send("Sorry can't find that!")
})
But this just returns ALL endpoints with
Sorry can't find that!
You need to make that this the last 'route' in app.js
app.use(function (req, res, next) {
res.status(404).send("Sorry can't find that!")
})
The order your specify your routes is important.
I'm getting a Node/Express API ready for production however have some questions/advice need help on:
1 - I'm using the npm package cors - did so for development to basically disable CORS, however now that I'm moving to production I only want certain URLS to be able to reach the API.
So to so this what I've seen is:
var corsOptions = {
origin: 'http://www.example.com',
methods: ['GET', 'POST']
};
app.get('*', cors(corsOptions), function(req, res, next) {
res.json({msg: 'This is CORS-enabled for only example.com.'});
});
However (from what I've seen) I'd need to do this for everyone request type e.g.
app.post('*', cors(corsOptions), function(req, res, next) {
res.json({msg: 'This is CORS-enabled for only example.com.'});
});
app.del('*', cors(corsOptions), function(req, res, next) {
res.json({msg: 'This is CORS-enabled for only example.com.'});
});
Is there an easier way to avoid such duplication?
2 - And the second question - I have a long list of API routes e.g.
router.post('/registerUser', function(req, res) {
...
}
Is it possible to place some kind of 'otherwise' line so that if a route doesn't match anything I've defined i can return something specific?
Thanks.
For first put cors as a middleware before your first route.
app.use(cors(corsOptions));
//routes down below
Explanation: Cors will be set for all the routes below for every request. As this middleware will be executed first.
For second put your otherwise or 404 route after your last route.
app.use((req,res,next)=>{
//Your message
res.send('Page Not Found');
});
Explanation: If any route will not be matched then this route will trigger.
Real simple question guys: I see a lot of books/code snippets use the following syntax in the router:
app.use('/todos/:id', function (req, res, next) {
console.log('Request Type:', req.method);
next();
});
I'm not sure how to interpret the route here... will it route '/todos/anything'? and then grab the 'anything' and treat is at variable ID? how do I use that variable? I'm sure this is a quick answer, I just haven't seen this syntax before.
This is an express middleware.
In this case, yes, it will route /todos/anything, and then req.params.id will be set to 'anything'
On your code, that is for express framework middleware, if you want to get any id in the server code using that route, you will get that id by req.params.id.
app.use('/todos/:id', function (req, res, next) {
console.log('Request Id:', req.params.id);
next();
});
Route path: /student/:studentID/books/:bookId
Request URL: http://localhost:xxxx/student/34/books/2424
req.params: { "studentID": "34", "bookId": "2424" }
app.get('/student/:studentID/books/:bookId', function (req, res) {
res.send(req.params);
});
Similarly for your code:
Route path: /todos/:id
Request URL: http://localhost:xxxx/todos/36
req.params: { "id": "36" }
app.use('/todos/:id', function (req, res, next) {
console.log('Request Id:', req.params.id);
next();
});
Yes, in your example youl get req.params.id set to 'anything'
A bit late to the party but the question mark in your question made me think of something that hasn't been touched upon.
If your route had a question mark after the id like so: '/todos/:id?', id would be an optional parameter, meaning you could do a getAll() if id was omitted (and therefore undefined).
This is called Path params and it's used to identify a specific resource.
and as all answer how to get the value of the path params
app.use('/todos/:id', function (req, res) {
console.log('Request Id:', req.params.id); // 'anything'
});
read more about params type
https://swagger.io/docs/specification/describing-parameters/
While coding my app, I sometimes had a little mishap when typing my URLs in the browser, and thus sometimes got the error message:
Cannot GET /some/route
Which was true, since the route may was not defined.
But since this app is planned to enter production, I kinda don't want to use this flat message as my "error page".
Looking into the Express 4 docs, they tell me to .use() a middleware with 4 arguments. I did that. But I'd still get this issue...
Turns out that this message comes from the finalhandler module and my bet is, that this middleware comes before my error-catching, 4-argument middleware.
Here is a basic express app that I threw together while trying to find a solution:
var app = require("express")();
app.use("/yo", function(req, res, next){
res.send("Yo!");
});
app.use(function(error, req, res, next){
res.send("An error: "+error);
console.log(error);
});
app.listen(10000);
Accessing /yo works. But, / or /derp yields the Cannot GET message instead of my little middleware.
So, how is this done correctly, now?
The error middleware is only for actual errors, such as a middleware or route handler throwing an exception or passing an error to next().
If you want to provide a route handler for requests that do not match any existing routes, then just add a middleware after all of your app's routes/middleware like:
var app = require("express")();
app.use("/yo", function(req, res, next){
res.send("Yo!");
});
app.use(function(req, res, next) {
res.send('Could not route your request!');
});
app.use(function(error, req, res, next){
res.send("An error: "+error);
console.log(error);
});
app.listen(10000);