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
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
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.
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.
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.
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));