Why does 'import socket.io' doesn't work for me? - socket.io

I'm learning Socket.io and practicing the demo tutorial with individual client side script file.
However, it didn't work as expected.
Here is my code.
client side HTML: index.html
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
<ul id="messages"></ul>
<form id="form" action="">
<input id="input" autocomplete="off" /><button>Send</button>
</form>
<script src="./app.js"></script>
</body>
</html>
client side JS: app.js
import { io } from "socket.io-client";
var socket = io('http://localhost:3000');
var messages = document.getElementById('messages');
var form = document.getElementById('form');
var input = document.getElementById('input');
form.addEventListener('submit', function(e) {
e.preventDefault();
if (input.value) {
socket.emit('chat message', input.value);
input.value = '';
}
});
socket.on('chat message', function(msg) {
var item = document.createElement('li');
item.textContent = msg;
messages.appendChild(item);
window.scrollTo(0, document.body.scrollHeight);
});
server side JS: index.js
const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const port = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
console.log('a new user join: ', socket.id);
socket.on('chat message', msg => {
io.emit('chat message', msg);
});
});
http.listen(port, () => {
console.log(`Socket.IO server running at http://localhost:${port}/`);
});
After node index to execute my server and open localhost:3000 on my browser, the console.log should tells 'a new user join: xxx', but it didn't.
Is there anything wrong with client side app.js?

Related

ExpressJS XMLHttpRequest Routing Error

I have an issue where I am trying to pass my file information in query parameter form to the route that I have set up to upload my AWS file and then return the url. The issue I am running into is that the form is located within the view file accessed with the /create/comment route and prepended to all of my routes is /app. In my XMLHttpRequest I am requesting /app/sign and the file query parameters, but for some reason it keeps prepending this with /app/create or /app/create/app/sign, which is why I have 404 error. Is there a way a specific method to prevent the prepending of /app/create?
Error function at xhr.send();
function sign_request(file, done) {
var xhr = new XMLHttpRequest();
console.log(xhr);
console.log(file);
xhr.open("GET", "app/sign?file_name=" + file.name + "&file_type=" + file.type);
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
var response = JSON.parse(xhr.responseText);
console.log(response);
done(response);
}
};
xhr.send();
};
Error Message:
comment:139 GET http://localhost:3000/app/create/app/sign?file_name=File-name.png&file_type=image/png 404 (Not Found)
Here is my route setup:
var express = require('express');
var router = express.Router();
router.use('/app');
var config = require(path.resolve(__dirname, '..', '..','./config/config.js'));
var models = require('../models/db-index');
var fs = require('fs');
var aws = require('aws-sdk');
/*==== /SIGN ====*/
router.get('/sign', function(req, res){
aws.config.update({accessKeyId: config.awsAccessKeyId, secretAccessKey: config.awsSecretAccessKey});
var s3 = new aws.S3()
var options = {
Bucket: config.awsBucket,
Region: 'us-east-1',
Key: req.query.file_name,
Expires: 60,
ContentType: req.query.file_type,
ACL: 'public-read'
}
s3.getSignedUrl('putObject', options, function(err, data){
if(err) return res.send('Error with S3')
res.json({
signed_request: data,
url: 'https://s3.amazonaws.com/' + S3_BUCKET + '/' + req.query.file_name
});
});
});
router.get('/create/comment',function(req, res){
models.DiscoverySource.findAll({
where: {
organizationId: req.user.organizationId
}, attributes: ['discoverySourceName']
}).then(function(discoverySource){
res.render('pages/app/comment-create.hbs',{
discoverySource: discoverySource
});
});
});
Form (Accessed at /app/create/comment):
<!DOCTYPE html>
<head>
{{> app/app-head}}
</head>
<body>
{{> app/app-navigation}}
<div class="container">
<div class="col-md-12">
<div class="row-form-container">
<label for="report-link">File Attachment:</label>
<input type="file" name="fileAttachment" id="image">
<img id="preview">
</div>
</div>
<script type="text/javascript">
function upload(file, signed_request, url, done) {
var xhr = new XMLHttpRequest();
xhr.open("PUT", signed_request);
xhr.setRequestHeader('x-amz-acl', 'public-read');
xhr.onload = function() {
if (xhr.status === 200) {
done();
};
};
xhr.send(file);
}
function sign_request(file, done) {
console.log('work please');
var xhr = new XMLHttpRequest();
console.log(xhr);
console.log(file);
xhr.open("GET", "app/sign?file_name=" + file.name + "&file_type=" + file.type);
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
var response = JSON.parse(xhr.responseText);
console.log(response);
done(response);
}
};
xhr.send();
};
document.getElementById("image").onchange = function() {
var file = document.getElementById("image").files[0]
if (!file) return
sign_request(file, function(response) {
upload(file, response.signed_request, response.url, function() {
document.getElementById("preview").src = response.url
});
});
};
</script>
</body>
Adding a / before app/sign when you send a request will prevent the prepending of current subpath.
Try:
xhr.open("GET", "/app/sign?file_name=" + file.name + "&file_type=" + file.type);

complex nodejs url mapping

I need help in url mapping in express.js framework in nodejs.
router.get('/first/:second_param', function(res,req){
//processing second_param and rendering a template,
res.render('first.html');
});
router.get('/first/:second_param/get_items', function(res,req){
//again evaluating second_param and and responding accordingly
res.send(jsonData);
});
Is this kind of routing possible in Express 4.0?
first.html makes a ajax request at url './get_items'
Yes, it is possible to do it with Express 4.0.
Here is an example:
you need to install ejs and express: npm install ejs express
app.js file:
var express = require('express');
var app = express();
app.set('view engine', 'ejs');
app.get('/', function(req, res) {
res.redirect('/home/2');
});
app.get('/home/:itemId', function(req, res) {
var itemId = req.params.itemId;
console.log(itemId);
res.render('index');
});
app.get('/api/items/:itemId', function(req, res) {
var itemId = req.params.itemId;
console.log('item id: %s', itemId);
res.json([{name: 'item1'}]);
});
app.listen(8080, function() {
console.log('server up and running at 8080');
});
views/index.ejs file:
<!doctype html>
<html>
<head>
</head>
<body>
<h1>Hello World!</h1>
<script>
function responseGET() {
if(this.readyState !== 4 || this.status !== 200) return;
alert(this.responseText);
}
function getItems(URL) {
var request = new XMLHttpRequest();
request.open('GET', URL, true);
request.onreadystatechange = responseGET.bind(request);
request.send(null);
}
function domReady() {
getItems('http://localhost:8080/api/items/1');
}
document.addEventListener('DOMContentLoaded', domReady);
</script>
</body>
</html>
Basically I am have a server which is serving an index.html when someone requests at /home/:itemId and also I am exposing another route for serving items /api/items/:itemId.
From the client side once the DOM is ready I am requesting to /api/items/:itemId some items which then are displayed in the index html.

Load chat messages upon page load using websockets on node.js

Hi I'm developing a chat application using nodejs I'm new to node so I'm not very well familiar on its capabilities... I have made my application store its chat messages on mysql database only but I need to also display the past message and current one of a user here is the index.js
var mysql = require('mysql');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var validator;
var connection = mysql.createConnection({ // setup the connection
host : "localhost",
user : "root",
password: "",
})
function getStdout(command, args, fn) {
var childProcess = require('child_process').spawn(command, args);
var output = '';
childProcess.stdout.setEncoding('utf8');
childProcess.stdout.on('data', function(data) {
output += data;
});
childProcess.on('close', function() {
fn(output);
});
}
app.use('/assets', require('express').static(__dirname + '/assets'));
app.use('/temp', require('express').static(__dirname + '/temp'));
app.get('/', function(req, res){
//res.sendfile(__dirname + '/' +validator);
res.send(validator);
});
//you should have only one io.on('connection')
io.on('connection', function(socket){
socket.on('chat message', function(msg){
console.log('message: ' + msg);
var myMsg= msg; // obtain the incoming msg
var strQuery = "INSERT INTO chat_storage(chat) VALUES(?)"; // your SQL string
connection.query("use schat"); // select the db
connection.query( strQuery, myMsg, function(err, rows){
if(err) {
// handle errors
} else {
io.emit('chat message', msg);
// message received
}
});
});
});
getStdout('php', ['message.php'], function(output) {
validator = output;
//start your server after you get an output
http.listen(3000, function(){
console.log(validator);
});
});
now here is the page for loading the chat messages
<?php startblock('script') ?>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
$(document).ready(function(){
$.ajax({
url: "localhost:3000/includes/message/store_chat.php",
type: "POST",
dataType: "html",
success: function (result) {
$("#messages").html(result);
}
});
});
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
</script>
<?php endblock(); ?>
My idea was to the chat messages once the page loads I was trying to achieve it using ajax as you can see on the script that I have provided.. but it was no good didnt work at all Please help me
Couple of suggestions:
1) Store all of your messages in-memory ( unless you see this growing to several MB of data ) so that you can catch up any new client quickly.
2) Use socket.io to send the chat messages that have been stored rather than an AJAX call.
I've also included SequelizeJS instead of raw MySQL - It has a much cleaner raw query model and allows you to transition into a DAO model of sorts if you want to.
app.js
// Highly suggest replacing raw mysql with SequelizeJS - http://sequelizejs.com/
var Sequelize = require('sequelize'),
app = require('express')(),
http = require('http').Server(app),
io = require('socket.io')(http);
var validator;
var messages = [];
var sequelize = new Sequelize('schat', 'root', '');
app.use('/assets', require('express').static(__dirname + '/assets'));
app.use('/temp', require('express').static(__dirname + '/temp'));
app.get('/', function(req, res){
res.send(validator);
});
io.on('connection', function(socket){
// Send all previously sent messages
for( i in messages ) {
socket.emit('chat message', messages[i]);
}
socket.on('chat message', function(msg){
console.log('message: ' + msg);
// Push the message into the in-memory array.
messages.push(msg);
// Storage the message for when the application is restarted.
sequelize.query('INSERT INTO chat_storage(chat) VALUES("'+msg'")').success(function() {
// Insert was successful.
}).error(function (err) {
// Error inserting message
});
// Send the message to everyone
socket.broadcast.emit('chat message', msg);
});
});
function getStdout(command, args, fn) {
var childProcess = require('child_process').spawn(command, args);
var output = '';
childProcess.stdout.setEncoding('utf8');
childProcess.stdout.on('data', function(data) {
output += data;
});
childProcess.on('close', function() {
fn(output);
});
}
// Load Messages
sequelize.query('SELECT chat FROM chat_storage').success(function (rows) {
for( i in rows ) {
messages.push(rows[i].chat);
}
getStdout('php', ['message.php'], function(output) {
validator = output;
http.listen(3000, function(){
// Start server.
});
});
}).error(function (err) {
// Error!
});
php include
<?php startblock('script') ?>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#messages').append($('li').text($('#m').val()));
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
</script>
<?php endblock(); ?>

node.js ajax express show restful data on a web page

I am newbie in node.js development and I have a particular problem. I want to create a one page web app with node.js which will the user will submit request data and then gets data back from imdb api and will show them on the same page. My code is the following
server.js
#!/usr/bin/env node
var express = require('express');
var app = express();
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
var fs = require('fs');
var inputFile = fs.readFileSync('index.html').toString();
console.log(inputFile);
app.get('/', function(request, response) {
response.send(inputFile);
});
var port = process.env.PORT || 8080;
app.listen(port, function() {
console.log("Listening on " + port);
})
app.post('/', function(req, res){
if (req.body.mysearch == ""){
var search = "heroes";
}else{
var search = req.body.mysearch;
}
console.log(search);
var http = require('http');
http.get("http://www.imdbapi.com/?t=" + search, function(res) {
console.log("Got response: " + res.statusCode);
var data = '';
res.on('data', function (chunk){
data += chunk;
})
res.on('end',function(){
// the whole of webpage data has been collected. parsing time!
var obj = JSON.parse(data);
console.log( obj.Title );
})
}).on('error', function(e) {
console.log("Got error: " + e.message);
})
});
index.html
<html>
<head>
<meta charset="utf-8">
<title>Title of the document</title>
</head>
<body>
<form id="myform" method="post" action="/"enctype="application/x-www-form-urlencoded">
<input type="text" id="search" name="mysearch">
<input type="submit" id="mysubmit" value="Search IMDB">
</form>
<div id="myTitle">
</div>
</body>
</html>
The code so far has successfully parsing the data from imdb and shows them on the console. The question is how I am going to print them on the web page (e.g on the div tag) without reload the page (ajax)
I had a similar question regarding re-rendering of div that got answered
how-to-re-render-html-div-in-node-js
Basically solution was to use client side frameworks like Angular.js to help in re-rendering via 2 way data binding.

socket.io not working in Chrome

i'm trying the this simple socket.io example and it works in Safari (send/receive from both sides). However, in the Chrome the client receives messages but the server won't receive messages sent by the client
index.html
<!doctype html>
<html>
<head>
<title>web sockets</title>
<meta charset="utf-8">
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:8888');
socket.on('news', function (data) {
console.log(data);
writeMessage(data);
socket.emit('my other event', { my: 'data' });
});
function writeMessage(msg) {
var msgArea = document.getElementById("msgArea");
if (typeof msg == "object") {
msgArea.innerHTML = msg.hello;
}
else {
msgArea.innerHTML = msg;
}
}
</script>
</head>
<body>
<div id="msgArea">
</div>
</body>
</html>
server.js
var app = require('http').createServer(handler)
, io = require('/usr/local/lib/node_modules/socket.io').listen(app)
, fs = require('fs')
app.listen(8888);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
Am I missing something? Chrome is on v.19
You can use http://socket.io-test.com to see if the problem is with your browser/proxy or your code.

Resources