My Zoho Catalyst framework isn't passing the request.body. Here is the code.
module.exports = (req, res1) => {
const debug = require('debug');
const https = require('https');
const tools = require('./tools.js');
const crypto = require('crypto');
const express = require('express');
const app = express();
app.use(express.json())
app.use(express.urlencoded({ extended: true }));
app.use(express.text());
function getHash(){
var hmac = crypto.createHmac('sha256', apisecretkey);
hmac.update(dataToSign);
return hmac.digest('base64');
};
var url = req.url;
switch (url) {
case '/scanName':
//var s = JSON.stringify(req.body)
console.log(req.body)
console.log(req.get('Accept'))
console.log(req.accepts('application/json'));
res1.write('xx')
res1.end()
break;
case '/':
Here is the output:
undefined
*/*
application/json
I've tried every form of POST from Postman that I can think of, and still nothing.
You have bound the express app variable to recognize the incoming data of the following types JSON, urlencoded and text. But you haven’t used that app variable to get the incoming request so technically it is like you have declared it but never used it. So, your function code couldn’t be able to identify the type of incoming data in the request body. You can modify your code like below:
'use strict';
const debug = require('debug');
const https = require('https');
const tools = require('./tools.js');
const crypto = require('crypto');
const express = require('express');
const app = express();
app.use(express.json());
app.use(express.text());
app.use(express.urlencoded({ extended: true }));
app.post('/scanName',async(req, res) => {
try {
let body = req.body;
console.log(body);
res.status(200).send(body);
} catch (error) {
console.log(error);
res.status(500).send(error);
}
});
module.exports = app;
You have to export the express app variable to make the endpoints accessible. You can check out this tutorial where we have shown an example of how to get and send data in the Catalyst Advanced IO function using Express.js.
I'm quite new to this whole backend business and I'm wondering if anyone can see where I'm going wrong. I've got an express server in my Nuxt app which is serving out an API. When I run the localhost:3000/api/salesforce/:id route - my vscode terminal generates a response - but it doesn't show up on the browser. Which in turn makes it inaccessible to Nuxt.
In my nuxt.config.js:
serverMiddleware: {
'/api': '~/api'
},
/api/index.js:
const express = require('express')
// Create express instance
const app = express()
// Require API routes
const users = require('./routes/users')
const test = require('./routes/test')
const salesforce = require('./routes/salesforce')
// Import API Routes
app.use(users)
app.use(test)
app.use(salesforce)
// Export express app
module.exports = app
// Start standalone server if directly running
if (require.main === module) {
const port = process.env.PORT || 3001
app.listen(port, () => {
// eslint-disable-next-line no-console
console.log(`API server listening on port ${port}`)
})
}
Then in /api/routes/salesforce.js:
const e = require('express')
const { Router } = require('express')
const router = Router()
const jsforce = require('jsforce');
// require the .env file for login
require('dotenv').config();
const { SF_USERNAME, SF_PASSWORD, SF_TOKEN, SF_LOGIN_URL } = process.env;
if (!(SF_USERNAME && SF_PASSWORD && SF_TOKEN && SF_LOGIN_URL)) {
console.error(
'Cannot start app: missing mandatory configuration. Check your .env file.'
);
process.exit(-1);
}
const conn = new jsforce.Connection({
loginUrl: SF_LOGIN_URL
});
conn.login(SF_USERNAME, SF_PASSWORD + SF_TOKEN, err => {
if (err) {
console.error(err);
process.exit(-1);
}
});
// get OPPORTUNITY specific
router.get('/salesforce/:id', function (req, res, next) {
const id = req.params.id
console.log(req.params.id)
const sfData = conn.query(`SELECT Id, Name, StageName FROM Opportunity WHERE Name = '` + id + `'`, (err, res)=>{
if(err){
console.log(err)
return "error";
} else {
console.log(res.records[0])
let sanitisedData = res.records[0]
return sanitisedData;
}
})
res.json(sfData.json)
})
If anyone can tell me where I'm going wrong that would be greatly appreciated, I'm kind of stuck here.
Im doing a mern tutorial on freecodecamp and I have run into an issue that is driving me nuts.
I have a route which is localhost:5000/exercises/1234
however I keep getting a 404 on that route.
If someone could point out the error if would be appreciated.
I have a server file:
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
const exerciseRouter = require("./routes/exercises");
const usersRouter = require("./routes/users");
require("dotenv").config();
const app = express();
const port = process.env.PORT || 5000;
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true,
});
const connection = mongoose.connection;
connection.once("open", () => {
console.log("Mongo DB database connection established successfully 👾👾👾");
});
app.use(cors());
app.use(express.json());
app.use("/exercises", exerciseRouter);
app.use("/users", usersRouter);
app.listen(port, () => {
console.log(`server is running on port ${port} 😻`);
});
and the route is defined here in an exercise.js file:
const router = require("express").Router();
const Exercise = require("../models/exercise.model");
router.route("/:id").get((req, res) => {
console.log(req.params);
Exercise.findById(req.params.id)
.then((exercise) => res.json(exercise))
.catch((err) => res.status(400).json(`Error ${req.params}`));
});
When i run this in the browser I get a 404 and not even the console log is run. Im really not sure why it isnt working.
Ah disregard this issue, i did an idiotic mistake. I had the method get inside another method (which isnt apparent in the above question).
Note to myself and others make sure your route aren't nested by accident in another route! lol
I am trying to set up a react express application with mongo db as the database. I am in the preliminary stages and keep coming across this error:
Error: Route.post() requires callback functions but got a [object Undefined]
here is my app.js
const express = require('express');
// const http = require('http');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const app = express();
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
//db and name is auth
mongoose.connect('mongodb://localhost/auth', {
useMongoClient: true,
/* other options */
});
// app setup
//server setup
const port = process.env.Port || 4000
// const server = http.createServer(app);
app.listen(port);
console.log(`Sever listening on ${port}`)
const authRoutes = require('./routes/auth_routes');
app.use('/',authRoutes);
my routes are right here. I am just testing to see if there is a correct connection.
const authController = '../controllers/auth_controller';
const express = require('express');
const authRoutes = express.Router();
authRoutes.post('/',authController.signup)
module.exports = authRoutes;
my controller is listed below:
const authController = {};
authController.signup = function(req,res,next) {
console.log('here');
res.json({
user: "doesnt matter",
data: 'Put a user profile on this route'
});
}
module.exports = authController;
not sure if mongo is the problem since it is my first time using it, but my connection to the database works robo 3t to check whats in the database and the user schema is there. if i comment out that one route in the routes page, the errors go away.
I believe the problem is here:
const authController = '../controllers/auth_controller';
authRoutes.post('/',authController.signup)
Note that authController is just a string. I'm guessing you intended:
const authController = require('../controllers/auth_controller');
I'm trying to create a really simple node API using express.js 4 but I need a few 'realtime' events for which I added socket.io. I'm fairly new to both so I'm likely missing something basic but I can't find good docs/tuts on this.
In the express app (created with the express generator) I have something like this based on simple examples and project docs that I read. This works OK and from client apps, I can send/receive the socket events:
var express = require('express');
var path = require('path');
var logger = require('morgan');
var api = require('./routes/api');
var app = express();
var io = require('socket.io').listen(app.listen(3000));
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/api', api);
io.sockets.on('connection', function (socket) {
console.log('client connect');
socket.on('echo', function (data) {
io.sockets.emit('message', data);
});
});
// error handlers omitted
module.exports = app;
but I want to use the sockets from my API routes (in the ./routes/api.js file that I 'require' above). For example, someone might use the API to PUT/POST a resource and I want that broadcast to connected socket.io clients.
I cannot see how to use the 'io' variable or organise the code currently in the io.sockets.on('connection' ... function inside express routes. Here's the ./routes/api.js file:
var express = require('express');
var router = express.Router();
var io = ???;
router.put('/foo', function(req, res) {
/*
do stuff to update the foo resource
...
*/
// now broadcast the updated foo..
io.sockets.emit('update', foo); // how?
});
module.exports = router;
One option is to pass it in to req object.
app.js:
var express = require('express');
var path = require('path');
var logger = require('morgan');
var api = require('./routes/api');
var app = express();
var io = require('socket.io').listen(app.listen(3000));
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
io.sockets.on('connection', function (socket) {
console.log('client connect');
socket.on('echo', function (data) {
io.sockets.emit('message', data);
});
});
// Make io accessible to our router
app.use(function(req,res,next){
req.io = io;
next();
});
app.use('/api', api);
// error handlers omitted
module.exports = app;
./routes/api.js:
var express = require('express');
var router = express.Router();
router.put('/foo', function(req, res) {
/*
do stuff to update the foo resource
...
*/
// now broadcast the updated foo..
req.io.sockets.emit('update', foo);
});
module.exports = router;
I've modified your files a little bit, may you check if it works?
You can pass the io you've defined to your routes like below;
require('./routes/api')(app,io);
I didn't test the Socket.IO parts but there is no syntax error and routes also working.
server.js file:
var express = require('express');
var app = express();
var path = require('path');
var logger = require('morgan');
var io = require('socket.io').listen(app.listen(3000));
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
io.sockets.on('connection', function (socket) {
console.log('client connect');
socket.on('echo', function (data) {
io.sockets.emit('message', data);
});
});
require('./routes/api')(app,io);
console.log("Server listening at port 3000");
api.js:
module.exports = function(app,io) {
app.put('/foo', function(req, res) {
/*
do stuff to update the foo resource
...
*/
// now broadcast the updated foo..
console.log("PUT OK!");
io.sockets.emit('update'); // how?
res.json({result: "update sent over IO"});
});
}
Supposing you want to access the SocketIO from anywhere in your application, not just in the router, you could create a singleton for it. This is what works for me:
//socket-singletion.js
var socket = require('socket.io');
var SocketSingleton = (function() {
this.io = null;
this.configure = function(server) {
this.io = socket(server);
}
return this;
})();
module.exports = SocketSingleton;
Then, you need to configure it using your server:
//server config file
var SocketSingleton = require('./socket-singleton');
var http = require('http');
var server = http.createServer(app);
SocketSingleton.configure(server); // <--here
server.listen('3000');
Finally, use it wherever you want:
//router/index.js
var express = require('express');
var router = express.Router();
var SocketSingleton = require('../socket-singleton');
/* GET home page. */
router.get('/', function(req, res, next) {
setTimeout(function(){
SocketSingleton.io.emit('news', {msg: 'success!'});
}, 3000);
res.render('index', { title: 'Express' });
});
module.exports = router;
One more option is to use req.app.
app.js
const express = require('express');
const path = require('path');
const logger = require('morgan');
const api = require('./routes/api');
const app = express();
const io = require('socket.io').listen(app.listen(3000));
// Keep the io instance
app.io = io;
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
// ...
app.use('/api', api);
module.exports = app;
routes/api.js
const express = require('express');
const router = express.Router();
router.put('/foo', function(req, res) {
/*
* API
*/
// Broadcast the updated foo..
req.app.io.sockets.emit('update', foo);
});
module.exports = router;
Refactored Edudjr's answer.
Change the singleton to create a new instance of socket.io server
const { Server } = require('socket.io');
const singleton = (() => {
this.configure = (server) => this.io = new Server(server)
return this
})();
module.exports = singleton
Initialise your express app, the server and the singleton.
// initialise app
const app = express();
const server = require('http').createServer(app);
// configure socket.io
socket.configure(server)
Then in your router
const socket = require('/utils/socket-singleton');
socket.io.emit('event', {message: 'your message here'})
I think best way is to set io as a property of req, like below:
app.use(function(req,res,next){
req.io = io;
next();
});
app.use('/your-sub-link', your-router);