I`m trying to create emit for the socket on post request from postman but got some troubles. I found an issue here but it seems not working for me. I have this code in my app.js
App.js
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
const http = require('http').createServer(app)
const eventsRoute = require('./routes/eventsRoute')
const io = require('socket.io')(http, {
cors: {origin: "*"},
path: '/api/events'
})
io.of('/api/events/').on('connection', socket => console.log('connected'))
...
app.use('/api/events', eventsRoute(io))
module.exports = app
And here I got eventsRoute.js code. Here, I think, is the main problem
eventsRoute.js
const express = require('express')
const errorHandler = require('../utils/errorHandler')
const router = express.Router()
const returnRouter = io => {
router.post('/', async (req, res) => {
try {
io.sockets.emit('create', req.body)
res.status(200).json({message: 'successful'})
} catch (e) {
errorHandler(e)
}
})
router.get("/", function (req, res) {
try {
res.send({})
} catch (e) {
errorHandler(e)
}
})
return router
}
module.exports = returnRouter
And on my client side, I have some code in the script tag. Here it is
<script src="https://cdn.socket.io/3.1.3/socket.io.min.js"></script>
<script>
const socket = io('ws://localhost:5000', {path: '/api/events'})
socket.on('create', data => {
console.log(data)
})
</script>
So, the main reason was in ... all files. Let's begin with index.js. I'm exporting the app. Instead of that, I have to export http. Then in app.js, I will have to change line with sockets to this
const io = require('socket.io')(http, options)
io.of('/api/events')
.on('connection', socket => {
app.use('/api/events', eventsRoute(socket))
})
Related
I'm a new learner express.js I want to test simple post and get operations with tdd mechanism. I created the test, route, index and db files but when I try to test POST method it gives me this error.
This is my routes/task.js
const express = require('express');
const router = express.Router();
router.post("/api/task", async (req,res) => {
try {
const task = await new Task(req.body).save();
res.send(task);
} catch (error) {
res.send(error);
}
})
This is my test/task.js
let chai = require("chai");
const chaiHttp = require("chai-http");
const { send } = require("process");
let server = require("../index");
//Assertion Style
chai.should();
chai.use(chaiHttp);
describe('Tasks API', () => {
/**
* Test the POST Route
*/
describe('POST /api/task', () => {
it("It should POST a new task", () => {
const task = {task: "Wake Up"};
chai.request(server)
.post("/api/task")
.send(task)
.end((err, response) => {
response.should.have.status(201);
response.body.should.be.a('string');
response.body.should.have.property('id');
response.body.should.have.property('task');
response.body.should.have.property('task').eq("Wake Up");
response.body.length.should.be.eq(1);
done();
});
});
});
});
This is my db.js
var sqlite3 = require('sqlite3').verbose()
const DBSOURCE = "db.sqlite"
let db = new sqlite3.Database(DBSOURCE, (err) => {
if (err) {
// Cannot open database
console.error(err.message)
throw err
}else{
console.log('Connected to the SQLite database.')
db.run(`CREATE TABLE IF NOT EXISTS todo (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task text
)`,
(err) => {
if (err) {
// Table already created
console.log(err);
}
});
}
});
module.exports = db
And this is my index.js
const connection = require('./db');
const express = require('express');
const app = express();
const cors = require("cors");
const port = process.env.PORT || 8080;
app.use(express.json());
app.use(cors());
app.get('/', (req, res) => {
res.send('Hello World');
});
app.post('/api/task', (req, res) => {
res.status(201).send(req);
});
app.listen(port, () => console.log(`Listening on port ${port}...`));
module.exports = app;
The thing that I try to do is building a test case to test the post method. I think I couldn't built the correct relations the files.
Currently, just by doing a POST request to /api/task, the error will appear. That is because of these lines in index.js:
app.post('/api/task', (req, res) => {
res.status(201).send(req);
});
The req parameter is circular, hence cannot be JSON-stringified.
Solution
In routes/task.js export the router:
const express = require('express');
const router = express.Router();
router.post("/api/task", async (req,res) => {
try {
const task = await new Task(req.body).save();
res.send(task);
} catch (error) {
res.send(error);
}
})
// By adding this line you can export the router
module.exports = router
In index.js, include the routes/task.js file and pass it to app.use(...), also remove the now-obsolete /api/task route:
const connection = require('./db');
const express = require('express');
const app = express();
const cors = require("cors");
const taskRoutes = require("./routes/task")
const port = process.env.PORT || 8080;
app.use(express.json());
app.use(cors());
app.get('/', (req, res) => {
res.send('Hello World');
});
app.use(taskRoutes)
app.listen(port, () => console.log(`Listening on port ${port}...`));
module.exports = app;
This way we got rid of the circular structure stringifying and the tests should now pass.
I have a simple app with database and i am having issues with controller function. It's not getting executed for some reason that i couldn't figure it out and it drove me crazy. I will be so grateful if you guys could help with me this.
userController.js
exports.insertUser = async (req, res, next) => {
try {
const user = await MySQL.insertRecord(User, { ...req.body })
res.status(201).send(user)
} catch (e) {
res.status(500).send(e)
}
}
insertion function in db.js
static async insertRecord (User, body) {
console.log(1) // for debugging purposes
const user = User.build(body)
try {
await user.save()
console.log('Record saved to database succesfully.')
return user
} catch (e) {
throw e
}
}
userRoutes.js
const express = require('express')
const userController = require('../controllers/userController')
const router = express.Router()
router
.post('/signup', userController.insertUser)
module.exports = router
server.js
(async () => {
const express = require('express')
require('dotenv').config()
const path = require('path')
const { Sequelize } = require('sequelize')
const MySQL = require('./database/db')
await MySQL.connect(Sequelize)
const userRouter = require('./routes/userRoutes')
const app = express()
const PORT = process.env.PORT || 3000
// setting ejs as the templating language
app.set('view engine', 'ejs')
// middlewares
app.use(express.json())
app.use(express.static(path.join(__dirname, 'public')))
app.use('/user', userRouter)
app.listen(PORT, () => console.log(`server listening on port: ${PORT}`))
})()
Here my insertRecord function is not getting executed. It doesn't log 1.
Hi I am trying to make a request and receive just the response in realtime using socketIO
and currently I am able to connect to the router but not getting any response as the error shows
Error: io is not defined.
If anyone can please help me to resolve this issue.
Below is the necessary code.
ChatPageProvider.dart
Future<void> addProduct(String message) async {
Map<String, String> headers = {
"Content-Type": "charset=utf-8",
"Content-type": "application/json"
};
const url = 'http://localhost:8080/message/check';
try {
var response = await http.post(url,
headers: headers,
body: json.encode({
"text": message,
}));
socketIO.init();
//Subscribe to an event to listen to
socketIO.subscribe('message', (jsonData) {
//Convert the JSON data received into a Map
Map<String, dynamic> data = json.decode(jsonData);
messages.add(data['message']);
notifyListeners();
});
socketIO.connect();
// final getMessage = Message(
// text: json.decode(response.body)['message'],
// );
print(response.statusCode);
notifyListeners();
} catch (error) {
throw error;
}
}
index.js
const express = require('express');
const app = express();
const notificationdetails = require('../nodePractice/router/notification');
const http = require('http').createServer(app);
const io = require('socket.io')(http);
bodyParser = require('body-parser');
var port = process.env.PORT || 8080;
app.use(bodyParser.json({limit: "50mb"}));
app.use(bodyParser.urlencoded({limit:"50mb",extended:true}));
io.on("connection",(userSocket) => {
console.log('Conntected to port')
io.emit('connected', 80);
})
var server = http.listen(port, ()=> {
console.log('listening on port' + port)
})
app.use(notificationdetails);
notification.js
const express = require('express');
const router = new express.Router()
router.post('/message/check',async(req,res) => {
console.log("Success"); // I am able to get till here but then the error occurs
io.emit("message", req.body)
try {
res.status(201).send();
io.emit("message", req.body)
}catch(e) {
res.status(401);
io.emit("message", req.body)
res.send(e);
}
})
module.exports = router
error
(node:78214) UnhandledPromiseRejectionWarning: ReferenceError: io is not defined
You can create a file like below, give it a name socket-io.js.
var io = require('socket.io')(9999);
module.exports = io;
Then import it first in your index.js like below snippet.
let io = require('./app/utilities/socket-io');
io.on('connection', function (socket) {
...
});
Last, you can import the same file in your notification.js file as well & try below code.
const express = require('express');
const router = new express.Router()
let io = require('./app/utilities/socket-io');
router.post('/message/check',async(req,res) => {
console.log("Success"); // I am able to get till here but then the error occurs
io.emit("message", req.body)
try {
res.status(201).send();
io.emit("message", req.body)
}catch(e) {
res.status(401);
io.emit("message", req.body)
res.send(e);
}
})
module.exports = router
I need export an object or variable from my app to a router module.
The object is called "page" into "ClientClass".
I read something in SO and I tried to use a global var to save the object, exports it on end of unit.
This object will be used in the router module.
But, I have no success. In the router module "page" is always undefined.
How could I do that?
Main App JS - ClientClass.js:
const express = require('express');
const app = express();
const WARoutes = require('./routes/WARoutes');
var globalpage;
export default class ClientClass {
constructor(options) {
this.options = ...
}
async start() {
const browser = ....
const page = await browser.newPage();
// set globalpage to export
globalpage = page;
console.log('Done!');
app.use(express.json({ limit: '20mb' }));
app.use('/whats', WARoutes);
app.listen(port, () => {
console.log(`Listening on ${this.callbackUrl}...`);
});
}
start();
};
module.exports.page =globalpage;
WARoutes.js:
const express = require('express');
const router = express.Router();
const pagebrowser = require('../ClientClass.js');
const page = pagebrowser.page;
router.get('/getChats', async (req, res) => {
const chats = await page.evaluate((includePict, done) => {
do sometthing; //Here is my problem - page is undefined
}, includePict, done);
res.send(chats);
});
module.exports = router;
You have a cyclical dependency. You need to pass your page variable to the WARoutes.js implementation. Here's one way to do it:
WARoutes.js:
const express = require('express');
const router = express.Router();
//export a function which takes the `page` variable, *returning* the router which used to be _exported_
module.exports = function(page){
router.get('/getChats', async (req, res) => {
const chats = await page.evaluate((includePict, done) => {
do something;
}, includePict, done);
res.send(chats);
});
return router;
}
ClientClass.js:
const express = require('express');
const app = express();
const WARoutes = require('./routes/WARoutes');
export default class ClientClass {
constructor(options) {
this.options = ...
}
async start() {
const browser = ....
const page = await browser.newPage();
console.log('Done!');
app.use(express.json({ limit: '20mb' }));
app.use('/whats', WARoutes(page));
app.listen(port, () => {
console.log(`Listening on ${this.callbackUrl}...`);
});
}
start();
};
P.S.
I am also curious about what you're passing to page.evaluate. The first is a function with two arguments, the second and third are those two arguments again. I have a sneaking suspicion this is not going to work even as modified. You're going to need to provide more information about the page.evaluate API for additional help with that.
I'm pretty new to sockets and I've been struggling to implement some of the documentation i've seen online. This is my set up currently and I wanted to run socket.io against just the healthcheck api endpoint (/api/v1/healthcheck) how would I go about running socket io in the healthcheck controller? and emit changes to the response? Any help is appreciated, i'm tearing my hair out :(
Server.js
const socket = require('socket.io')
const healthcheck = require('./routes/healthcheck');
const auth = require('./routes/auth');
const users = require('./routes/users');
const server = app.listen(
PORT,
console.log(
`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`.cyan.bold
)
);
let io = require('socket.io')(server);
app.set("io", io);
//Auth
app.use('/api/v1/auth', auth);
app.use('/api/v1/users', users);
//Health check
app.use('/api/v1/healthcheck', healthcheck);
/routes/healthcheck.js
const express = require('express');
const { checkHealth } = require('../controllers/healthcheck');
const router = express.Router();
router.post('/', checkHealth);
module.exports = router;
/controllers/healthcheck.js
const asyncHandler = require('../middleware/async');
exports.checkHealth = asyncHandler(async (req, res, next) => {
res.status(200).json({
success: true,
data: {
status: "Alive!"
}
});
});
You can pass in the instance of io into that healthcheck route and then simply listen to events and take action. Sample code below.
server.js
const socket = require('socket.io')
const server = app.listen(
PORT,
console.log(
`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`.cyan.bold
)
);
let io = require('socket.io')(server);
app.set("io", io);
// pass in io to the relevant route
const healthcheck = require('./routes/healthcheck')(io);
const auth = require('./routes/auth');
const users = require('./routes/users');
//Auth
app.use('/api/v1/auth', auth);
app.use('/api/v1/users', users);
//Health check
app.use('/api/v1/healthcheck', healthcheck);
healthcheck route
const express = require('express');
const { checkHealth } = require('../controllers/healthcheck');
const router = express.Router();
module.exports = (io) => {
router.post('/', checkHealth);
io.on('connection', socket => {
socket.emit('hello', {message: 'helloworld'});
socket.on('reply', checkHealth.someMethod);
});
return router;
}
I would rather create endpoints in files - same as you do for express routes, and init these in your server.js as follows:
let io = require('socket.io')(server);
app.set("io", io);
io.on('connection', socket => {
require('./myendpointexample')(socket);
});
myendpointexample.js
module.exports = (socket) => {
socket.on('myevent', (message) => {
mycontroller.myFunction(message).then(result => {
socket.emit('myEvent', result);
});
});
};