Emitted value cannot be added to DIV express.js socket.io - javascript

I have the following app.js
var express = require('express');
var app = express();
// var responseHandlerRouter = require('./routes/responseHandlerRouter.js');
routes = require('./routes');
var server = app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
io = require('/usr/local/lib/node_modules/socket.io').listen(server);
app.use('/', routes(io));
routes.js
var express = require('express');
var router = express.Router();
module.exports = function (io) {
// all of this router's configurations
router.get('/login', function (req, res, next) {
io.emit('notification', 'news');
res.end('well finally I am here');
});
return router;
}
index.html
<!doctype html>
<html>
<head>
<script src="http://127.0.0.1:3000/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:3000/login');
socket.on('notification', function (data) {
console.log(data);
});
</script>
</head>
<body>
<ul id='messages'></ul>
</body>
</html>
When I do a get on the URL, it should emit but its not happening. Its not showing any errors, but fails silently.
Is there anything wrong?
Update
I want to show the "news" in the div.
but I am not able to append this as follows
.... socket.on('notification', function (data) {
$('#messages').html(data);
});
</script>
</head>
<body>
<ul id='messages'></ul>
</body>....
Will make this eligible for bounty

Looks like you are using the router in a wrong way.
Not sure, but I think that app.use('/login', routes(io)) instead of what you've got should do the trick.
In your implementation your router receives only GETs to '/'
EDIT: although the answer is accepted, the real solution is in the comments below (wrong connection url specified)

Related

How to fix error Cannot GET with Node.js / Express

I have a class Server :
Server.js
const express = require('express');
class Server {
constructor() {
this.app = express();
this.app.get('/', function(req, res) {
res.send('Hello World');
})
}
start() {
this.app.listen(8080, function() {
console.log('MPS application is listening on port 8080 !')
});
}
}
module.exports = Server;
I start my server in app.js :
const Server = require('./server/Server');
const express = require('express');
const server = new Server();
server.start();
server.app.use('/client', express.static(__dirname + '/client'));
My html code :
index.html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript" src="js/index.js"></script>
<title></title>
</head>
<body>
<div id="historique">
<button v-on:click="openHistorique">
Historique Proface
</button>
</div>
</body>
</html>
My index.js :
window.onload = function () {
var hist = new Vue({
el:'#historique',
methods: {
openHistorique: function() {
console.log("On clique");
document.location.href="../AffichageHistorique/index.php";
}
}
})
}
And the folder structure :
client
AffichageHistorique
index.php
js
index.js
index.html
server
Server.js
app.js
When I click on the button in index.html, I want to open index.php but i have the error Cannot GET /AffichageHistorique/index.php and I don't see how to fix the problem.
Here:
this.app.get('/', function(req, res) {
… you wrote a handler for what happens when the client tries to get /.
You haven't written one for /AffichageHistorique/index.php.
server.app.use('/client', express.static(__dirname + '/client'));
… comes close, but since your URL doesn't start with /client, it doesn't get hit.
Even if it did, it wouldn't execute the PHP.
The static module is for serving static files, not for executing PHP.
If you're using PHP, then consider using a server that PHP is designed to work with (like Apache HTTPD or Lighttpd).

How to find a function (GET, POST, ... ) by index.js with an Express router?

I would like to install a router in Express. I followed a good tutorial but my code still don't find my function get/users.
My function works when I put it on index.js
index.js :
const express = require('express');
const app = express();
app.use(express.json());
const users = require('./api/user');
app.use('/users', users);
./api/user.js :
const {user, validate} = require('../models/user');
const mongoose = require('mongoose');
const express = require('express');
const router = express.Router();
const mysql = require('mysql')
const connection = mysql.createConnection({
host: 'localhost',
user:'root',
password: 'root',
database: 'mf_consultation'
});
router.get('/users', (req, res) => {
console.log("Enter in get request");
const queryString = "SELECT * FROM user"
connection.query(queryString, (err, rows, fields) => {
if(error) return res.status(400).send(result.error.details[0].message);
console.log("I think we fetched users successfully");
res.json(rows);
});
});
module.exports = router;
I have this result on postman
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot GET /users</pre>
</body>
</html>
My console didn't display the console.log "Enter in get request".
Have you an idea ? Thank you in advance.
In your index.js, you have specified this:
app.use('/users', users);
This means that any route that starts with /users should be handled inside your users router.
Then, in your users.js, you have this:
router.get('/users', (req, res) => {
// code here
}
This means that your express application will handle /users/users instead of just /users. The first /users leads your express application to use your user router, while the second /users leads your user router to use the GET function defined inside the router.
If you want to reach the controller/handler with only /users, there are 2 ways:
define this in your index.js
app.get('/users', (req, res) => {
// code here
});
replace your router.get('/users', ... with router.get('/', ... in your user router.
Both ways should work, just that the structure of your code base will change a little.

Can't load static files in index.html

I'm trying setup simple app with node, express and angular2. The problem is that, when I run localhost, open it in browser, I get errors: "Uncaught SyntaxError: Unexpected token <". I think it happens because of incorrect path or wrong code in my node/express files.
For example, when I'm trying open library file in source, I always get index.html code :
Here is the folder structure:
Below I'll show full code
index.js
'use strict'
// require dependencies
let express = require('express');
let bodyParser = require('body-parser');
let path = require('path');
// require our custom dependencies
let router = require('./router');
let app = express();
const PORT = process.env.PORT || 4000;
// get the data from a POST
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
//share folder with static content
app.use(express.static(__dirname + '../frontend/build'));
app.use('/', router);
app.listen(PORT, function() {
console.log('Example app listening on port', PORT);
});
router.js
let express = require('express');
let router = express.Router();
let path = require('path');
let User = require('./models/user');
router.use(function(req, res, next) {
console.log('request to', req.path);
next();
});
router.route('/users')
.get(function(req, res) {
User.find(function(err, users) {
if (err) {
res.send(err);
}
res.json(users);
});
});
router.get('*', function (req, res) {
res.status(200).sendFile(path.resolve('frontend/build/index.html'));
})
module.exports = router;
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My Angular 2 App!</title>
<base href="/">
<!-- load the dependencies -->
<script src="./assets/libs/core-js/client/shim.min.js"></script>
<script src="./assets/libs/zone.js/dist/zone.js"></script>
<script src="./assets/libs/reflect-metadata/Reflect.js"></script>
<script src="./assets/libs/systemjs/dist/system.src.js"></script>
<script src="./systemjs.config.js"></script>
<script>
System.import('app').catch(function(err) {
console.error(err);
});
</script>
</head>
<body>
<h1>Hello</h1>
</body>
</html>
Thanks!
Update
I changed in router.js from this
router.get('*', function (req, res) {
res.status(200).sendFile(path.resolve('frontend/build/index.html'));
});
to this
router.get('/', function (req, res) {
res.status(200).sendFile(path.resolve('frontend/build/index.html'));
});
and now I have 404 error, files not found

Is it possible to return data from webage to main server

This may be a (and probably is) dumb question but I have been trying to set up a server that will work with http and websockets. I would like the result of a button press to change a value within the server which can then be sent across a websocket.
This is my main server code:
var express = require('express');
var app = express();
var expressWs = require('express-ws')(app);
app.use(function (req, res, next) {
console.log('middleware');
req.testing = 'device-protocol';
return next();
});
app.get('/button.htm', function (req, res) {
res.sendFile( __dirname + "/" + "button.htm" );
});
app.ws('/', function(ws, req) {
ws.on('message', function(msg) {
console.log("Message received from client: %s", msg);
ws.send(JSON.stringify(msg));
given, should query
});
console.log('socket', req.testing);
});
var server = app.listen(8080, function () {
var host = server.address().address
var port = server.address().port
console.log("Test app listening at http://%s:%s", host, port)
})
And here is my button webpage:
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8 /angular.min.js"></script>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.showMe = false;
$scope.myFunc = function() {
$scope.showMe = !$scope.showMe;
}
});
</script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<button ng-click="myFunc()">Click Me!</button>
</div>
</body>
</html>
Is it possible to hand back a variable from the webpage's button to the main server and have it continuously update?
Just have myFunc to make a plain http request to your server, in which it will receive a value and broadcast it through your websockets connection.

Modularizing Socket.io with Express 4

I'm trying to modularize my application files and I'm having problems with Socket.io. I would like to use the io inside my routes.js. Something like this:
var router = require('express').Router();
var io = require('./sockets/my-io');
router.get('/', function(req, res) {
io.emit('request-detected');
});
module.exports = router;
But I can't do, because the socket.io needs the app server, and when I'm inside the routes.js file, the app server is not listening or being exported yet.
Can you give me a solution, or any other approach to this problem?
Here's what I have, and if it's possible, I would like to keep the file structure:
app.js
var app = require('express')();
var routes = require('./routes');
/* ... */
app.use('/contacts', routes);
module.exports = app;
bin/www
#!/usr/bin/env node
var app = require('../wallet');
var server = app.listen(port, function() {
debug('Express is listening o port ' + port);
});
routes.js
var router = require('express').Router();
router.get('/', function(req, res) {
console.log('hey');
});
module.exports = router;
You can do it by passing the io variable to your routes module.
bin/www
#!/usr/bin/env node
var app = require('./app');
var server = app.listen(3000, function() {
console.log('Express is listening on port 3000');
}); // start the server
var socket = require('./socket')(server); // require socket.io code
var routes = require('./routes')(socket); // require routes
app.use('/', routes);
app.js
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.set('views engine', 'ejs');
app.set('views', __dirname + '/');
module.exports = app;
socket.js
var socketio = require('socket.io');
function init(server) {
var io = socketio(server);
io.on('connection', function (socket) {
console.log("socket connected");
socket.on('newEvent', function (data) {
console.log(data);
});
});
return io;
}
module.exports = init;
routes.js
var express = require('express');
var route = express.Router();
function init(io) {
route.get('/', function (req, res) {
res.render('index.ejs', {});
setTimeout(function() {io.emit('newEvent', {message: "Hi from the server"})}, 2000);
});
return route;
}
module.exports = init;
The code above worked for me. However, I'm not sure why you want to do that.
Inside the router, you still have full control of what you want to send to the user via html, so you can just add the data to the html directly.
The idea of socket.io is that you can send data between the client and back once he has loaded the html and established a connection to your server with socket.io.
As you can see in the routes.js, I had to add a timeout to the emit. This is because the socket event will be emit before the browser has reloaded the page. In my case the browser logged the event and then immediately refreshed, losing the data you just sent.
Another problem is that you don't know anything about the socket of the client that is requesting the page because he hasn't connected yet. This means that calling io.emit() will send the event to all connected sockets.
As I said, this really depends on what exactly you want to do.
EDIT:
Instead of updating your contacts using ajax, you can do that with socket.io.
socket.js
var socketio = require('socket.io');
function init(server) {
var io = socketio(server);
io.on('connection', function (socket) {
console.log("socket connected");
socket.on('newContact', function (data, callback) {
// add data.contactName to db
// after adding something, you use the callback to
// send the added data back to the client
// callback(newContact);
});
});
return io;
}
module.exports = init;
index.html
<script type="text/javascript" >
var socket = io();
// call this emit when the user wants to add a contact
socket.emit('newContact', {contactName: name}, function(newContact) {
// here you will get the result from the server and you can
// update the html with jquery for example
});
</script>
If i understand your question correctly ,maybe you can try this way.
in your routes.js file
var app = require('./app');
var server = require('http').createServer(app);
var io = require('./sockets/my-io')(server);
var route = app.Router();
in your app.js file
var port = process.env.PORT || 3000;
app.listen(port,function(){
console.log('server on port ' + port)
})

Categories

Resources