Need help on this issue:
Working on a project that involves code editor and evaluating the code from the USER.
Created a route and a function on my backend (Express) where the function takes the user written code, evaluates and return its value.
Post request is being made using axios from the Frontend(REACT) to backend for the user code to be evaulated and send the response back to frontend.
What i have accomplished:
send the user code to backend via post request.
code is eval in the backend using sandbox.
What i am having issues with?
sending the response back to the frontend. The post req does not bring back a response.
below is the code: any thoughts / feedback?
BACKEND:
const express = require('express');
const codeRoutes = express.Router();
const codeHelper = require('../services/code/code-helper');
codeRoutes.post('/', codeHelper.codeEval, (req, res) => {res.json({
data: res.result
})
});
module.exports = codeRoutes;
HELPER FUNCTION:
const vm = require('vm');
let codeEval = (req, res) => {
let result;
let code = req.body.code;
const sandbox = {};
vm.createContext(sandbox);
result = vm.runInContext(code, sandbox);
console.log(result); // this does console.log in the terminal
return result;
}
module.exports = { codeEval };
FRONTEND:
handleExecuteCode = (code) => {
axios.post('/code', {
code: code,
}).then(res => {
console.log('frontend received--->', res)
}).catch(err => console.log(err));
}
<button onClick={() =>
this.handleExecuteCode(this.state.code)}>EXECUTE</button>
actually just figured it out. My setup is correct. I was not using and calling next() in my helper function thus it was not returning anything. I just tested and it works. :)
Related
I am building out an API using Node for the first time but a little stuck on something.
I have the following files:
My routes, routes/index.js:
const express = require('express');
const router = express.Router();
const transactionsController = require('../controllers/transactionsController');
const ordersController = require('../controllers/ordersController');
const ordersCountController = require('../controllers/ordersCountController');
router.get('/transactions', transactionsController);
router.get('/orders', ordersController);
router.get('/orders_count', ordersCountController);
module.exports = router;
My controllers, controllers/ordersCountController.js:
const ordersCountService = require('../services/ordersCountService');
const ordersCountController = async () => {
try {
const data = await ordersCountService();
console.log(data);
return data;
} catch(err) {
console.log(err);
}
};
module.exports = ordersCountController;
My service to fetch from an external API, services/ordersCountService.js:
const fetch = require('node-fetch');
const ordersCountService = async () => {
const URL = ....;
const settings = { method: 'Get'};
const res = await fetch(URL, settings);
if (!res.ok) throw new Error('Unable to retrieve data');
return await res.json();
}
module.exports = ordersCountService;
How can I pass the JSON through to the browser?
I have been trying a few things - you'll notice the return data; - but I can't figure out how to return the JSON so that it's displayed in the browser when someone visits ourdomain.com/api/orders_count.
Any suggestions as to what I am doing wrong here? I am still new to JS so sorry if I am missing something completely obvious here.
Thank you all for your time. If there is anything I can add for clarity, please don't hesitate to ask.
In your controller, ordersCountService should have 2 parameters: req and res:
The req object represents the HTTP request and has properties for the request query string, parameters, body, and HTTP headers.
The res object represents the HTTP response that an Express app sends when it gets an HTTP request.
In this case, your controller should be:
const ordersCountController = async (req, res) => {
try {
const data = await ordersCountService();
console.log(data);
res.json({data})
} catch(err) {
console.log(err);
}
};
Save it, and open the express server, and type the route url in the browser, you would see the json format.
You could find more information about Express in this article.
Express Explained with Examples - Installation, Routing, Middleware, and More
Below is my project folder structure :
app
Controller
testController.js
Service
testInfoService.js
testMoreDataService.js
config
node-modules
public
index.js
routes
routes.js
Here some code :
routes.js
router.get('/config', (req, res) => {
require(controllerDirectoryPath+"/testController.js").index(req, res)
})
testController.js
const testInfoService = require('somePath/Service/testInfoService')
const index = async (req, res) =>{
console.log('Request object : ');
console.log(req);
console.log('Response object : ');
console.log(res);
//getting more info from service
testMoreInfo = await testInfoService.getMoreInformation(args)
return res.status(200).send(testMoreInfo);
}
module.exports = {index:index}
testInfoService.js
const testMoreDataService = require("somePath/testMoreDataService")
const getMoreInformation = async (args)=> {
...some code here
response = await testMoreDataService.getMoreData(args)
return response
}
module.exports = {getMoreInformation:getMoreInformation}
testMoreDataService.js
const getMoreData = async (args)=> {
**//here I want to use Request and Response object**
...some code here
return response
}
module.exports = {getMoreData:getMoreData}
Is there any way I can access req and res object in my service?
I am using node : 12.16.2 with Express.
Main file is public/index.js
Also let me know is this the correct way I am following for any application(REST-API)?
The structure is correct,
Route -> Controller -> Service
You don't have to propagate the actual req, res object all the way down to all the services.
In your controller, you would fetch the following,
Query parameter. Eg. req.query.limit
Path variable. Eg.req.param.id
Request body. Eg. req.body/req.body.name
Once you get the required information in the controller, you could construct an object or pass the relevant information to your service.
Do all the business logic in your service and return the final information to the controller.
The controller would then send this response back to the client.
I'm created a chat-bot using 'botact' library, but
when I'm trying to verificate my bot on vk-community API working page I receive an error in 'Windows PowerShell' (Here I started the server for bot):
TypeError: Cannot read property 'fwd_messages' of undefined
at Botact.getLastMessage (C:\Users\whoami\Desktop\Bot-test\node_modules\botact\lib\utils\getLastMessage.js:2:11)
at Botact.module.exports (C:\Users\whoami\Desktop\Bot-test\node_modules\botact\lib\methods\listen.js:29:28).
The file 'getLastMessage.js' contains this code:
const getLastMessage = (msg) => {
if (msg.fwd_messages && msg.fwd_messages.length) {
return getLastMessage(msg.fwd_messages[0])
}
return msg
}
module.exports = getLastMessage
So I don't know much about botact but according to the code when you are hitting the / route, you need to pass a body containing an object property.
Now as this is bot framework for vk bots maybe it automatically sends the request body. You can make sure by logging the request body.
server.post('/', async (req,res)=>{
console.dir(req.body);
await bot.listen(req, res);
});
/lib/methods/listen.js:
const { type, secret, object, group_id } = framework === 'koa'
? args[0].request.body
: args[0].body
...
...
...
const { events, middlewares } = actions
const forwarded = this.getLastMessage(object)
Now, when you do bot.listen express passes req as first argument. and { type, secret, object, group_id } these fields get distructured from the req.body.
And then object is getting passed to the getLastMessage function.
So for the request body in minimum you would need
{ "object": {} }
Here is the 200 OK output that I got after added that to the request body from Postman
POC Code:
const express = require("express");
const bodyParser = require("body-parser");
const { Botact } = require("botact");
const server = express();
const bot = new Botact({
token: "token_for_my_group_i_just_hided_it",
confirmation: "code_for_my_group_i_just_hided_it"
});
server.use(bodyParser.json());
server.post("/",bot.listen);
server.listen(8080);
Preamble: I'm new to web dev so maybe this might be a very basic question for you vets.
I'm using MVC architecture pattern for this basic app. I've models (MongoDB), views (Express Handlebars), and controllers (functions that take in req, res, next and returns promises (.then > JSON is returned, .catch > error is returned). I'll be routing the paths reqs to their corresponding api endpoints in the controllers.
This makes sense (right?) when I'm purely working on API calls where JSON is the res. However, I also want to call these api endpoints > get their res.json > and use that to render my HTML using Handlebars. What is the best way to accomplish this? I can create same controllers and instead of resp being JSON, I can do render ("html view", res.json). But that seems like I'm repeating same code again just to change what to do with the response (return JSON or Render the JSON).
Hope I'm making sense, if not, do let me know. Please advise.
p.s. try to ELI5 things for me. (:
Edit:
//Model Example
const Schema = require('mongoose').Schema;
const testSchema = new Schema({
testText: { type: String, required: true },
});
const Test = mongoose.model('Test', testSchema);
module.exports = Test;
//Controller Example
const model = require('../models');
module.exports = {
getAll: function(req, res, next) {
model.Test.find(req.query)
.then((testItems) => {
!testItems.length
? res.status(404).json({ message: 'No Test Item Found' })
: res.status(200).json(testItems);
})
.catch((err) => next(err));
},
};
//Route Example
const router = require('express').Router(),
controller = require('../controllers');
router.get('/', controller.getAll);
module.exports = router;
I want the endpoints to return JSON and somehow manage whether to render (if the req comes from a browser) or stay with JSON (if called from Postman or an API web URL for example) without repeating the code. I'm trying to not create two endpoitns with 99% of the code being the same, the only difference being .then > res.status(200).json(testItems); vs .then > res.status(200).render('testPage', { testItems}).
For postman you could check the existence of postman-token in req.headers, then you could render accordingly, something like this:
req.headers['postman-token'] ? res.json({ /* json */ }) : render('view', {/ * json */});
If you want to go with checking postman token then you can use similar to method1.
if you want to check with query params in this case you can get json response or html even from browser for future use also and is not dependent on postman then use similar to method2 of the following example.
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
const port = 5000
app.get('/method1', (req, res) => {
const isJSONResp = req.headers['postman-token']
const resp = { status: "hello" }
if (isJSONResp) {
res.json(resp)
} else {
res.render('some.html', resp)
}
})
app.get('/method2', (req, res) => {
const params = req.params
const resp = { status: "hello" }
if (params.resp === 'json') {
res.json(resp)
} else {
res.render('some.html', resp)
}
})
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
In my Express app I am receiving a payload from an external POST request:
router.post('/liveReleaseStore', (req,res) => {
let thing = req.body.myPayload
...
I also handle a GET request from my client:
router.get('/liveReleaseStore', (req, res) => {
let myResponse = ...
res.send(myResponse);
});
I need to reroute the payload so that when my client sends a GET to the server I am able to send back the data or tell the client that I haven't received any data yet.
What is the best way to about about this?
Thanks
You could initialize the data outside the two functions to null. And then send the data if it's been initialized by the post function.
let thing = null;
router.post('/liveReleaseStore', (req,res) => {
let thing = req.body.myPayload
...
}
router.get('/liveReleaseStore', (req,res) => {
if (thing === null)
return res.send('no data yet');
res.send(thing);
}