I am trying to fetch web pages using express static and below is the server code.
app.use(express.static('DIR/webfiles'));
app.get('/test', function(req, res) {
console.log("got req");
res.sendfile("login.html");
});
app.get('/', function(req, res) {
console.log("got req");
res.sendfile("login.html");
});
when I request for localhost:port/test (from browser), I am able to see login.html page and it prints "got req" on server end but when I request for localhost:port or localhost:port/ , I am getting some other file in webfiles folder. It does not print "got req". Is empty GET handler overridden by express static?
When I remove "app.use(express.static('DIR/webfiles'));" line, it is able to get empty GET request but doesn't work in way I want it to. Why it is not getting empty request and how to handle empty requests.
Express will process the various route handlers (including the static middleware) in order of declaration.
If you request /, the static middleware will check for a file called webfiles/index.html, and if it exists, it will be returned.
To override this behaviour, make sure that you declare your own route handler before the static middleware declaration:
// This will match requests to `/` and since it's declared before
// the static middleware, it will get to handle those requests.
app.get('/', function(req, res) {
console.log("got req");
res.sendfile("login.html");
});
app.use(express.static('DIR/webfiles'));
Related
I have a MEAN stack application and using Node.js and Express.js as back-end API.
Assuming I have a 'comments' route as follow
/* GET /comments listing. */
router.get("/", function(req, res, next) {
Comment.find(function(err, comments) {
if (err) return next(err);
res.json(comments);
});
});
And use it in my server like this:
var commentsRouter = require('./routes/comments');
...
app.use('/comments', commentsRouter);
My question is: Is there a way to prevent users to access http://mrUrl/comments in browser and deny the request with probably 403 Forbidden message but at the same time JavaScript file tries to access the same URL will receive a content message (in the example should be res.json(comments);)
Also, would it be possible to enable such a restriction for all routes once, not for each.
Yes, you can use a middleware.
A middleware is a function you can pass before or after the main function you are executing (in this case, GET comments)
the order of the function location matters, what comes first - executes first, and you implement it like so:
app.use(myBrowsingRestrictionMiddlewareFunction) // Runs
app.use('/comments', commentsRouter);
app.use('/account', accountRouter);
You can also use within a route handler:
app.post('/comments', myMakeSureDataIsAlrightFunction, myMainCreateCommentFunction, myAfterStatusWasSentToClientAndIWishToMakeAnotherInternalActionMiddleware);
The properties req, res, next are passed into the function automatically.
which means, myBrowsingRestrictionMiddlewareFunction receives them and you can use them like so:
export function myBrowsingRestrictionMiddlewareFunction(req, res, next) {
if (req.headers['my-special-header']) {
// custom header exists, then call next() to pass to the next function
next();
} else {
res.sendStatus(403);
}
}
EDIT
Expanding regards to where to place the middleware in the FS structure (personal suggestion):
What I like to do is to separate the router from app.js like so:
app.js
app.use('/', mainRouter);
router.js
const router = express.Router();
router.use(middlewareForAllRoutes);
router.use('/comments', commentsRouter);
router.use(middlewareForOnlyAnyRouteBelow);
router.use('/account', accountRouter);
router.use(middlewareThatWillBeFiredLast); // To activate this, remember to call next(); on the last function handler in your route.
commentsRouter.js
const router = express.Router();
router.use(middlewareForAllRoutesONLYFORWithinAccountRoute);
route.get('/', middlewareOnlyForGETAccountRoute, getAccountFunction);
router.post('/', createAccount);
I have a URL like for example 'localhost:3000/verify/a5d5sd', that I have sent to a user's email, upon clicking this link, I am using the param (a5d5sd) in the link for checking some stuff in the server and database(MongoDB) and returning a response with an object, now when the link is clicked or opened on a new tab, I only see the response from the server but not with the HTML from my Angular 2 component.
In my Angular 2 route config module, I did config a route like
{
path: 'verify/:id',
component: MyComponent
},
And on ngOnInit of this component, I am calling a service method that makes a GET http request with a URL like verify/:id the param(:id) I get it using the ActivatedRoute from the #angular/router so that I can make the request.
To handle this I was advised to have the following code for my express to use:
app.use(express.static(path.join(__dirname, 'client/dist')));
app.get('*', function(req, res) {
res.sendFile(__dirname + '/client/dist/index.html');
})
Have even tried with:
app.all('*', function(req, res) {
res.sendFile(__dirname + '/client/dist/index.html');
})
This code works for direct navigation(pasting URLon the search bar) and refreshes for only POST and PUT requests but not working with GET requestS that expects a response from the server side, when I directly visit a URL or refresh the page, the DOM is written with the server response but with not HTML, any assistance will be appreciated.
After define all routes, add the route for the index.html file
// Set your routes here
app.use('/api', api);
// Catch all other routes and return the index file
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'path/to/index.html')); //path from the root dir
});
This was work for me.
Thanks
app.get(`/`, (req, res, next) => {
console.log(`in / get`);
const indexHtml = path.resolve( __dirname + '/../public/index.html' );
res.sendFile(indexHtml);
next();
});
I'm trying to make this index.html show up on my home route using express but it's not loading. I get the console log, and I've console logged indexHTML to ensure the path is correct, but all I get is an error of cannot get.
All my other routes that are brought it are working a-ok. Just not this guy.
Remove the call to next() after res.sendFile(). You want the res.sendFile() to handle the response entirely, but calling next() passes on control to other handlers, probably ending up in the 404 handler and because that doesn't have to read the disk, it gets processed before res.sendFile() does it's job.
When you send the response, you do not want to call next() because you don't want any more request handlers in the chain to run.
I have a simple node/express js api that receives request from another app.The request is this GET /api/users?data=5. Whenever i hardcode data with 5 like above, it does hit /api/users route.But whenever i send the request with dynamic data like GET /api/users?data=id where id = 5, it DOESN'T hit /api/users route, But in the server logs i do see the request did hit with url /users?data=5.I am not sure whats wrong but i am suspecting maybe i didnt define the routes correctly.Any help will be appreciated.Sorry I am new to Node js. Thank you.Here is my code
var app = express();
var router = express.Router();
router.use(function(req, res, next) {
next();
});
router.get('/', function(req, res) {
res.render('home');
});
app.use('/api', router);
router.route('/users')
.get (function(req, res) {
var data = req.query.data;
});
I figured it out , in the request GET /api/users?data=id HTTP/1. id was not properly formated ,hence the request was hitting the server but not application layer.
UPDATE
In short the app that make Http GET request is written in arduino (which translates it to C).I was reading the ID from the device memory which is saved as char array.So i thought i had converted the char array to string but in reality was still chars, and i put this variable in the url for Get request that is why it was complaining.
I want to check the authorization of the users of my web app when they entered the url. But when I used an individually middleware to check the authorization, it's useless for the already existing routes, such as:
function authChecker(req, res, next) {
if (req.session.auth) {
next();
} else {
res.redirect("/auth");
}
}
app.use(authChecker);
app.get("/", routes.index);
app.get("/foo/bar", routes.foobar);
The authChecker is unabled to check the authority of the users who entered the two urls.
It only works for the unspecified urls.
And I saw a method that I can put the authChecker between the route and the route handler,
such as:
app.get("/", authChecker, routes.index);
But How can I achieve it in a simple way rather than putting the authChecker in every route?
As long as
app.use(authChecker);
is before
app.use(app.router);
it will get called for every request. However, you will get the "too many redirects" because it is being called for ALL ROUTES, including /auth. So in order to get around this, I would suggest modifying the function to something like:
function authChecker(req, res, next) {
if (req.session.auth || req.path==='/auth') {
next();
} else {
res.redirect("/auth");
}
}
This way you won't redirect for the auth url as well.
There are may ways to approach this problem but here is what works for me.
I like to create an array of middleware for protected and unprotected routes and then use when necessary.
var protected = [authChecker, fetchUserObject, ...]
var unprotected = [...]
app.get("/", unprotected, function(req, res){
// display landing page
})
app.get("/dashboard", protected, function(req, res){
// display private page (if they get this far)
})
app.get("/auth", unprotected, function(req, res){
// display login form
})
app.put("/auth", unprotected, function(req, res){
// if authentication successful redirect to dashboard
// otherwise display login form again with validation errors
})
This makes it easy to extend functionality for each middleware scopes by editing the array for each type of route. It also makes the function of each route more clear because it tells us the type of route it is.
Hope this helps.
But when I used an individually middleware to check the authorization, it's useless for the already existing routes
Express will run middleware in the order added to the stack. The router is one of these middleware functions. As long as you get your authChecker into the stack BEFORE the router, it will be used by all routes and things will work.
Most likely you have the router before authChecker because you have routes defined prior to getting your authChecker into the stack. Make sure to put all your app.use calls before any calls to app.get, app.post, etc to avoid express's infuriating implicit injection of the router into the middleware stack.