Node.js + body-parser object format changes when it reaches backend - json

I'm trying to send an object inside an another object from React frontend to Node/express backend using jquery ajax. The problem the data is received at the backend, it no longer looks follows the syntax of an object. Instead, it looks something like this:
{ 'data[name]': 'test name',
'data[size][height]': '123',
'data[size][weight]': '50' }
Here is the front end ajax call...
lendItem(){
let id = "5af3348742afc60ab71d7d80"
$.ajax({
url: '/api/items/' + id,
method: 'put',
data: {
'data': {
name: "test name",
size: {
height: 123,
weight: 50
}
}
},
success: (res) => {console.log(res)}
});
}
backend server...
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
// connect to mongodb
mongoose.connect('mongodb://localhost/promedical');
mongoose.Promise = global.Promise;
const app = express();
const port = process.env.PORT || 5000;
// parsing data that was received
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// initialize routes
app.use('/api', require('./routes/api'));
// error handling
app.use((err, req, res, next)=>{
res.status(422).send({error: err.message});
});
app.listen(port, () => {
console.log(`Listening on port ${port}`)
});
...and here is the route I'm interested in.
router.put('/items/:id', (req, res, next)=>{
console.log(req.body);
res.send("success");
});
I think this problem might have something to do with that body-parser. Is is possible to send objects inside an object via jquery ajax and have it keep it's form once it reaches the backend? If not, should I just send all the data inside one object and then parse it at the backend?

It turns out that the object called 'data' becomes a string after the backend has accepted the ajax call. Is there any way to prevent this from happening? I need to store that object into a database as an object, not as a string.

Related

I am trying to display a html file using res.sendFile in express

i am trying to implement a work flow, where, when the user logs in, the user credentials is posted to one of the routes in express via ajax to check if the user exists, if the user exists, the express route will send back a message "authorised" to the ajax call, and the success callback is invoked where another ajax call sends a header along with data to the express route(/reroute). This express /reroute api is trying to res.redirect to another route /homepage. Inside the /homepage route i am attempting to display a html file using res.sendfile, and the res.sendfile is not working.
my login ajax call
$(document).on("click", "#login", (e) => {
const email = $('#logemail').val().trim();
const pass = $('#password').val().trim();
$.ajax({
url: "http://localhost:4000/checkuserexists",
type: "POST",
dataType: "JSON",
data: {
email: email,
pass: pass
},
success: function(data, textStatus, request) {
console.log(data)
if (data.message === "authorised") {
const token = request.getResponseHeader('access-token');
localStorage.setItem("access-token", token);
$.ajax({
url: "http://localhost:4000/reroute",
type: "GET",
dataType: "JSON",
beforeSend: function(xhr) {
xhr.setRequestHeader('access-token', token);
},
data: {
redirectTo: 'homepage'
},
success: function(data) {
console.log(data + " from ajax ")
}
})
} else {
$('.alertbox').show();
$('.alertbox').text("User unauthorised");
}
}
})
})
my express route (/reroute)
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
if (req.header('access-token')) {
const token = req.header('access-token');
const redirectTo = req.query.redirectTo;
if (redirectTo === 'homepage') {
res.setHeader('access-token', token)
res.redirect('/homepage')
}
}
})
module.exports = router;
my homepage route
const express = require('express');
const path = require('path');
const token_middleware = require('../middlewares/jwtauth');
const router = express.Router();
router.use(express.static(path.join(__dirname, "../public")))
router.get('/', token_middleware, (req, res) => {
if (req.status === "exists") {
res.sendFile(path.join(__dirname, "../public/homepage.html"));
} else {
res.redirect('/');
}
})
module.exports = router;
You're requesting the URL with Ajax.
The browser asks for /reroute and gets a redirect to /homepage.
It then asks for /homepage and gets an HTML document.
It passes that HTML document to the JavaScript engine and jQuery tries to parse it as JSON (it ignores the Content-Type because you said dataType: "JSON") and errors.
If you want to do this with Ajax, then don't redirect. Return some JSON that tells your code the login was successful. Then you can navigate with client-side JS and the location object.
If you want to redirect, then use a regular form submission and not Ajax.

How to send the express "req" object to client side [duplicate]

This question already has answers here:
How can I print a circular structure in a JSON-like format?
(31 answers)
Closed 4 years ago.
I'm not sure if this is possible, but I would like to see the whole content of the req object in client side.
const express = require('express');
const app = express();
app.get('/', (req, res) => {
// send req object to the client
res.json(req);
});
app.listen(5000, () => {
console.log('Server successfully started on port 5000');
});
This will result in an error like:
TypeError: Converting circular structure to JSON
The req object contains a lot of data. I don't think that you need all of theses to be sent back to client side.
You should select what you want to send back, and be sure theses values are not posing a ciruclar issue.
Like :
res.json({
body: req.body,
});
Sends a JSON response composed of a stringified version of the specified data.
usage:
return res.json([statusCode, ] data);
Example:
var info = [
{id:1, name: "test 1"},
{id:2, name: "test 2"}
]
const express = require('express');
const app = express();
app.get('/', (req, res) => {
// send req object to the client
res.json(info);
});
app.listen(5000, () => {
console.log('Server successfully started on port 5000');
});
or i think that it's better to use body-parser

How to Parse JSON and use axios without express

I'm currently making a twitter bot with node.js and I don't want to make a server with express unless I have to.
// imports
var Twit=require('twit');
var bodyParser = require('body-parser');
// config.js has my authentication
var config = require('./config');
var axios = require('axios');
axios.get('https://api.reddit.com/r/worldnews/hot.json?', { params: { sort: 'hot', limit: 1 } })
.then(response => {
var redditdata= response.data;
console.log(redditdata);
console.log(response.status);
})
var T = new Twit(config);
T.post('statuses/update', { status: redditdata.data.children.data.title + " " + redditdata.data.children.data.url }, function(err, data, response) {
console.log(data)
});
How do I input the reddit title and the url in the twitter post request? I know how to do this if with express server but how do I without a express?
Declare a global variable and then assign "redditdata.data.children.data" to that global variable inside your axios function. then you can access the data you want from a global variable. Right now, you are trying to get "redditdata.data.children.data" inside another function and it does not work because of function scope.

No body in POST request

I'm working on a web-push notifications project. I want to send user subscriptions from my client to a node server.
Client side code
function sendSubscriptionToBackEnd(subscription) {
return fetch('/api/save-subscription/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(subscription)
});
}
Server side code
app.post('/api/save-subscription/', function (req, res) {
console.log(req.body);
}
The subscription object is a standard subscription with "endpoint" and "keys". I have already tried printing the subscription on the client side before sending it and it appears to be valid.
The problem is that the "req" object on the server side doesn't contain any "body" key. So, I don't know how to grab the subscription on the server side.
You might need the body-parser middleware if you don't have it already.
That's what parses the body of http requests, and gives you a nice parsed object to deal with.
In your server side code:
const bodyParser = require('body-parser');
const express = require('express');
const app = express();
app.use(bodyParser.json()); // <-- this guy!
app.post('/api/save-subscription', (req, res) => {
console.log(req.body);
return res.sendStatus(201);
});

nodeJS - make HTTPS request, sending JSON data

I would like to send an HTTPS POST from one nodeJS server to another. I have some JSON data I would like to send with this request (populated by a html form).
How can I do this? I am aware of https.request() but there does not seem to be an option to include JSON as a part of the query. From my research it seems possible with an HTTP request, but not an HTTPS request. How can I solve this?
const pug = require('pug');
var cloudinary = require('cloudinary');
var express = require('express');
var multer = require('multer');
var upload = multer({ dest: 'uploads/' });
var request = require('request');
var bodyParser = require('body-parser');
var options = {
hostname: 'ec2-54-202-139-197.us-west-2.compute.amazonaws.com',
port: 443,
path: '/',
method: 'GET'
};
var app = express();
var parser = bodyParser.raw();
app.use(parser);
app.set('view engine', 'pug');
app.get('/', upload.single('avatar'), function(req, res) {
return res.render('index.pug');
});
app.get('/makeRequest*', function(req, res) {
query = req['query'];
/*
Here, I would like to send the contents of the query variable as JSON to the server specified in options.
*/
});
You can send JSON data through a POST http request with the native https node module, as stated in the documentation
All options from http.request() are valid.
So, taking the http.request() example you can do the following:
var postData = querystring.stringify({
'msg' : 'Hello World!'
});
var options = {
hostname: 'www.google.com',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
var req = https.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
});
// write data to request body
req.write(postData);
req.end();
You should edit postData to your desired JSON object
I believe the below is what you want. Using the request library. See comments in the code for my recommendations.
...
var options = {
hostname: 'ec2-54-202-139-197.us-west-2.compute.amazonaws.com',
port: 443,
path: '/',
method: 'POST',
json: true
};
...
//making a post request and sending up your query is better then putting it in the query string
app.post('/makeRequest', function(req, res) {
var query = req.body['query'];
//NOTE, you cannot use a GET request to send JSON. You'll need to use a POST request.
//(you may need to make changes on your other servers)
options.body = { payload: query };
request(options, function(err, response, body) {
if (err) {
//Handle error
return;
}
if (response.statusCode == 200) {
console.log('contents received');
}
});
});
as matt mentioned you need to use request
to send JSON object not JSON.Stringify so that at the server you can receive it using:
app.post('/makeRequest', function(req, res) {
console.log (req.body.param1);
}
Use the following code:
var request = require("request");
request({
'url':"http://www.url.com",
method: "POST",
json: true,
body: {'param1':'any value'}
}, function (error, resp, body) {
console.log ("check response.");
});