Authentication Using Passport.js Serving Stating Content Through Nginx - node.js

for a project that im currently working on, i decided not to use node's http server, and for a few days i have been trying to figure out how to combine a socket.io-passport app with nginx.To my understanding im forced to use express (for session handling).Its very weird that all the examples i have found on the net, always using node's server for serving static content and noone has made an actual working example with Nginx instead.Let me describe my problem.
Consider the following code
app.get('/home', function(reg, res){
//check user session value, is logged in
if(req.user)
res.render('dash',{
username: req.user['member_id']//req.user array contains serializeUser data
});
else
res.render('index');
});
app.get('/logout', function(req, res){
req.logout();
res.redirect('/home');
});
//login form submit as post
app.post('/login',
passport.authenticate('local', {
successRedirect: '/dashboard',
failureRedirect: '/home'
})
);
app.get('/signup',routes.signup);
app.get('*', routes.index);
How do i instruct JavaScript in my js file, to serve static files without routes?

In expressjs you can use static middleware to serve static content from specific folder. You do not need to specify route for that.
app.use(express.static(__dirname + '/public'));
you can access static files in public folder localhost:portnumber/staticfile.js
You may want to prefix static files, you can use this:
app.use('/static', express.static(__dirname + '/public'));
you can access with localhost:portnumber/static/staticfile.js
If you want nginx to serve static files you can simply create new vhost in nginx to serve static files through nginx aswell.
Generally nginx is used as reverse proxy to proxy all request on port 80 to node.js app.

Related

Express doesn't load page only return json

The problem appears when after reloading a page, server return only json instead that page
I'm using React and return static files from build folder, there is also express handles routing, it is reproduced only in production mode when running localhost everything ok
app.use('/auth', authRoutes);
app.use('/user', userRoutes);
app.use(['/dota2', '/csgo', '/lol'], generalRoutes);
if (process.env.REACT_APP_ENV === 'production') {
console.log('Production is running');
app.use('/', express.static(path.join(__dirname, '../build')));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, '../build', 'index.html'));
});
}
There are routes
const router = Router();
router.get('/live', liveMatches);
router.get('/upcoming', upcomingMatches);
router.get('/past', pastMatches);
router.get('/:matchId', getMatchById);
router.get('/opponents/:tournamentId', opponents);
router.post('/past-team-matches', pastTeamMatches);
You can visit mySite and you will see json as result but if you clear matchId in URL and click on any match the page will load as normal
There is also react-router
<ServiceRoute
key={key}
path={['/dota2', '/csgo', '/lol']}
exact
access
component={Matches}
/>
<ServiceRoute
key={key}
path={['/dota2/:matchId', '/csgo/:matchId', '/lol/:matchId']}
exact
access
component={MatchInfo}
/>
Let's follow the route matching that express does in this case:
When looking for /dota2/566624, it will match here: app.use(['/dota2', '/csgo', '/lol'], generalRoutes); and return the JSON.
When looking for /dota2, it won't match app.use(['/dota2', '/csgo', '/lol'], generalRoutes); so it will continue down until it matches app.get('*', (req, res) => {, serving the React page.
The problem I see here, is that you're using the very same routes for the API and the front-end routing on React. Ideally, when serving the API and the front-end application from the same server you should prefix the API routes, that way they won't clash with the front-end routes. Let's say that you prefix the API routes with: /api. Now you we have:
app.use('/api/auth', authRoutes);
app.use('/api/user', userRoutes);
app.use(['/api/dota2', '/api/csgo', '/api/lol'], generalRoutes);
// ... everything is the same down here
/api/dota2/566624. Will match against the endpoint that returns the JSON on the first load.
/dota2/566624. Will not match the JSON endpoint and will follow down to the '*' route that loads the React app, later, once the app is loaded that route will be handled by the router you're using on the react application.
Don't add the prefix as I did in the example above, use the const router = Router(); you've been using for this purpose as well. I hard-coded the prefix so that I can keep the example short.
One last question is: Why is this not happening on development?
I don't have all the information but for what I can see you're serving the front-end application from a different server than the one running the API; in that case you won't have the route clashing, since they are server from different ports, e.g front-end served on localhost:8080 and API served on localhost:5000.
I hope this helps! please comment if you need info!

NodeJS Express — Serve generated index.html public file without saving it

When using express, the expectation is that you'll serve a public directory.
const app = express();
app.use('/', express.static('./public/'));
Is there a way I could serve a generated file instead? For my application, it would be much more convenient if I could build the index.html directly, then serve that 'file' directly from memory, without having to save it just to then serve it via 'use'.
the expectation is that you'll serve a public directory
I don't think that is the expectation at all. Many applications just use routes instead making a REST micro service.
There are two ways you can do what you want to do.
Use a templating engine with NodeJS and just res.render() the template. Check this out for more information, even though the article is using .pug you can use these ones as well. Popular ones are ejs, handlebars
app.get('/', function (req, res) {
res.render('index', { title: 'Hey', message: 'Hello there!' })
})
Or you can write everything inside res.send() for example:
app.get('/', function (req, res) {
//set the appropriate HTTP header
res.setHeader('Content-Type', 'text/html');
//send multiple responses to the client
res.send('<h1>This is the response</h1>');
});

better way to verify jwt token for angular app deployed on nodejs

I have created a server using the express framework. I have implemented the JWT. I have created an angular app then copied to the public folder. Then used
app.use(express.static(__dirname + "/public"));
to make this public. Now I want to authenticate my angular routes. Now there could be a call for the URL that will be URL of angular routing like localhost:7000/a, localhost:7000/b and so on. Additionally, there will be calls for the actual files like CSS, images or other files.
So I have used a middleware to intercept all the server calls.
app.use((req, res, next) => {
let pwt = req.cookies ? req.cookies.pwt : null;
jwt.verify(pwt, process.env.SECRET_KEY, (err, decoded) => {
if (decoded) {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
} else {
let callbackUrl = encodeURIComponent("http://" + req.headers.host + req.originalUrl);
res.redirect(process.env.AUTH_SERVER + "/auth?_r=" + callbackUrl);
}
});
});
I am checking the jwt token and return the index.html file for each request. when there is call for image or any other CSS files it returns the index.html file.
One way is to make an array of Angular routing URLs and serve the index.html file only if req.originalUrl is from that list. But this is not the good approach, as the server should not have the knowledge of app routing. Is there any way to solve this problem?
I think the best way to do this is to implement routes in angular and secure it there if you are building SPA, but with express middleware just secure your API request from your angular app.

Express - Setting different maxAge for certain files

I'm building a single page application using Express for the backend and AngularJS for the frontend and I'm having some cache problems.
I'm not using express views, only serving files with express.static middleware.
My static files are in public/app or public/dist depending on enviroment (dist has minified files).
app.use app.router
app.use express.static(cwd + '/public/' + publicFolder, maxAge: MAX_AGE)
When requesting '/', app.router verifies if user is logged in, and if everything is ok then index.html is served via express.static (I just call next() in the controller). If user is not logged in, it gets redirected to login.html
My problem is that if I set maxAge, my index.html file gets cached and the first request to '/' doesn't go through router. I can enter the app even if I'm not logged in.
If I set maxAge to 0, the problem goes away, but I want to cache all my *.js and *.css files.
What is the correct approach to this kind of problems? Start using views? Different express.static mount points?
You can always define individual routes without necessarily using views (although view templates aren't a bad idea). In this way you could define index.html just to apply the special case maxAge.
Just be sure to put the route before the static middleware.
If you wanted you could even use send, the same static server that the static middleware uses behind the scenes. Something like:
// install send from npm
var send = require("send");
app.get("/index.html", function (req, res) {
send(req, "/index.html")
.maxage(0)
.root(__dirname + "/public")
.pipe(res);
});
Or the more low level stream way, something like:
app.get("/index.html", function (req, res) {
res.setHeader('Content-Type', 'text/html');
res.setHeader('Cache-Control', 'public, max-age=0');
// Note that you'd probably want to stat the file for `content-length`
// as well. This is just an example.
var stream = fs.createReadStream(__dirname + '/public/index.html');
stream.pipe(res);
});

How to use AngularJS routes with Express (Node.js) when a new page is requested?

I'm using Express, which loads AngularJS from a static directory. Normally, I will request http://localhost/, in which Express serves me my index.html and all of the correct Angular files, etc. In my Angular app, I have these routes setup, which replace the content in an ng-view:
$routeProvider.when('/', {
templateUrl: '/partials/main.html',
controller: MainCtrl,
});
$routeProvider.when('/project/:projectId', {
templateUrl: '/partials/project.html',
controller: ProjectCtrl,
});
$locationProvider.html5Mode(true);
On my main page, I have a link to <a href="/project/{{project.id}}">, which will successfully load the template and direct me to http://localhost/project/3 or whatever ID I have specified. The problem is when I try to direct my browser to http://localhost/project/3 or refresh the page, the request is going to the Express/Node server, which returns Cannot GET /project/3.
How do I setup my Express routes to accommodate for this? I'm guessing it will require the use of $location in Angular (although I'd prefer to avoid the ugly ?searches and #hashes they use), but I'm clueless about how to go about setting up the Express routes to handle this.
Thanks.
with express 4, you probably want to catch all requests and redirect to angularjs index.html page.
app.use(app.router); doesn't exist anymore and res.sendfile is deprecated, use res.sendFilewith an uppercase F.
app.post('/projects/', projectController.createProject);
app.get('/projects/:id', projectController.getProject);
app.get('*', function (req, res) {
res.sendFile('/public/index.html');
});
put all your API routes before the route for every path app.get('*', function (req, res){...})
I would create a catch-all handler that runs after your regular routes that sends the necessary data.
app = express();
// your normal configuration like `app.use(express.bodyParser());` here
// ...
app.use(app.router);
app.use(function(req, res) {
// Use res.sendfile, as it streams instead of reading the file into memory.
res.sendfile(__dirname + '/public/index.html');
});
app.router is the middleware that runs all of your Express routes (like app.get and app.post); normally, Express puts this at the very end of the middleware chain automatically, but you can also add it to the chain explicitly, like we did here.
Then, if the URL isn't handled by app.router, the last middleware will send the Angular HTML view down to the client. This will happen for any URL that isn't handled by the other middleware, so your Angular app will have to handle invalid routes correctly.
I guess I should have clarified that I wasn't interested in using a template engine, but having Angular pull all of the HTML partials on it's own, Node is functioning completely as a static server here (but it won't be for the JSON API. Brian Ford shows how to do it using Jade here: http://briantford.com/blog/angular-express.html
My app is a single-page app, so I created an Express route for each possible URL pattern, and each of them does the same thing.
fs.readFile(__dirname + '/public/index.html', 'utf8', function(err, content) {
res.send(content);
});
I was assuming I would have to pass some request variables to Angular, but it looks like Angular takes care of it automatically.

Resources