I am newbie and starting learning socket.io. I created my backend with express-generator, I installed all required dependencies and the server working fine with no error, however, when I try to connect socket.io from frontend in React it gives many errors and I am not able to connect to connect, I have seen all the question and answer but cannot fix it, all code is given below.
info: I have exported server from bin/www file, and import it in app.js in backend and all modules version are latest
var server = http.createServer(app);
exports.server = server;
"Express Server"
var createError = require("http-errors");
var express = require("express");
var path = require("path");
var cookieParser = require("cookie-parser");
var logger = require("morgan");
var cors = require("cors");
const { server } = require("./bin/www");
var io = require("socket.io")(server);
var indexRouter = require("./routes/index");
var usersRouter = require("./routes/users");
var app = express();
// view engine setup
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "jade");
app.use(cors());
app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, "public")));
// Socket.io config
io.on("connection", (socket) => {
console.log("Connected");
});
app.use("/", indexRouter);
app.use("/users", usersRouter);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
});
// error handler
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get("env") === "development" ? err : {};
// render the error page
res.status(err.status || 500);
res.render("error");
});
module.exports = app;
"React"
import React from "react";
import socket from "socket.io-client";
import "./App.css";
const ENDPOINT = "http://localhost:3000";
function App() {
const io = socket(ENDPOINT);
return (
<div className="App">
<h1>Working</h1>
</div>
);
}
export default App;
Logs in backend
GET /socket.io/?EIO=4&transport=polling&t=NRtAs89 404 14.138 ms - 1362
GET /socket.io/?EIO=4&transport=polling&t=NRtAsNq 404 8.662 ms - 1362
GET /socket.io/?EIO=4&transport=polling&t=NRtAtc3 404 10.450 ms - 1362
GET /socket.io/?EIO=4&transport=polling&t=NRtAtrY 404 15.608 ms - 1362
GET /socket.io/?EIO=4&transport=polling&t=NRtAv3j 404 13.641 ms - 1362
GET /socket.io/?EIO=4&transport=polling&t=NRtAvJH 404 10.490 ms - 1362
Logs in console frontend
The server is not listening for any incoming connection. You didn't start the server as far as I can tell from your code. That's why the frontend is giving you a 404 not found. You have to call .listen()
I am putting everything in one file for simplicity's sake. You can separate them later one for your file in /bin/www/
const express = require('express');
// Initialize the app
const app = express();
// Initialize socket.io server
const server = require('http').createServer(app);
const io = require('socket.io')(server);
PORT = 3003
// Start the Server (socket.io + express)
server.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
});
Update:
If you want to bind socket.io with express, you will have to bind it before you call .listen() Otherwise, socket.io won't start.
Just tested with express-generator myself. You will need to move the socket.io logic into /bin/www. Like the following:
const server = require('http').createServer(app);
const io = require('socket.io')(server);
Side Note:
Personally, I suggest you not to use express-generator if you are going to combine it with socket.io. express-generator gives you a rigid boilerplate that undoubtedly includes lots of things that are irrelevant to your app. Plus the template is still using var to assign variables. ES6 has been out there for 6 years already.
Related
I'm following the Beginners Series to Node JS by Microsoft. At 3.47 into video 18 of 26
my sample code throws 'RequestError: Error: connect ECONNREFUSED 127.0.0.1:5000' whereas the tutorial is successful
Below is my sample code as I followed along. Can you let me know what I'm missing.
Thanks
file name is App.js
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser'); // Read info user/client sends to server
const package = require('./package.json');
const port = process.env.port || process.env.PORT || 5000;
const apiRoot = '/api'; // register the router with the app
const app = express();
// configure app
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(cors({origin: /hhtp:\/\/localhost/})); // by default browsers are allowed to access APIs that are on the servere from which the page was rendered
app.options('*', cors()); // using cors allows access from some where else. This allows 1 site to render the client and another to manage the server
// configure routes
const router = express.router();
router.get('/', (req, res) => { // the '/' is the default path. req = request. res = response
res.send(`${package.description} - v${package.version}`);
});
// register routes
// tell app to use registered router with the app
app.use(apiRoot, router) ; // specify api route and then add in the router
app.listen(port, () => {
console.log('server is up!');
});
I have a node & express app that is currently hosted on a shared hosting. I would like to run and manage the app using Phusion Passenger. My hosting account supports nodejs applications managed by Passenger which i have never used before.
The server code generated when setting up the Node app is the basic server setup as below.
var http = require('http');
var server = http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
var message = 'It works!\n',
version = 'NodeJS ' + process.versions.node + '\n',
response = [message, version].join('\n');
res.end(response);
});
server.listen();
I would like to replace this with the code below that has elements of express that i am using to serve my API routes.
//import modules
var express = require('express'),
bodyParser = require('body-parser'),
morgan = require('morgan'),
cors = require('cors');
path = require('path');
var app = express();
var port = process.env.PORT || 3000;
//import database connection from dbconnect.js file
var mysql = require('./dbconnect/dbconnect');
//Parse as urlencoded and json.
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());
//adding middleware - cors
app.use(cors());
//Http logger
app.use(morgan('dev'));
//Uncomment for production
//app.use(express.static(__dirname + '/public'));
// Point static path to public
app.use(express.static(path.join(__dirname, 'public')));
//import routes from /routes/routes.js
var user = require('./routes/Users');
route = require('./routes/route');
router = require('./router/router');
//adding routes
app.use('/api', user, route, router);
// Catch all other routes and return the index file
app.get('/*', (req, res) => { res.sendFile(path.join(__dirname, '/public/index.html'));
});
app.use(function (req,res,next){
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "x-access-token, Origin, Content-Type, Accept");
next();
});
app.listen(port, function() {console.log('Server started at http://localhost:'+port+'/');});
but i get the error:
I am currently running my server script on the shared server using Forever, which is working fine but that hasn't been efficient, so i would like to switch to using Passenger.
Are you able to set your NODE_ENV=development and then look at your page again? It will likely output a lot more information, why it throws the Error.
With the error information, we can have a better look at what might be wrong.
Thanks,
Marc
I suspect it has to do with your routes and it not finding the files.
I tried to get socket.io to run, but I always get a client error, so I think there is a logic bomb inside the code.
app.js
const express = require('express');
const app = express();
const router = express.Router();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.set('socketio', io);
const expressLayouts = require('express-ejs-layouts');
module.exports = router;
app.use(express.static(__dirname));
app.use(express.urlencoded({ extended: true }));
app.use(expressLayouts);
app.set('view engine', 'ejs');
app.use(function(req, res, next) {
next();
});
io.on('connection', function(socket){
console.log('a user connected');
});
app.use('/', require('./routes/test.js'));
const PORT = process.env.PORT || 8081;
app.listen(PORT, console.log(`Server started on port ${PORT}`));
Inside the route file I open the page
test.js
const express = require('express');
const router = express.Router();
// Dashboard
router.get('/start', (req, res, next) => {
res.render('index2', {
caseArray: 'eins'
});
});
module.exports = router;
And finally inside the template I added:
<script
src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"
></script>
<script src="/socket.io/socket.io.js"></script>
<script>var socket = io();</script>
But I always get an error message inside the browser console:
GET http://localhost:8081/socket.io/socket.io.js net::ERR_ABORTED 404 (Not Found)
(index):24 Uncaught ReferenceError: io is not defined
at (index):24
As I understand from all the tutorial is, that node will send the socket.io within the request to the html page and that with the html page the server get connected. But there is no connection message because the files do not exists. Where is my problem? In client or server?
It seems node is trying to locate socket.io's js files on your server on the route /socket/socket.io.js which I assume you haven't defined
I would suggest you use Socket io's cdn link and place it between your html header tags
<script src='https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.js'></script>
For all with a similar problem. I solved it by using
server.listen(PORT, console.log(`Server started on port ${PORT}`));
instead of using
app.listen(PORT, console.log(`Server started on port ${PORT}`));
I'm using Angular 7 to send a http request to an Express 4 backend code, but keep getting a 404 response in return. I think it might be an issue with the way I've listed the path for the http request, but not sure. This is the first time I'm attempting something like this. I have set up a proxy.conf.js file in Angular to allow from cross origin communication (angular runs on localhost:4200, express on localhost:8085). My Express code is saved under C:/ABC/myapp. Here's the relevant code:
Angular proxy.conf.js file:
{
"/": {
"target": "http://localhost:8085",
"secure": false,
"logLevel": "debug"
}
}
Angular service code which sends the http request:
export class ContactUsService {
private url = '/contactus';
private result: any;
message: string;
addMessage(contactUsMessage: contactUsInterface): Observable<contactUsInterface> {
return this.http.post<contactUsInterface>(this.url, contactUsMessage). (retry(3));
};
constructor(private http: HttpClient) {}
};
Express app.js code:
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var createError = require('http-errors');
var express = require('express');
var logger = require('morgan');
var mongoose = require('mongoose');
var path = require('path');
var winston = require('winston');
var contactUsRouter = require(path.join(__dirname, 'routes', 'contactUs'));
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/contactus', contactUsRouter);
app.use(function(req, res, next) {
next(createError(404));
});
app.use(function(err, req, res, next) {
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
contactUs.js code (for contactUsRouter):
var express = require('express');
var router = express.Router();
var contactUsMessage = require('../models/contactUsMessage');
router.route('/contactus')
.get(function(req,res,next){
res.send("Hello")
})
.put(function(req,res,next){
res.send("Hello")
});
module.exports = router;
When I reach the contactus page (url: localhost:4200/contactus) and execute the submit button for the form, I get the following errors:
In the browser console: "HTTP404: NOT FOUND - The server has not found anything matching the requested URI (Uniform Resource Identifier).
(XHR)POST - http://localhost:4200/contactus"
In the npm log: "POST /contactus 404 3.081 ms - 2128
Error: Failed to lookup view "error" in views directory "C:\ABC\myapp\views".
Any words of wisdom on what I'm doing incorrectly?
Currently you are exposing a route of POST /contactus/contactus because you are specifying a base route with the statement app.use('/contactus', contactUsRouter);, then adding/appending an additional/extra /contactus with the registration of the POST/PUT routes.
Try change the POST route to path to just '/':
var express = require('express');
var router = express.Router();
var contactUsMessage = require('../models/contactUsMessage');
router.route('/')
.get(function(req,res,next){
res.send("Hello")
})
.post(function(req,res,next){
res.send("Hello")
});
module.exports = router;
Hopefully that helps!
Your proxy conf file is not working properly.
The requests are still trying to look for a POST method route /contactus in angular application running on port 4200 ((XHR)POST - http://localhost:4200/contactus) which does not exist and hence you are getting a 404.
Make sure you have followed the steps mentioned on official angular website - Add Proxy for backend server - angular.io
It will be advisable if you use proxy path /api instead of / . Something like this
{
"/api": {
"target": "http://localhost:8085",
"secure": false
}
}
Hope it helps
Here is my node server.js it is in the project root with its own npm config. All Angular files are in /client hence after ng build the dist will be at client/dist
const express = require('express');
const colors = require('colors');
const bodyParser = require('body-parser');
const path = require('path');
const cors = require('cors');
const PORT = process.env.port||'3200';
// init "app"
const app = express();
app.use(cors({origin: `http://localhost:4200`}));
// angular entry point
app.use(express.static(path.join(__dirname, 'client/dist')));
//parse incoming data before routes
app.use(bodyParser.json())
// api routes
app.use('/api',require('./api/api'));
// error middleware
app.use(function(err, req, res, next){
console.log(`${err}`.red.bold)
res.status(422).send({error: err.message });
});
// listen
app.listen(PORT, function(){
console.log(`app running on ${PORT}...`.magenta);
});
When I go to the server http://localhost:3200/ I see my angular app. and when I go to http://localhost:3200/api/someExpressRoute I get my api functions. great
Now I need to figure out how to serve angular routes. for example http://localhost:3200/about is part of my angular single page app. But when I go to that url the server doesnt know what to do.
How do I configure this server to handle http://localhost:3200/* as an angular route that is served from index?
Here's how I serve my angular application via nodejs:
var express = require('express'),
path = require('path'),
fs = require('fs');
var compression = require('compression');
var app = express();
var staticRoot = __dirname + '/';
var env = process.env.NODE_ENV || 'development';
app.set('port', (process.env.PORT || 5000));
app.use(compression());
/* other middleware */
/* place any backend routes you have here */
app.use(function(req, res, next) {
//if the request is not html then move along
var accept = req.accepts('html', 'json', 'xml');
if (accept !== 'html') {
return next();
}
// if the request has a '.' assume that it's for a file, move along
var ext = path.extname(req.path);
if (ext !== '') {
return next();
}
fs.createReadStream(staticRoot + 'index.html').pipe(res);
});
app.use(express.static(staticRoot));
app.listen(app.get('port'), function() {
console.log('app running on port', app.get('port'));
});
When serving the application, ensure all of your frontend dist files are in the same folder as this file (which I call index.js)