So i have an express app and in the app.js i have this:
app.use('/index', function (req, res, next){
res.sendFile(__dirname+'/index.html');
}
app.get('/script.js',function(req,res){
res.sendFile(__dirname+'/public/script.js');
and after starting the server and type localhost:3000/index and the app works fine but here comes the problem..
when i change the first app.use() function to:
app.use('/', function (req, res, next){}
so that i don't have to type the index part in the URL, all the next get requests respond with index.html page and i tried adding
res.end(); after res.sendFile();
but no other response gets sent after that, how can i solve?
Your / route is acting as a wildcard and capturing all requests, which means that anything not matching a route defined BEFORE this route will be caught by it. You have two options here:
Change app.use to app.get so that you are explicitly only matching / (and only with a GET method)
Move the route to the bottom of all of your routes
As explained on the Express.js API docs for app.use here:
A route will match any path, which follows its path immediately with a “/”. For example: app.use('/apple', ...) will match “/apple”, “/apple/images”, “/apple/images/news”, and so on.
Related
I've created a NodeJS Express app. But my express route is invocking multiple routes function, one after another, but I only need one at a time.
My express app.js
app.use(routes)
Express router:
const router = express.Router();
router.post("/product", controller.productFunction)
router.post("/user", controller.userFunction)
router.get("/:id", idController.getId)
Whenever I create a post request for "/product" route, first the productFunction is invocked, but then the "/:id" routes getId function is also get invocked. Same thing happen for /user route as well. Always /:id route is getting invocked.
Is there any way to prevent this?
I even tried this way, but after the homepage loading then again it invockes getId function.
app.get("/", (req, res, next) => {
res.sendFile(..........);
});
app.use(routes);
I am sure that this is not an issue with the router itself.
You can't skip from POST to GET handling. So invocations are caused by different requests.
router.get("/:id", idController.getId) kind of wild card, and <server_url>/favicon.ico will trigger it
If you check it via browser it tries to get favicon or smth else and invokes this handler.
Try to make POST request via curl/Postman and idController.getId should not be called.
It is risky to serve static and process requests on a same level.
You can add some prefix to all your request, like that app.use('/api', routes); then static file will be available on /<file_name> and all server logic will be under /api/<request>
I am beginning with express.js and I am wondering why the following code:
const express = require('express');
const app = express();
app.use('/', (req, res, next) => {
console.log('First middleware');
next();
});
app.use('/add-product', (req, res, next) => {
console.log('Second middleware');
res.send('<h1>The add-product page!</h1>');
});
app.use('/', (req, res, next) => {
console.log('Third middleware');
res.send('<h1>Hello from Express!</h1>');
});
app.listen(3000);
..when called with localhost:3000/add-product from chrome/firefox etc, produces
First middleware
Second middleware
First middleware
Third middleware
in the console?
First off, the browser is making two requests to your server:
/add-product
/favicon.ico
Then, to understand the routing, you have to understand the difference in route matching between app.use() and app.get().
app.get() matches only if the route definition matches the whole requested URL. The same is true for app.post(), app.put(), app.delete() and app.all().
app.use() matches if the route definition is at least partial match to the requested URL.
Note also that app.get() matches only GET requests while app.use() matches any HTTP verb (including POST, PUT, DELETE) though this difference doesn't matter in this particular example since both the requests happening here are GET requests.
In fact, the difference between app.use() and app.all() (who both match any HTTP verb) is that app.all() needs a full match and app.use() accepts only a partial match.
Also, the routes are checked for matches in the order specified in your code.
The /add-product routing
So, when the browser requests /add-product, you get this:
app.use('/', ...) matches because / is a partial match to /add-product.
app.use('/add-product', ...) matches because /add-product is a match to /add-product
The /add-product route then sends a response and does not call next() so routing is done for that request and the third route is not checked at all.
The /favicon.ico routing
Then, when the browser requests /favicon.ico, you get this:
app.use('/', ...) matches because / is a partial match to /favicon.ico.
app.use('/add-product', ...) does not match because it is not at least a partial match for /favicon.ico
Then, it checks your third route this time and it is a partial match for app.use('/', ...) which sends a response and doesn't call next() so routing is done for that request.
Note: It's important to pick app.get() or app.use() appropriately.
Two logs at the end - First and Third is for favicon.ico request. When you return a html string at /add-product, browse will auto makes a request like GET favicon.ico.
If you want to prevent it, at second middleware, return a html string like:
res.send('<head><link rel="icon" href="data:,"></head><h1>The add-product page!</h1>');
your browser is making two network calls: one to /add-product, and one to /favicon.ico. verify this by examining the network activity tab of your browser's dev tools, and/or make the same request from the command line (with wget or similar) and see what happens.
the first request passes through your first and second middleware functions, and the second request passes through your first and third middleware functions.
I'm doing an API in nodejs with express as router.
Now i'm trying to implement an client-id and an apikey to add some security to the API, and the problem that i'm facing is the next:
One of my API call is like this:
router.get("roles/get-objects/:mail/:filter*?")
So this means, that i can request an object like this:
/roles/get-objects/mail#mail.com/customer
Now the tricky part begins... when I needed to stablish a middleware to read an client-id and an apikey to verify that the client is authorized to se the API, so I did this:
In the declaration of the middleware, I use this wildcard:
router.all('/*', function (req, res, next) {
XXXX})
The thing is, I have tried in the middleware, as a wildcard everything...
I want that any API call is filtered thru that middleware, but apparently I can't find the right wildcard for it...
When I use /roles/* as wildcard, if I do a request to /roles it does work, but when I use the complete URL like: /roles/get-objects/mail#mail.com/customer it doesn't go thru my middleware.
So anybody has any idea? i'm starting to loose my mind
Thank you so much to all of you!
EDIT:
Now i'm using this middleware declaration:
router.use(function (req, res, next) {XXXX})
So when I call:
/roles/get-objects/
It's executed, the problem is when I add the email to the route:
/roles/get-objects/mail#mail.com
The app goes directly to the route that i have for that, but omits my middleware:
router.get("roles/get-objects/:mail",
I don't understand why is this happening, apparently everything should go thru my middleware first, or am I wrong?
If you want to establish a middleware to check all HTTP request whose URL starting with /roles/, the middleware should be placed before any other specific router definition:
router.use('/roles', function(req, res, next) {...});
...
router.get('/roles/get-objects/:mail', ...);
If the middleware is defined after specific route, when HTTP request comes in, the specific route is targeted and processed, the middleware won't be executed any more:
router.get('/roles/get-objects/:mail', ...);
...
router.use('/roles', function(req, res, next) {...}); // This middleware logic won't execute when request is sent to '/roles/get-objects/some-email', as the request has already been handled and response is already sent to browser.
I'm using Express framework, app.use() in app.js and router.get() in users.js. When I search localhost:3000/users/u it works fine, but when I search localhost:3000/users, it's a 404 error. What's wrong?
This is because /users call redirects to your users.js module and you don't handle / in it. To fix this, simply add the route:
// users.js
router.get('/', function (req, res) {
console.log('It works');
// ...
});
when call app.use('users',users), the users will be called and after that it will call router.handle(req,res,next) and it will match the path, if there is no related path, it will give 404 not found error.
the calling address:
https://github.com/expressjs/express/blob/master/lib/router/index.js#L47
You haven't made a /users route yet.
The app.use('/users', users) you have made, take all the routes in the users object in relative pathing. so if you create a /u in users object, it original url is http://hostname:port/users/u. You haven't made a /users route which could handle that path.
Create a router.get('/') route in your users.js, everything would be fine.
I was just reading the documentation on express and found these two terms, app.use(); and router.use();
I know app.use(); is used in node for Mounting a middleware at a path, and we often use it in most of the node apps. but what is router.use(); are they both same? if not, whats the difference ?
I read about router here. I also found similar questions on SO What is the difference between "express.Router" and routing using "app.get"?
and Difference between app.all('*') and app.use('/'), but they do not really answer my question. Thanks.
router.get is only for defining subpaths. Consider this example:
var router = express.Router();
app.use('/first', router); // Mount the router as middleware at path /first
router.get('/sud', smaller);
router.get('/user', bigger);
If you open /first/sud, then the smaller function will get called.
If you open /first/user, then the bigger function will get called.
In short, app.use('/first', router) mounts the middleware at path /first, then router.get sets the subpath accordingly.
But if we instead use the following:
app.use('/first', fun);
app.get('/sud', bigger);
app.get('/user', smaller);
If you open /first in your browser, fun will get called,
For /sud, bigger will get called
For /user, smaller will get called
But remember for /first/sud, no function will get called.
This link may also help: http://expressjs.com/api.html#router
router.use(); mounts middleware for the routes served by the specific router, app.use(); mounts middleware for all routes of the app (or those matching the routes specified if you use app.use('/ANYROUTESHERE', yourMiddleware());).
Example use case could be an app with one router with standard routes and one router that handles api routes, which need a valid user.
You would then mount the authentication middleware for the api router only with router.use(yourAuthMiddleware());.
If you would have an app though that requires a valid user for all routes, mount the middleware for the app with app.use(yourAuthMiddleware());
app.use() used to Mounts the middleware function or functions at the specified path,the middleware function is executed when the base of the requested path matches path.
router.use() is used to middleware function or functions, The defaults mount path to “/”.
But in
app.use() you will have to give a specified path like that:
var adsRouter = require('./adsRouter.js');
app.use('/ads', adsRouter);
or
app.use('/ads', function(req, res, next) {
// write your callback code here.
});
But while using router.use() you can give only middleware, like this:
router.use(function(req, res, next) {
console.log('%s %s %s', req.method, req.url, req.path);
next();
});
or
router.use('/test', function(req, res, next) {
// write your callback code here.
next();
});
or
//in router.js
router.use('/admin', authUtil.verifySessionId, authUtil.verifyLisencee);
router.post('/admin', controllerIndex.ads.adListingAdmin);
In the above code when the end point is '/admin' then first it will call the authUtil.verifySessionId and authUtil.verifyLisencee then it will execute next line with 'admin' end point and according to controllerIndex.ads.adListingAdmin method.
app.use(middleware): application-level middleware.
router.use(middleware): router-level middleware.
("middleware" refers to methods/functions/operations that are called between processing the request and sending the response.)
See https://expressjs.com/en/guide/using-middleware.html for a comparison of different types of middleware used in an Express app.
When looking at the express js docs for Routing (https://expressjs.com/en/guide/routing.html#express-router):
Use the express.Router class to create modular, mountable route handlers. A Router instance is a complete middleware and routing system; for this reason, it is often referred to as a “mini-app”.
A Router created with express.Router() is no different than an app created with express() in terms of functionality; it's like a logical grouping of routes/handlers/services/databases/etc. The biggest difference is the scope that it affects. A router just affects its own scope while the app is like the master/global scope for your web/app server. You could have many routers or "apps" running on one main app/web server instance. This is why you could listen to requests on an app instance via app.listen(80) but not on a router.