Node.js + Express: file structure and communication - javascript

I have a login application but I am having trouble communicating the credentials of the form (email and password) to my existing .js files, where it performs some logic and retrieves some info.
On my login page I have a form with a POST method. Then, I have a main.js that performs the login:
main.js
module.exports = {
returnSessionToken: function(success, error) {
var email = email_X;
var pwd = password_Y;
[...]
function(error, response, body) {
var login = JSON.parse(body);
success(login.sessionToken)
}
And then I have a index.js where I retrieve some info of the logged user:
index.js
var authToken = require("./main");
authToken.returnSessionToken((result) => {
'my_website_token': result,
[...]
}
In my express project, I have these two files in a js folder. What I am trying to do is getting the email and password of the form of the login page and pass it to my main.js file (email_X and password_Y) and then call index.js. I know how to get the req.body.email and req.body.password in the routes folder, but stil can't figure out how to make these files communicate.
I have also tried to edit the app.js file into:
app.js
var login = require('./js/main');
and then,
app.use('/myaccount', login);
But no success.
Any help will be very much appreciated. Thanks!

I'm slightly confused by the details and what looks like some missing steps, but it looks like the problem may be caused by the way you're setting up and referencing your main.js module.
app.use('/myaccount', login) will send your main.js module two objects, generally referenced as req and res. req contains information about the http request. I believe the data from a form HTTP post is sent in req.body.
See example below:
index.js
var express = require('express');
var login = require('./login');
var app = express();
app.use('/login', login); // mount the sub app
login.js
var express = require('express');
var login = express();
login.post('/', function (req, res) {
console.log(req.body); // should print your form data
// do your login logic here
res.status(200).end(); // Sends http response back
});
module.exports = login;

For future reference, here's a working example. Thank you Ryan Villanueva for the help!
main.js
module.exports = {
returnSessionToken: function(email, pwd, success, fail) {
var email = email;
var pwd = pwd;
success(token)
[...]
}
index.js
module.exports = {
returnUserData: function(authToken, success) {
[...]
'my_website_token': authToken,
}
app.js
var myaccount = require('./routes/myaccount');
app.use('/myaccount', myaccount);
routes/myaccount.js
var express = require('express');
var router = express.Router();
var login = require('../js/main')
router.post('/', function(req, res) {
var email = req.body.email
var password = req.body.password
login.returnSessionToken(email, password, (token) => {
console.log("return token: ", token)
var logged = require('../js/index')
logged.returnUserData(token, (myData) => {
res.render('myaccount', { myData: myData });
})
},
(fail) => {console.log(fail)})
})
module.exports = router;

Related

Access express response data client side

In my express router I check if the data inserted on a form are valid then if they are I render another page passing form data. I would like to access the data I pass client-side. On the chat.ejs view I have a chatroom.js client file, I want to access the data there without having to access them in a script tag.
I thought about using Ajax but the only answer I found here on StackOverflow was marked as wrong, so how do I go about that?
router.js
module.exports=function(app) {
const express = require('express');
const router = express.Router();
const {check, validationResult} = require('express-validator');
const {matchedData} = require('express-validator/filter');
router.get('/', (req, res) => {
res.render('index', {
data: {},
errors: {}
})
});
router.post('/enter', [
check('username')
.isLength({min: 1})
.withMessage('Username is required').trim(),
check('room')//implement personalized check
], (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.render('index', {
data: req.body,
errors: errors.mapped()
})
}
else {
const data = matchedData(req);
return res.render('chat',{
user: data.username,
room:data.room
})
}
});
return router;
//MOVE TO SUPPORT
function find(name) {
return 1;
}
}
there is really nothing client-side so far so It seems useless just posting my views. Alternatively, I could use Ajax on client.ejs to handle the form submission but I would like to keep this clean and handle the routing with the router file.
I ended up creating two global variables in a script tag for my index.ejs page like this
<script>
var user = <%- JSON.stringify( user ) %>
var room = <%- JSON.stringify(room)%>;
</script>
and then I could access them in the chatroom.js file linked below

Express over Node.js - TypeError: Cannot read property 'forEach' of undefined

I'm building my first node/express app and am following this tut.
I am at a point where I am trying to get all JSON data and put it in an array to be sent to the template and rendered. When I try to run the app via CLI, I get the following error:
Directory Structure
The data output at the var blogsurlall location
hellotest.js
var routes = require('./routes/index');
var express = require('express');
var app = express();
var request = require("request");
var blogsurlall = "https://[JSON export URL location configured in a Drupal 8 view]";
app.set('view engine','ejs');
var server = app.listen (2000, function(){ console.log('Waiting for you on port 2000'); });
/* Get all global blogs data */
request({
url: blogsurlall,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
blogsdata_all = body;
}
// Create blogs array for footer.
var blogs = [];
// Fill up the array with blogs.
blogsdata_all.blogs.forEach(function(item){
blogs = blogs.concat(item);
});
app.locals.blogsdata = blogs;
});
app.use('/', routes);
index.js
var express = require('express');
var routes = express.Router();
routes.get('/', function(req, res){ res.render('default',{title: 'Home', body: 'blogsdata'}); });
routes.get('/about-us', function(req, res){ res.send('<h1>Lucius Websystems</h1>Amsterdam, The Netherlands'); });
routes.get('/about/:name?', function(req, res){ var name = req.params.name; res.send('<h1>' +name +'</h1>About text'); });
/* GET Blog detail page. */
routes.get('/blog/:blogid', function(req, res, next) {
// Place json data in a var.
var blogsdata = req.app.locals.blogsdata;
// Create array.
var blogItem = [];
// Check and build current URL
var currentURL = '/blog/' + req.params.blogid;
// Lop through json data and pick correct blog-item based on current URL.
blogsdata.forEach(function (item) {
if (item.title == currentURL) {
blogItem = item;
}
});
if (blogItem.length == 0) {
// Render the 404 page.
res.render('404', {
title: '404',
body: '404'
});
} else {
// Render the blog page.
res.render('blog-detail', {
blog: blogItem
});
}
});
module.exports = routes;
From the CLI error, it appears no blog data is even returned to be read into the array.
I have carefully gone through the tutorial several times and I think there are steps that may be implied that I am missing.
Can someone please help me understand how to get the blog data so that it can be read into the array and output to my template?
Also open to troubleshooting suggestions in comments.
Thanks for reading!
The error is raising in this line:
blogsdata_all.blogs.forEach(function(item){
As the error says, blogs is undefined.
If there is an error in the request or status code isn't 200, the body is not assigned to the variable, but you are not finishing the execution, so the variable in that case would be undefined.
Other possible problem is the json received doesn't have blogs as key of the body.
Check this both things and let us know if you found the problem

Jquery ajax request response 404 when make a post request

I am creating a basic friend request feature. This is one of the function I am working on, when Ajax send the post request it shows 404. It works if I put the code directly in the server.js file but I am trying to organize the code. Any solution? Thanks!
client.pug make a ajax request when user add friend by using email and hit submit
$('#addFriend').on('click', function(ev) {
ev.preventDefault();
var searchByEmail = $('#searchByEmail').val();
$.ajax({
type: 'POST',
url: '/add',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
data: {
email: searchByEmail
},
success: function(data) {
console.log('success');
}
});
document.getElementById("searchByEmail").value = "";
$('#userModal').modal('hide'); });
controllers/friend.js
const express = require('express');
const app = express();
const User = require('../models/user');
const bodyParser = require('body-parser');
var friendRequest = function() {
app.post('/add', function(req, res) {
var requestToEmail = req.body.email;
console.log(requestToEmail);
User.findOne({
email: requestToEmail
}, function(err, email) {
if (!email) {
console.log('cannot find the email', err);
return res.send(err);
}
/*
Add into database
Display the friend list
*/
})
});
} // End friend request
module.exports = friendRequest;
server.js include and use the module
const friendInvite = require('./controllers/friend');
app.use('/friend', friendInvite);
file structure
- server.js
- controllers
- friend.js
- views
- client.pug
Try change your code on controllers/friend.js like below :
const express = require('express');
const app = express();
const User = require('../models/user');
const bodyParser = require('body-parser');
var friendRequest = function() {
app.post('/add', function(req, res) {
var requestToEmail = req.body.email;
console.log(requestToEmail);
User.findOne({
email: requestToEmail
}, function(err, email) {
if (!email) {
console.log('cannot find the email', err);
return res.send(err);
}
/*
Add into database
Display the friend list
*/
//add this response to client side
res.json({ 'status': '200', 'desc': 'Success' });
})
});
} // End friend request
module.exports = friendRequest;
you must send response to client side what is sign if the data has saved.
maybe you can try to check snippets code here :
https://github.com/egin10/node_mongoose/blob/master/routes/student.js
I didn't see response in your app.post()
So it will be 404(Not found).
When you find a User, you can response something.
For example, a 'success' message and friend list.
app.post('/add', function(req, res) {
res.json(['success', friend list]);
});

Should express router.get intervene page loading?

I have built a mean-stack application. I use http to communicate data between front-end and back-end. For example,
In front-end, I have
app.factory('ops', ['$http', function ($http) {
var o = {};
o.get = function (id) {
return $http.get('/ops/' + id)
.then(function (res) {
return res.data
})
};
return o;
}]);
In the back-end, in routes/index.js, I have
var express = require('express');
var router = express.Router();
... ...
router.get('/ops/:op', function (req, res, next) {
console.log("/ops/:op");
res.json(req.op);
})
module.exports = router;
And it is the job of ui-router to load a page like https://localhost:3000/ops/59202d6a38b09685ff6b0581:
.state('ops', {
url: '/ops/{id}',
...
However, since I turned html5Mode to true, it seems that router.get('/ops/:op', function (req, res, next) { console.log("/ops/:op"); res.json(req.op); }) can directly load the page https://localhost:3000/ops/59202d6a38b09685ff6b0581. If I comment .state('ops' ... and load the page, I see /ops/:op is displayed in the server console, and the content of the json data is shown in the browser. At the same time, in the browser console, I see
Resource interpreted as Document but transferred with MIME type application/json: "https://localhost:3000/ops/59202d6a38b09685ff6b0581"
Could anyone tell me if we should let router.get('/ops/:op' ... intervenue the loading of a page in this way? If not, how could we disable it?
PS: routers/index.js is referenced in app.js as follows:
var index = require('./routes/index');
app.use('/', index);

Passing objects and variables using `require` in `Node.js`

I am working on moving routing methods from app.js to separate files.
I managed to do it using (in app.js):
var userRoutes = require('./serverRoutes/userRoutes');
app.use('/userRoutes', userRoutes);
app.post('/user/login', userRoutes);
I can see that routing is being done.
I have some variables in my app.js like:
- tokens array
- jwtSecretKeystring
- jwt encryption module
- User which is mongoose schema
I would like to pass them and make them usable by routing methods inside userRoutes.js file.
I do not know how to do it.
Another question.
I also have some 'helper' type methods I would like to use in different 'routing' files.
I do not know how to pass them either.
This is how I deal with 'routing' files:
var express = require('express');
var router = express.Router();
router.post('/user/login', function (request, response) {
var email = request.body.email;
var password = request.body.password;
User.findOne({ email: email, password: password },
function (err, user) {
if (err)
response.send(err);
if (user) {
var expires = new Date();
expires.setDate((new Date()).getDate() + 5);
var token = jwt.encode({
email: email,
expires: expires
}, jwtTokenSecret);
tokens.push(token);
response.send(200, { access_token: token });
} else {
response.send(401, { message: "User not found" });
}
});
});
module.exports = router;
Thank you :-)
I am unsure what the "resolve" part of your title has to do with your question, but I can answer the rest of what you discuss in your question.
I have some variables in my app.js... I would like to pass them and
make them usable by routing methods inside userRoutes.js file.
The usual way to share some settings with another module is to pass them to that module in a module constructor or a module method:
var userRoutes = require('./serverRoutes/userRoutes')({
tokens: tokens,
jwtSecretKey: jwtSecretKey,
jwt: jwt,
User: User
});
Then, inside that userRoutes module:
var express = require('express');
var router = express.Router();
var jwtSecretKey, jwt, User, tokens;
router.post('/user/login', function (request, response) {
var email = request.body.email;
var password = request.body.password;
User.findOne({ email: email, password: password },
function (err, user) {
if (err)
response.send(err);
if (user) {
var expires = new Date();
expires.setDate((new Date()).getDate() + 5);
var token = jwt.encode({
email: email,
expires: expires
}, jwtSecretKey);
tokens.push(token);
response.send(200, { access_token: token });
} else {
response.send(401, { message: "User not found" });
}
});
});
// define module constructor
module.exports = function(options) {
// save data shared from parent module
jwtSecretKey = options.jwtSecretKey;
jwt = options.jwt;
User = options.User;
tokens = options.tokens;
return router;
};
I also have some 'helper' type methods I would like to use in
different 'routing' files. I do not know how to pass them either.
The usual way to share some common help functions is to put them in their own module and then you just require() in that module in any other module that you need to use them.

Categories

Resources