Express response manipulation to send string to client - javascript

I have the following app.js file for handle a specific endpoint:
const express = require('express');
const app = express();
app.use((req, res, next) => {
!process.env.HTTP_ACCESS_IP || res.setHeader('Access-Control-Allow-Origin', process.env.HTTP_ACCESS_IP);
res.setHeader(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept, Authorization'
);
res.setHeader(
'Access-Control-Allow-Methods',
'GET, POST, PATCH, PUT, DELETE, OPTIONS',
);
next();
});
app.use(express.json({ limit: '50mb' }));
app.use(express.urlencoded({ limit: '50mb', extended: true }));
app.post('/api/verificationstart', (req, res) => {
return res.status(400).send({ message: 'TEST' });
})
module.exports = app;
I my client side, I send HTTP REQUEST to the endpoint above, then code res.json().
async function fetchApi() {
return fetch('...', {
method: 'POST',
referrerPolicy: 'no-referrer',
});
}
async function verificationStartApi(data) {
const res = await fetchApi();
if (res._bodyText || res._bodyInit) {
return res.json();
} else {
return res;
}
}
The problem is that, from the res.json() I'd like to get a string object, not a JSON one. How could I do it? So that the result from res.json() would be "{ message: 'TEST' }".
Note that I want solution in backend. I can't touch client side.
I've been trying anything in backend using res.send() but nothing did the work:
res.send('"{ "message": "string" }"');
res.send('{ message: "test" }');
res.send('{ "message": "test" }');

So this is the ugliest answer:
return res.send('"{ \\"message\\": \\"string\\" }"');

You could use double JSON.stringify.
app.post('/api/verificationstart', (req, res) => {
// it will be res.send('"{\\"message\\":\\"TEST\\"}"')
res.send(JSON.stringify(JSON.stringify({ message: 'TEST' })))
})

Send a JSON valid string. Suppose this is your api.
app.post('/api/verificationstart', (req, res) => {
return res.status(400).send(JSON.stringify("{ message: 'TEST' }"));
})
res.send(JSON.stringify('{ "message": "test" }'));.
EDIT:
Get what you mean. enclose the Stringified JSON inside a string. Have a look at my update, tested it.

Related

Reference error is not defined on application

When trying to submit data on a form, the webserver is giving me an error saying Reference error: Item is not defined, but based on my code, everything looks okay to me. Is there anything that stands out to you in my code that might cause this?
I was playing around with the Const, but I'm not sure if that's where the problem lies.
Here's my Javascript file:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
//specify where to find the schema
const Items = require('./models/item')
// connect and display the status
mongoose.connect('mongodb://localhost:27017/items', { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => { console.log("connected"); })
.catch(() => { console.log("error connecting"); });
// use the following code on any request that matches the specified mount path
app.use((req, res, next) => {
console.log('This line is always called');
res.setHeader('Access-Control-Allow-Origin', '*'); //can connect from any host
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, OPTIONS'); //allowable methods
res.setHeader('Access-Control-Allow-Headers', 'Origin, Content-Type, Accept');
next();
});
app.get('/items', (req, res, next) => {
//call mongoose method find (MongoDB db.Items.find())
Items.find()
//if data is returned, send data as a response
.then(data => res.status(200).json(data))
//if error, send internal server error
.catch(err => {
console.log('Error: ${err}');
res.status(500).json(err);
});
});
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
// serve incoming post requests to /items
app.post('/items', (req, res, next) => {
// create a new item variable and save request’s fields
const Items = new items ({
itemName: req.body.itemName,
servings: req.body.servings
});
//send the document to the database
Items.save()
//in case of success
.then(() => { console.log('Success');})
//if error
.catch(err => {console.log('Error:' + err);});
});
//to use this middleware in other parts of the application
module.exports=app;
app.post('/items', (req, res, next) => {
// Items already defined
const items = new Items({
itemName: req.body.itemName,
servings: req.body.servings
});
items.save()
//in case of success
.then(() => { console.log('Success');})
//if error
.catch(err => {console.log('Error:' + err);});
});
Items constant is already declared, and you trying to re-declare it

Having issues with javascript compiling

I have an application Javascript file that is showing an error in the console section of VS Studio Code, it keeps saying: app.js: The parser expected to find a '}' to match the '{' token here. and the console will not compile.
Based on my code, would you be able to tell me where I need to close in my braces? I think I might be confused.
Here is my app.js code:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
//specify where to find the schema
const Item = require('./models/item')
// connect and display the status
mongoose.connect('mongodb://localhost:27017/items', { useNewUrlParser: true })
.then(() => { console.log("connected"); })
.catch(() => { console.log("error connecting"); });
// use the following code on any request that matches the specified mount path
app.use((req, res, next) => {
console.log('This line is always called');
res.setHeader('Access-Control-Allow-Origin', '*'); //can connect from any host
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, OPTIONS'); //allowable methods
res.setHeader('Access-Control-Allow-Headers', 'Origin, Content-Type, Accept');
next();
});
app.get('/items', (req, res, next) => {
//call mongoose method find (MongoDB db.Students.find())
Item.find()
//if data is returned, send data as a response
.then(data => res.status(200).json(data))
//if error, send internal server error
.catch(err => {
console.log('Error: ${err}');
res.status(500).json(err);
});
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
// serve incoming post requests to /items
app.post('/items', (req, res, next) => {
const items = req.body;
console.log(items.itemName + " " + items.servings);
//sent an acknowledgment back to caller
res.status(201).json('Post successful');
});
//to use this middleware in other parts of the application
module.exports=app;
Your app.get('/items' function is not closed. Try this.
app.get('/items', (req, res, next) => {
//call mongoose method find (MongoDB db.Students.find())
Item.find()
//if data is returned, send data as a response
.then(data => res.status(200).json(data))
//if error, send internal server error
.catch(err => {
console.log('Error: ${err}');
res.status(500).json(err);
});
});
But in the future, please just use an IDE of some sorts. Even just dumping your code into JSFiddle will highlight this for you.

Fetch method put with React.js and Node server

I want to update my data in my MySQL database. I have React front-end and I'm using node server as back-end. I am getting nothing with body when I try to update data with fetch put method. Why is that?
Why does "body" in fetch method with JSON.stringify(req.body) give me an empty object server-side?
React code(button click event):
handlePrioDown(a) {
sessionStorage["id"] = a["id"];
sessionStorage["priority"] = a["priority"];
fetch('http://localhost:3001/TeacherPri/'+a["id"], {
method: 'PUT',
body: JSON.stringify({priority: a["priority"]+1})
})
}
Node (server.js):
//CORS middleware
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
app.use( bodyParser.json())
app.use(bodyParser.urlencoded({
extended: true
}))
app.use(allowCrossDomain)
app.use(express.json())
app.route("/TeacherPri/:id")
.put(controller.changePriority)
Node (controller.js):
changePriority: (req ,res) => {
let v = req.body;
let key = req.params.id;
console.log(JSON.stringify(v) + " ::::: id="+key)
CONN.query('UPDATE teacher SET priority=? WHERE id=?', [v.priority, key],
(err, results, fields) => {
if(err) {
console.log(err)
res.json(err)
} else {
console.log("Done")
res.statusCode = 204
res.send();
}
})
}
I'm excpecting that I get something like { priority: 4 } as req.body object on server side. I get empty object atm.

Axios data is breaking the request

I have an express API and a ReactJs front-end. I try to make a POST call from my front-end directly to the local API.
For this I'm using axios.
The request is working fine when I set the parameters directly inside the query string but is always getting on timeout if I try to add the parameters through the data attribute of the axios.post() method.
Working
axios.post(`http://localhost:5001/site/authenticate?username=demo&password=demo`)
Not working
const payload = {
"username":"mh",
"password":"mh"
}
axios.post(`http://localhost:5001/site/authenticate`, payload)
My express server:
const express = require('express');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
var cors = require('cors');
const app = express();
const port = process.env.API_PORT || 5001;
app.use(cors());
app.set('secret', process.env.API_SECRET);
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(morgan('dev'));
app.use((req, res, next) => {
let data = '';
req.setEncoding('utf8');
req.on('data', (chunk) => {
data += chunk;
});
req.on('end', () => {
req.rawBody = data;
next();
});
});
// Allow CORS
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
// SITE ROUTES -------------------
const siteRoutes = express.Router();
siteRoutes.post('/authenticate', function(req, res) {
console.log('auth');
getDocument(usersBucket, req.query.username)
.then((doc) => {
console.log("Authentification... TODO");
// return the information including token as JSON
res.json({
success: true,
status: 200,
token: token
});
})
.catch(() => {
res.status(401).json({ success: false, message: 'Authentification failed. User not found.' });
});
});
// route middleware to verify a token
siteRoutes.use(function(req, res, next) {
const token = req.body.token || req.query.token || req.headers['x-access-token'];
if (token) {
// verifies secret and checks exp
jwt.verify(token, app.get('secret'), function(err, decoded) {
if (err) {
return res.json({ success: false, message: 'Failed to authenticate token.', status: 401 });
} else {
req.decoded = decoded;
next();
}
});
} else {
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
});
siteRoutes.get('/', function(req, res) {
res.json({ message: 'Welcome!' });
});
app.use('/site', siteRoutes);
app.listen(port, () => {
logger.log(`Express server listening on port ${port}`);
});
Any idea? Thanks.
Update
I replaced my route just to see if I got in or not (without worrying about parameters):
siteRoutes.post('/authenticate', function(req, res) {
console.log("go in");
res.json({
success: true,
status: 200,
});
});
But my console.log is not showing hen I use the payload (it is when I do not).
You should access the payload data via request.body, not the request.query:
// SITE ROUTES -------------------
const siteRoutes = express.Router();
siteRoutes.post('/authenticate', function(req, res) {
console.log('auth');
getDocument(usersBucket, req.body.username) // <------- HERE
.then((doc) => {
console.log("Authentification... TODO");
// return the information including token as JSON
res.json({
success: true,
status: 200,
token: token
});
})
.catch(() => {
res.status(401).json({ success: false, message: 'Authentification failed. User not found.' });
});
});
request.query are the parameters passed in the URL, like:
protocol://hostname:port/path/to.route?query_param_0=value_0&query_param_1=value_1
on your express endpoint request.query will be:
{
query_param_0: value_0,
query_param_1: value_1
}
while sending the payload, with the second argument in axios.post(url, payload):
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
on your express endpoint request.body will be:
{
firstName: 'Fred',
lastName: 'Flintstone'
}
when you use app.use(bodyParser.json()); (and you do).
You are using “getDocument(usersBucket, req.query.username)”
This means you express route is expecting username as a request param. That’s why it’s working when you use “?username=xx”
Instead try to get it from json body of request.
“req.body.username”
Also you should consider validating the request body or param as required.

CORS policy: Response to preflight request doesn't pass access control check

I am currently trying to do a simple post method to my API through the browser and it fails. When I do the same on postman, the POST method goes without problem. It returns a json string and returns 2 cookies.
I have tried to set the headers in the middleware like I found on SO:
router.use(function(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
console.log('Something is happening.');
next(); // make sure we go to the next routes and don't stop here
});
Unfortunately this did not solve the issue, so I went out for more research and found a NPM package about Cors: https://www.npmjs.com/package/cors
so I went through the installation guide and added it to my solution:
....
var cors = require('cors');
....
app.use(cors());
app.options('*', cors())
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
Also, without luck.
I am pretty much out of ideas, and have no clue what could be the issue here.
Here is the client side:
login() {
if(this.input.username != '' && this.input.password != '') {
//We should execute our Axios here.
axios.post('http://localhost:8080/api/user/login',{
username:this.input.username,
password:this.input.password
})
.then(function (response) {
// handle success
console.log(JSON.stringify(response.data));
console.log(response.status);
console.log(response.headers);
//Router.push('Dashboard')
})
.catch(function (error) {
// handle error
console.log(JSON.stringify(error.data));
console.log(error.status);
console.log(error.headers);
})
.then(function () {
// always executed
});
} else {
console.log('A username and password must be present')
}
}
but that seems to be OK to me.
Post method itself:
router.route('/user/login/')
.post(function(req, res) {
var user = new User(); // create a new instance of the user model
user.username = req.body.username; // set the users name (comes from the request)
user.password = req.body.password;
User.findOne({ username: user.username}, function(err, dbuser) {
if (err)
res.send(err);
console.log('Error');
bcrypt.compare(user.password, dbuser.password, function(err, compareResult) {
console.log('Match!')
// create a token
var token = jwt.sign({ username: user.username }, secret, {
expiresIn: 86400 // expires in 24 hours
});
res.cookie("test", user.username);
res.status(200).send({ auth: true, token: token });
console.log(token);
});
});
});
When using the cors module here are the settings I use to allow everything cors related
const corsOptions = {
origin: true,
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
credentials: true,
preflightContinue: true,
maxAge: 600,
};
app.options('*', cors(corsOptions));
app.use(cors(corsOptions));

Categories