Managing Sessions in node - node.js

I'm learning how to use nodejs and i'm developing a chat page with my experience from php, i know that nodejs does almost nothing about what php does, so i'm building the whole structure, like rebuilding the php engine but just in node, for now im having problems with sessions, because i want to make a User system, so im making a login, it's quite hard for me to figure out what process to do in order to make a login process and if user exist, make the session, i have this code in my index
<!doctype html>
<html>
<head>
<title>Login - Chat</title>
<meta charset="UTF-8">
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<link rel="stylesheet" type="text/css" href="css/main.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
</head>
<body>
<div class="container" id="page">
<h2>Chat Login</h2>
<div id="login-form" class="well">
<form method="post" accept-charset="UTF-8">
<div class="form-group" method="post">
<label for="Username">Username</label>
<input type="text" class="form-control" id="Username" name="Username" placeholder="Enter email">
</div>
<div class="form-group">
<label for="Password">Password</label>
<input type="password" class="form-control" id="Password" name="Password" placeholder="Password">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
<script type="text/javascript">
window.onload = init;
var socketio = io.connect(window.location.hostname);
function init()
{
var login = document.getElementById('login-form');
login.onsubmit = requestData;
}
function requestData()
{
username = document.getElementById('Username');
password = document.getElementById('Password');
//alert if form is empty.
if((username.value && password.value) == '')
{
alert('Box has empty value.');
return false;
}
else
{
socketio.emit('Login_user', {user: username.value, pass: password.value});
}
}
</script>
</body>
</html>
im using socket.io for transfering data from client to server and viceversa (im still learning it socket). I got stuck right in this step, i just need to know how to handle sessions in nodejs, i've got my github repository for this : Chat so you can see my whole code in there, any idea how to handle sessions?.
PD: I'm just a newbie developer, i have like 6 months using PHP and like 2 weeks with node, i dont want to use any framework in order to learn the language better.

I recommend using Express.js as node framework. Express has built in support via Connect framework. Im using this via a Redis backed session store to allow multi server load balancing. Here's a snippet on node-express-connect work in app.js if you want:
var express = require('express')
, RedisStore = require('connect-redis')(express)
;
var app = express();
app.use(express.session({
secret: 'some pass',
cookie: {
httpOnly: false,
secure: false,
maxAge:null,
domain:'.yourdomain.com'
},
store: new RedisStore({
ttl:1800, //30 min redis ttl
client:redis,
secret:'some pass'
})
}));

Since your using socket.io, I would recommend reading through the session.socket.io module. The source code is very small and readable:
README.md
session.socket.io.js (48 lines of code)

Related

socket console.log() not showing when connected

I'm completely new to socket.io and I'm trying to connect a client to the server.
This is app.js.
const socketio = require("socket.io");
const app = express();
app.set("view engine", "ejs");
app.use(express.static("public"));
app.get("/", (req, res) => {
res.render("index");
});
const server = app.listen(process.env.PORT || 3000, () => {
console.log("server is running...");
});
// Initialize socket for the server
const io = socketio(server);
io.on("connection", socket => {
console.log("New user connected");
});
This is index.ejs.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Real time Chat App</title>
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
/>
</head>
<body>
<div class="container">
<div class="title">
<h3>Realtime Chat Room</h3>
</div>
<div class="card">
<div class="card-header">Anonymous</div>
<div class="card-body">
<div class="input-group">
<input
type="text"
class="form-control"
id="username"
placeholder="Change your username"
/>
<div class="input-group-append">
<button class="btn btn-warning" type="button" id="usernameBtn">
Change
</button>
</div>
</div>
</div>
<div class="message-box">
<ul class="list-group list-group-flush" id="message-list"></ul>
<div class="info"></div>
</div>
<div class="card-footer">
<div class="input-group">
<input
type="text"
class="form-control"
id="message"
placeholder="Send new message"
/>
<div class="input-group-append">
<button class="btn btn-success" type="button" id="messageBtn">
Send
</button>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.socket.io/socket.io-1.0.0.js"></script>
<script src="/js/chatroom.js"></script>
</body>
</html>
This is chatroom.js.
(function connect() {
let socket = io.connect("http://localhost:3000")
})();
The problem is I don't know why io.on("connection", socket => { console.log("New user connected"); }); not working here. Everything seems to be OK in Google Chrome console, but the message doesn't appear in VS code terminal when I go to localhost website. The terminal always looks like this when I refresh the page.
vs code terminal
Is there anything wrong with my code?
I solved it already. I change <script src="https://cdn.socket.io/socket.io-1.0.0.js"></script> to <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.5/socket.io.js"></script> and still have no idea what the problem is ,but it works.
I think it's a cors origin problem, use Firefox to see it in the console
And that't how you can resolve it : socket.io, 'Access-Control-Allow-Origin' error

GET method form with ExpressJS - multiple app.get

I want to make a simple login form.
This is the relevant code:
app.get('/login' , (req,res)=>{
app.use(express.static('login'));
res.render(__dirname + '/login/index.ejs');
/*This is load the login page*/
});
index.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>login</title>
</head>
<body>
<h1>Login</h1>
<form action="/" method="GET">
<input type="text" name="email" placeholder="email">
<input type="password" name="password" placeholder="password">
<input type="submit" value="login">
</form>
</body>
</html>
You can see the form is GET method because I don't create/update anything. If I used app.post for detecting the parameters I've used app.post and it was working fine.
But how I handle two app.get ? one for load the page, the second for handle the html form ?
For example:
app.get('/login' , (req,res)=>{
console.log(req.query);
}
Thanks !
I recommend that instead of using the GET method for both the login and the displaying of your website you make your form method POST instead of GET. Then use multer in your express app as a way to parse the received form data.
<form action="/" method="POST">
const multer = require('multer');
const upload = multer();
app.use(upload.array());
app.post('/login', function(req, res){
console.log(req.body);
res.send("recieved your request!");
});

Localhost test: can't get resource using http://localhost:8888

For test purposes I run Apache local web server and I'm setting up a node.js app listening on port 8888 serving as image preprocessor, but unfortunately I'm experiencing problems as described below.
The node app.js is running in the web root directory:
'use strict';
let express= require('express')
,multer = require('multer')
,upload = multer()
,app = express()
//Import imgProcessor module which we would implement later
,imgProc = require('./imgProcessor');
app.get ('/', (req, res, next)=>{
res.sendFile(__dirname+'/appmain.html');
});
app.post('/uploadImg', upload.array('pics'),
(req, res, next)=>{
//Call the convertImgs method and pass the image files as its argument
imgProc.convertImgs(req.files).then(
(imageStringArray)=>{
//After all image processing finished, send the base64 image string to client
res.json(imageStringArray)})});
app.listen(8888, ()=>{
console.log('Hosted on Port 8888')});
The appmain.html page resides in the same web root directory:
<html>
<head>
<title>Upload Image Demo</title>
<link rel="shortcut icon" href="">
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script src="node_modules/materialize-css/dist/js/materialize.min.js"></script>
<link rel="stylesheet" href="node_modules/materialize-css/dist/css/materialize.min.css">
</head>
<body class="container">
<div class="row">
<form id="form1" class="col m4 offset-m4" action="/uploadImg" enctype="multipart/form-data" method="post">
<div class="file-field input-field">
<div class="btn">
<span>File</span>
<input type="file" multiple="" accept="image/jpeg,png" name="pics">
</div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text" placeholder="Upload one or more files">
</div>
</div>
<div class="input-field">
<button type="submit" class="waves-effect waves-light btn">Submit</button>
</div>
<div class="progress" style="display:none">
<div class="indeterminate"></div>
</div>
</form>
</div>
<div class="row img-preview"></div>
<script>
$(function(){
$('#form1').on('submit', function(event){
event.preventDefault();
var data = new FormData(this);
$.each(
$('input[name="pics"]')[0].files,
function(i, file){
data.append('file-'+i, file);
});
$('.progress').css({
display:'block'
});
$.ajax({
type:'POST',
url: $(this).attr('action'),
data:data,
cache:false,
contentType: false,
processData: false,
success:function(data){
for(var i=0;i<data.length;i++){
var template =
'<div class="col m4">
<div class="card">
<div class="card-image">
<img src="'
+ data[i]
+ '"></div></div></div>';
$('.img-preview').append(template);
}
$('.progress').css({
display:'none'
});
},
error: function(err){
$('.progress').css({
display:'none'
});
}
});
})
})
</script>
</body>
</html>
When I use the URL http://localhost:8888 in the browser the html page is loaded (i.e. I can see the buttons and input fields of the form) but the resources requested in the <script> (ex.: node_modules/jquery/dist/jquery.min.js or node_modules/materialize-css/dist/js/materialize.min.js) are not loaded. By the same way the page can't benefit from the unloaded CSS stylesheet.
As opposite, if I try to use the URL http://localhost/appmain.html the page is loaded as expected (I mean: with the correct resources and CSS).
It seems that my Apache Web Server can't serve resources when handling the port number inside the URL. How can I resolve this?
EDIT
Just to simplify: let'say the node app2.js is listening on port 8888 and it has just a method (get) that send to the client the 'Hello World!' page app2main.html. No files to serve. The app2main.html page need only to load a couple of Javascript script and a CSS stylesheet.
app2.js
'use strict';
let express= require('express')
,app = express();
app.get ('/', (req, res, next)=>{
res.sendFile(__dirname+'/app2main.html');
});
app.listen(8888, ()=>{
console.log('Hosted on Port 8888')});
app2main.html
<html>
<head>
<title>Upload Image Demo</title>
<link rel="shortcut icon" href="">
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script
src="node_modules/materialize-css/dist/js/materialize.min.js"></script>
<link rel="stylesheet"
href="node_modules/materialize-css/dist/css/materialize.min.css">
</head>
<body class="container">
<h2> Hello World! </h2>
</body>
</html>
When accessing the URL http://localhost:8888 the 'Hello World!' message appears, but I get the following error (visibile by inspecting the page):
http://localhost:8888/node_modules/jquery/dist/jquery.min.js Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:8888/node_modules/materialize-css/dist/js/materialize.min.js Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:8888/node_modules/materialize-css/dist/css/materialize.min.css Failed to load resource: the server responded with a status of 404 (Not Found)
http://localhost:8888/node_modules/materialize-css/dist/css/materialize.min.css Failed to load resource: the server responded with a status of 404 (Not Found)
Instead I get no error (and the expected style) when accessing the URL http://localhost/app2main.html
As discussed in comments, you should use express.static to serve static content in node.js app. In your case, your static content lies in node_modules directory itself. You can try the following code to load all resources,
e.g. http://localhost:8888/node_modules/jquery/dist/jquery.min.js
app.use('/node_modules', express.static('node_modules'));
Also, you mentioned that when you access http://localhost/app2main.html, then it worked without express.static, because apache web server to serve static files similar to express.static in node.js. That's why
http://localhost/node_modules/jquery/dist/jquery.min.js was working.
Hope it clears your doubt.

model undefined on page reload

I'm trying example from this site. It works fine. But if i separate views,models,routers into separate file it gives me a problem. There is 3 views. WineList view, WineListItemView and winedetails view. WineList view takes collection of wine models as model and winelistItem and winedetails view takes wine as a model.
Router's code is like this
var app = app || {};
app.AppRouter = Backbone.Router.extend({
routes:{
"":"list",
"wines/:id":"wineDetails"
},
initialize:function () {
$('#header').html(new app.HeaderView().render().el);
},
list:function () {
this.wineList = new app.WineCollection();
this.wineListView = new app.WineListView({model:this.wineList});
this.wineList.fetch();
$('#sidebar').html(this.wineListView.render().el);
},
wineDetails:function (id) {
if(this.wineList == undefined)
{
this.wineList = new app.WineCollection();
this.wineListView = new app.WineListView({model:this.wineList});
this.wineList.fetch();
$('#sidebar').html(this.wineListView.render().el);
}
this.wine = this.wineList.get(id);
if (app.router.wineView) app.router.wineView.close();
this.wineView = new app.WineView({model:this.wine});
$('#content').html(this.wineView.render().el);
}
});
On page load it fetches models from server and displays list of wines in sidebar div of page. When i click on particular wine item its details will be displayed in content div of page. That all works fine. But when i reload that page which now contains details of particular,wine model of Winedetails view gives undefined .
I'm intializing the router on main page like this
app.js
var app = app || {};
$(function() {
})
app.router = new app.AppRouter();
Backbone.history.start();
index.html
<!DOCTYPE HTML>
<html>
<head>
<title>Backbone Cellar</title>
<link rel="stylesheet" href="../css/styles.css" />
</head>
<body>
<div id="header"><span class="title">Backbone Cellar</span></div>
<div id="sidebar"></div>
<div id="content">
<h2>Welcome to Backbone Cellar</h2>
<p>
This is a sample application part of of three-part tutorial showing how to build a CRUD application with Backbone.js.
</p>
</div>
<div>
Next page
</div>
<!-- Templates -->
<script type="text/template" id="tpl-header">
<span class="title">Backbone Cellar</span>
<button class="new">New Wine</button>
</script>
<script type="text/template" id="tpl-wine-list-item">
<a href='#wines/<%= id %>'><%= name %></a>
</script>
<script type="text/template" id="tpl-wine-details">
<div class="form-left-col">
<label>Id:</label>
<input type="text" id="wineId" name="id" value="<%= id %>" disabled />
<label>Name:</label>
<input type="text" id="name" name="name" value="<%= name %>" required/>
<label>Grapes:</label>
<input type="text" id="grapes" name="grapes" value="<%= grapes %>"/>
<label>Country:</label>
<input type="text" id="country" name="country" value="<%= country %>"/>
<label>Region:</label>
<input type="text" id="region" name="region" value="<%= region %>"/>
<label>Year:</label>
<input type="text" id="year" name="year" value="<%= year %>"/>
<button class="save">Save</button>
<button class="delete">Delete</button>
</div>
<div class="form-right-col">
<img height="300" src="../pics/<%= picture %>"/>
<label>Notes:</label>
<textarea id="description" name="description"><%= description %></textarea>
</div>
</script>
<!-- JavaScript -->
<script src="js/lib/jquery.min.js"></script>
<script src="js/lib/underscore.js"></script>
<script src="js/lib/backbone.js"></script>
<script src="js/models/WineModel.js"></script>
<script src="js/collections/WineListCollection.js"></script>
<script src="js/Views/WineListView.js"></script>
<script src="js/Views/WineListItemView.js"></script>
<script src="js/Views/WineDetailsView.js"></script>
<script src="js/Views/HeaderView.js"></script>
<script src="js/routers/routers.js"></script>
<script src="js/app.js"></script>
</body>
</html>
I'm new to this backbone technology. please tell me what am i missing
this.wineList.fetch();
fires an asynchronous request to your server, which means that the content will arrive (or not) at some point after executing this line, but your application execution continues whether the response arrived or not. On page reload (assume you have wines/:id in the URL) first you have to fetch the complete list of wines before accessing any particular wine from the collection.
You have to wait until is download the collection, and access the wine with id, after this request is finished.
So after initiating the request continue your application logic in the success callback:
this.wineList.fetch({
success: function(model) {
...
this.wine = model.get(id);
...
}
});

Referencing external files with a node.js server?

I have an Ubuntu 10.04 hosting server which allows me to run node.js off of it. I'm making an test homepage and I have a few files as follows:
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>iSuperMario</title>
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/style.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script src="/nowjs/now.js"></script>
<script src="js/chat.js"></script>
</head>
<body>
<div id="wrapper">
<div id="header">
<img src="images/green_pipe_960.png">
<img src="images/orange_pipe_960.png">
</div>
<div id="chat">
<input type="text" id="text-input">
<input type="button" value="Send" id="send-button">
</div>
<div id="content">
</div>
<div id="rooms">
</div>
</div>
</body>
</html>
reset.css and style.css (which both just contain styling for the index.html page
chat.js (which contains some scripting to implement the barebones chat function for the index.html page)
server.js which is a node.js server utilizing nowjs to serve the index.html page on port 8080 of the Ubuntu server and to implement the chat function:
var fs = require('fs');
var server = require('http').createServer(function(req, response){
fs.readFile(__dirname+'/index.html', function(err, data){
response.writeHead(200, {'Content-Type':'text/html'});
response.write(data);
response.end();
});
});
server.listen(8080);
var everyone = require("now").initialize(server);
everyone.connected(function(){
console.log("Someone has joined!");
});
everyone.disconnected(function(){
console.log("Someone has left...");
});
everyone.now.distributeMessage = function(message){everyone.now.receiveMessage(message);};
So, when I view the page from the server in a browser, none of the external resources (reset.css, style.css, chat.js, green_pipe_960.png and orange_pipe_960.png) are connected properly.
How should I enable these? I mean, if I had to, and it simplified the process a great deal, I could always include the external styles and scripts in index.html. But, the images could never be embedded (at least I think xD).
Thanks!
You need to set your file structure as follows
= main
= index.html
= css
= reset.css
= style.css
= js
= chat.js
= images
= green_pipe..
= orange_pipe..
Alternatively you can change your urls to match your real file structure.
I would like to recommend you use express or something else if you want to server something beyond a very basic prototype.
This webpage might help. Serving Static Files from Node.js.

Resources