I have the following server file:
const express = require('express')
const app = express()
const server = require('http').Server(app)
const io = module.exports.io = require('socket.io')(server)
const PORT = process.env.PORT || 3231
const SocketManager = require('./SocketManager')
app.use(express.static(__dirname + '/../../build'))
io.on('connection', SocketManager)
server.listen(PORT, ()=>{
console.log("Connected to port:" + PORT);
})
And I am connecting it on the front end like so:
import React, { Component } from 'react';
import io from 'socket.io-client';
import Game from '../Game/Game';
import axios from 'axios'
const socketUrl = "/"
const socket = io(socketUrl)
But I keep getting this in my console:
Failed to load resource: the server responded with a status of 405 (Not Allowed)
I really am not sure what to change or set up to rectify what is an error.
My set up was not proper for the people that are having trouble with socketio connection with their backend from a react frontend. This worked for me:
const express = require('express')
const app = express()
const server = require('http').Server(app)
const io = module.exports.io = require('socket.io')(server, { origins: '*:*'})
const path = require('path')
// for prod dont use port #
const PORT = process.env.PORT || 3001
const SocketManager = require('./socketmanager')
app.use(express.static(path.join(__dirname, 'build')));
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
io.on('connection', SocketManager)
server.listen(PORT, ()=>{
console.log("Connected to port:" + PORT);
})
Related
I really can't get socket.io to work after deployment.
Backend:
import * as dotenv from "dotenv";
import express from "express";
import mongoose from "mongoose";
import cors from "cors";
import bodyParser from "body-parser";
import { Server } from "socket.io";
dotenv.config();
const app = express();
app.use(bodyParser.json({ limit: "15mb", extended: true }));
app.use(bodyParser.urlencoded({ limit: "15mb", extended: true }));
app.use(cors());
app.get("/", (req, res) => res.send("My app API"));
const PORT = process.env.PORT || 5000;
const SOCKET_IO_PORT = process.env.SOCKET_IO_PORT || 5500;
let server = app.listen(SOCKET_IO_PORT, () => {
console.log("Socket.io server running on port :" + SOCKET_IO_PORT);
});
const io = new Server(server, {
cors: { origin: "https://myapp.pages.dev" },
});
mongoose
.connect(process.env.CONNECTION_URL)
.then(() =>
app.listen(PORT, () => console.log(`Server running on port : ${PORT}`))
)
.catch((error) => console.log(error.message));
Frontend:
socket.current = io("https://myapp-api-production.up.railway.app");
socket.current?.on(
"getMessage",
(...) => {
...
}
);
Browser network tab:
Request URL: https://myapp-api-production.up.railway.app/socket.io/?EIO=4&transport=polling&t=OO7eSMV
Request Method: GET
Status Code: 404
Response:
Cannot GET /socket.io/
Server deployment log:
Socket.io server running on port :5698
Server running on port :
7777
You're creating two separate HTTP servers (by calling app.listen() twice). It looks like your frontend code is targeting the Express server, and not the socket.io server.
My suggestion would be to just use one HTTP server listening on PORT:
let server = app.listen(PORT, () => {
console.log("Server running on port :" + PORT);
});
(and remove the call to app.listen() in the Mongoose then() handler).
Server-side code:
const express = require("express");
const app = express();
const http = require("http");
const { Server } = require("socket.io");
const cors = require("cors");
app.use(cors());
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"],
},
});
io.on("connection", (socket) => {
console.log(`User Connected: ${socket.id}`);
socket.on("join_room", (data) => {
socket.join(data);
});
Client-side code:
import io from "socket.io-client";
const socket = io.connect("http://localhost:8080");
function App() {
const joinRoom = () => {
if (room !== "") {
socket.emit("join_room", room);
}
};
But getting the following error after hosting it to cloudflare which works fine in local.:
polling.js:311 GET http://localhost:8080/socket.io/?EIO=4&transport=polling&t=OKgPK3u net::ERR_CONNECTION_REFUSED
I tried giving different port but still facing the same problem. Can anyone please help me?
I have two different machines connect to same network.
I wanted to connect over LAN Network using LAN assigned IP address below is the simple demonstration
Socket Client (Reactjs, IP : 192.168.0.103) to Socket Server (Express, IP :192.168.0.114)
Problem :
Getting error : Access blocked by CORS (tried express 'cors' middleware but failed with no solution)
Here is Simple React Code which is working fine
import socketClient from 'socket.io-client';
const SocketServer = 'http://192.168.0.114:3000';
function App() {
var socket = socketClient(SocketServer, {secure: true});
socket.emit('client_connected', { payload: {
message: "react client is connected"
}});
return (
<div>
</div>
);
}
export default App;
And simple express code (which also working fine)
const cors = require('cors')
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
const http = require('http')
const server = http.createServer(app)
const { Server } = require('socket.io')
const io = new Server(server)
app.use(bodyParser.urlencoded({extended: true}))
app.use(express.static('public'))
app.use(cors({
origin: '*'
}));
app.set('view engine', 'ejs')
app.get('/', (req,res) => {
res.sendFile(__dirname + '/index.html')
})
io.on('connection', (socket) => {
socket.on('client_connected', (message) => {
console.log(message)
})
})
server.listen(3000, () => {
console.log('listening on *:3000');
});
Error screenshot getting in Browser console on ReatJs
enter image description here
I tried setting up headers in express but getting same error
Any help will be appreciated
You need to configure cors in the socket server not express
take a look here to know more about the configuration https://socket.io/docs/v3/handling-cors/
configuration example
const io = require("socket.io")(httpServer, {
cors: {
origin: "https://example.com",
methods: ["GET", "POST"]
}
});
How do I convert my app that is made with .pug to next app ? I have an app using .pug engine and I want to convert it into next.
This is the app.js but as I know next is different how do I do it? Because here my files are in views, and in views the files are in pages etc how do I do it? Is there any way or I have to code it all again?
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
const middleware = require('./middleware')
const path = require('path')
const bodyParser = require("body-parser")
const mongoose = require("./database");
const session = require("express-session");
const http = require('http');
const server = app.listen(port, () => console.log("Server listening on port " + port));
const io = require("socket.io")(server, { pingTimeout: 60000 });
app.set("view engine", "pug");
app.set("views", "views");
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, "public")));
app.use(session({
secret: "#########",
resave: true,
saveUninitialized: false
}))
// Routes
const loginRoute = require('./routes/loginRoutes');
const registerRoute = require('./routes/registerRoutes');
const logoutRoute = require('./routes/logout');
const postRoute = require('./routes/postRoutes');
const profileRoute = require('./routes/profileRoutes');
const uploadRoute = require('./routes/uploadRoutes');
const searchRoute = require('./routes/searchRoutes');
const messagesRoute = require('./routes/messagesRoutes');
const notificationsRoute = require('./routes/notificationRoutes');
// Api routes
const postsApiRoute = require('./routes/api/posts');
const usersApiRoute = require('./routes/api/users');
const chatsApiRoute = require('./routes/api/chats');
const messagesApiRoute = require('./routes/api/messages');
const notificationsApiRoute = require('./routes/api/notifications');
app.use("/login", loginRoute);
app.use("/register", registerRoute);
app.use("/logout", logoutRoute);
app.use("/posts", middleware.requireLogin, postRoute);
app.use("/profile", middleware.requireLogin, profileRoute);
app.use("/uploads", uploadRoute);
app.use("/search", middleware.requireLogin, searchRoute);
app.use("/messages", middleware.requireLogin, messagesRoute);
app.use("/notifications", middleware.requireLogin, notificationsRoute);
app.use("/api/posts", postsApiRoute);
app.use("/api/users", usersApiRoute);
app.use("/api/chats", chatsApiRoute);
app.use("/api/messages", messagesApiRoute);
app.use("/api/notifications", notificationsApiRoute);
app.get("/", middleware.requireLogin, (req, res, next) => {
var payload = {
pageTitle: "Home",
userLoggedIn: req.session.user,
userLoggedInJs: JSON.stringify(req.session.user),
}
res.status(200).render("home", payload);
})
io.on("connection", socket => {
socket.on("setup", userData => {
socket.join(userData._id);
socket.emit("connected");
})
socket.on("join room", room => socket.join(room));
socket.on("typing", room => socket.in(room).emit("typing"));
socket.on("stop typing", room => socket.in(room).emit("stop typing"));
socket.on("notification received", room => socket.in(room).emit("notification received"));
socket.on("new message", newMessage => {
var chat = newMessage.chat;
if(!chat.users) return console.log("Chat.users not defined");
chat.users.forEach(user => {
if(user._id == newMessage.sender._id) return;
socket.in(user._id).emit("message received", newMessage);
})
});
})
If you don't want to refactor all your pug template engine pages to next.js pages, then you can make the pug pages coexist with the next.js. You can make the next.js the default route, and place next.js code after all pug page routes. And you also need to refactor app.get("/", middleware.requireLogin, (req, res, next) => {...} to make sure next.js is the default route.
To apply this rule, you need a custom next.js server.
sample code
const express = require('express');
const next = require('next');
const port = 3000;
const dev = process.env.NODE_ENV !== 'production'; // use default NodeJS environment variable to figure out dev mode
const app = next({dev, conf});
const handle = app.getRequestHandler();
const server = express();
// all your pug page routes should be declared before `server.get('*'`.
server.get('*', authMiddleware(false), (req, res) => {
// pass through everything to NextJS
return handle(req, res);
});
app.prepare().then(() => {
server.listen(port, (err) => {
if (err) throw err;
console.log('NextJS is ready on http://localhost:' + port);
});
}).catch(e => {
console.error(e.stack);
process.exit(1);
});
When I run heroku local, app working as expecting.
On production, it's not loading anything from Mlab (remote mongoDb)
Here is it
https://react-bulletin.herokuapp.com/
Just showing static react file.
here is my server file
require('dotenv').config();
// Express Stuff
const express = require('express');
const app = express();
const cors = require('cors')
const path = require('path')
// Mongo Wrapper
const mongoose = require('mongoose');
// Supporting Libraries
const bodyParser = require('body-parser');
// Globals
const dbUrl = process.env.MONGODB_URI
const port = process.env.PORT
mongoose.connect(dbUrl, {
useNewUrlParser: true,
useFindAndModify: false
});
app.use(cors())
app.use(bodyParser.json());
app.use('/', require('./Routes'));
if (process.env.NODE_ENV === 'production') {
// Serve any static files
app.use(express.static(path.join(__dirname, 'client/build')));
// Handle React routing, return all requests to React app
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'client/build', 'index.html'));
});
}
const PORT = process.env.PORT || 5000;
app.listen(port, () => {
console.log(`Running at http://localhost:${PORT}`);
I have no idea why is that.
Please any help.
PS
MONGODB_URI is added to heroku varibles.