Object property key is different within req.body than client-side (Express) - node.js

I'm a bit of a noob working on my first CRUD application (dream journal) using Node, Express, and MongoDB/Mongoose.
I'm creating a simple object based on a few user form inputs and then submitting a post request to the server, which in turn calls Mongoose.save().
The object I'm creating on the client side, however, is slightly different than the one that is being received by the server, and I'm at a complete loss as to why.
First I'm getting some values from a form and putting them in an object:
// within button click event handler
var dreamText = $('#dream-text').val().trim();
var dreamTags = ["tag 1", "tag 2", "tag 3"]; // for debugging
var dreamLucid = $('#dream-lucid').val() == 'Yes' ? true : false;
var dreamDate = $('#dream-date').val();
var dream = {
userID: 'test',
text: dreamText,
tags: dreamTags,
isLucid: dreamLucid,
dateCreated: dreamDate
};
Here a console.log of dream shows everything as it should be:
Object {userID: "test", text: "sample text", tags: Array[3], isLucid: false, dateCreated: "2016-08-08"}
From there I'm submitting a POST request with the dream object:
$.ajax({
type: 'POST',
url: '/new',
data: dream,
success: function(data){
console.log('dream saved');
}
});
Now on the server side, with Express and Mongoose, I'm attempting to save the object to a DB:
router.post('/', urlencodedParser, function(req, res) {
console.log(req.body);
var newDream = Dream(req.body).save(function(err, data){
if (err) {
throw error;
}
});
});
All the properties except tags are saving correctly, and a console.log of req.body yields:
{ userID: 'test',
text: 'sample text',
'tags[]': [ 'tag 1', 'tag 2', 'tag 3' ],
isLucid: 'false',
dateCreated: '2016-08-08' }
Any idea why the tags property on the client side is becoming 'tags[ ]' when it gets passed through the POST request?
I've tried both tags: Array and tags: [String] in my Mongoose Model, but the problem seems to be occurring before I ever call Mongoose.save.

By default, $.ajax() encodes a POST operation as application/x-www-form-urlencoded which does different things with arrays. You probably just want to send JSON so you can receive JSON on the server.
You can cause that to happen by manually turning your data into JSON and setting the content type appropriately:
$.ajax({
type: 'POST',
url: '/new',
data: JSON.stringify(dream),
contentType: "application/json",
success: function(data){
console.log('dream saved');
}
});
Then, you may also have to parse the JSON on the server side of things, either manually for this request or with some middleware like bodyParser.json().

Related

How to send array of object from postman which has file in it

I want a request from postman in particular format but I don't know how to do it.
So, I want to send data from postman to my local API in array of object.
That object contains textual information and may one file and I have multiple objects like that.
for e.g. :
[{
id: 1,
question: How are you ?,
answer: I am fine.
},
{
id : 2,
question: "upload your document",
answer: [file]
}
]
This is how my request looks on postman,
And this is how i am getting it in backend
{ additonalQuestion:
[ '12',
'Upload your document',
'file',
'13',
'How old are you ?',
'text',
'16' ] }
I am using formidable node package to read it. and following is the code
const formidable = require('formidable');
const form = formidable({ multiples: true });
await form.parse(req, (err, fields, files) => {
console.log('fields: ', fields);
});
To summarise my question , How to can i make a request from postman where i can get request like
[{
id: 1,
question: How are you ?,
answer: I am fine.
},
{
id : 2,
question: "upload your document",
answer: [file]
}
]
In backend.
Thank you for your time :)

JSON not being parsed for validation when doing a POST request to Fastify

In my routes, I have the following:
const reservationSchema = {
body: {
type: 'object',
required: ['in', 'out', 'guests', 'language', 'roomsSelected'],
properties: {
language: {
type: 'string',
},
// ... several other property validations here
}
}
};
fastify.post(
'/api/reservations/:slug',
{ schema: reservationSchema },
reservationsController.addReservation
);
I send the POST request from React like this:
const response = await fetch(process.env.REACT_APP_API_HOSTNAME + '/api/reservations/' + property.slug, {
method: 'POST',
body: JSON.stringify(requestBody)
});
I can see that it is correctly sending JSON when I look at the request:
However I receive the following response:
{
"statusCode":400,
"error":"Bad Request",
"message":"body should be object"
}
Am I missing something to automatically parse the POST body as an object in Fastify so I can validate it using a validation schema? Even in my reservationsController.addReservation() function I need to manually do JSON.parse() on req.body.
From the fetch() docs:
Both request and response (and by extension the fetch() function), will try to intelligently determine the content type. A request will also automatically set a Content-Type header if none is set in the dictionary.
However, (at least in Chrome), when you send a JSON string, it does not intelligently determine that this string is JSON, and instead sends the Content-Type header as text/plain;charset=UTF-8. Since the server receives this Content-Type header, it assumes that you are sending a plan text string and therefore does not parse it as JSON.
To make the server automatically parse the body as JSON, you need to make sure to set the Content-Type header to application/json. Like this:
const response = await fetch(process.env.REACT_APP_API_HOSTNAME + '/api/reservations/' + property.slug, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestBody)
});

API design relating to AJAX and the way data is obtained

i've designed a RESTful API that im now testing, its a bog standard follow a tutorial API with some routes and a db context,
The requests are looking for "Name"...
But in Ajax, you have to specify it in "Data" and so then the request becomes Data[Name:]
should i be re-designing my API so that they all take Data[] now?
function handleLoginData() {
form = document.getElementById("LoginForm");
let name = form.name.value;
let email = form.email.value;
let password = form.password.value;
$.post('http://localhost:3000/api/users/register', {
dataType: 'json', // type of response data
timeout: 500, // timeout milliseconds
processData: false,
data: {
name: name,
email: email,
password: password
},
success: function(data, status, xhr) { // success callback function
console.log(data);
},
error: function(jqXhr, textStatus, errorMessage) { // error callback
console.log(errorMessage);
}
});
}
will return:

Axios post request body is just an empty object on the server side (React - Axios - Node.js - Express)

I was trying to send a post request to my server and was using this:
let dataToReturn = {
method: "POST",
url: "http://localhost:9000/logData",
headers: { "testing" : "IT WORKED" },
body: {"hola" : 'testing to see if this counts'}
}
axios(dataToReturn)
It know it would send. I checked the network tab in inspector and could see that it was sent, and could do req.headers on the server and it would print out the headers. But whenever I tried to log req.body on the server it would just print out '{}'
var body = {
firstName: 'testName',
lastName: 'testLastName'
};
axios.post('http://localhost:9000/logData', body)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
This works tho ^^ and successfully prints out the body when I do 'req.body'
Why does the top example log an empty object?
Here's what the route looked like on the server side
app.post('/logData', function(req, res) {
console.log('recieved post');
console.log(req.body);
res.sendStatus(200);
})
I acknowledge that I'm a noob and this might be a dumb question, so please excuse my ignorance. Also happy to post more info if you need it.
You need to add content type in the header of your request.change your header as mentioned below
headers: { "testing" : "IT WORKED","Content-Type":"application/json" },

Node.js Problem redirecting routine post method

I write here for who can help me, since I'm new to NodeJS, I'm trying to do something simple, but in the end it doesn't work for me.
I want from the frontend, to make a request to the backend, through the ajax post method. When executing it, from the frontend send a JSON object to the backend and then from the backend it must redirect to another page to the frontend (the latter is what I could not achieve)
Example of what I try
Frontend
var objAgente = {
"FIRSTNAME": "PEDRO",
"LASTNAME": "PEREZ",
"NRORUT": "123456789",
"NROAGENT": "3",
"HRCONNECT": "12:12:12"
};
$.ajax({
type: 'POST',
url: '/LoginAgente',
data: JSON.stringify({ "objectData": objAgente}),
success: function(data) {console.log('todo OK')},
contentType: "application/json",
dataType: 'json'
});
Backend
const express = require("express");
const router = express.Router();
router.use(express.json())
router.use(express.urlencoded({ extended: true }))
router.get('/', (req, res)=>{
res.render('loading.html', { title: 'Iniciando Sistema'});
});
router.get('/Inicio', (req,res)=>{
res.render('confInitial.html', { title: 'Inicio de Sistema'});
});
router.get('/Agente', (req,res)=>{
res.render('PanelAgente/Agente.html', { title: 'Equipo solo Agente'});
});
router.post('/LoginAgente', function (req, res) {
var newUser = req.body;
console.log(newUser);
res.redirect('/Agente');
});
module.exports = router;
When I execute the sending of the JSON object to the backend, the data arrives since I can print it by console, but the res.redirect is not fulfilled;
It does not return an error, but it does not redirect me to where I want.
Thank you very much to those who can give me an idea of ​​what happens
Instead of
res.redirect('/Agente');
Try
res.send({redirect: '/Agente'});
UPDATE:
Frontend
var objAgente = {
"FIRSTNAME": "PEDRO",
"LASTNAME": "PEREZ",
"NRORUT": "123456789",
"NROAGENT": "3",
"HRCONNECT": "12:12:12"
};
$.ajax({
type: 'POST',
url: '/LoginAgente',
data: JSON.stringify({ "objectData": objAgente}),
success: function(data) {
if (data && data.redirect) {
window.location.href = data.redirect;
}
},
contentType: "application/json",
dataType: 'json'
});
Hope this helps!
as you are sending request using AJAX , server can not redirect to other page in AJAX request , you have to redirect user after you getting response from AJAX
$.ajax({
type: 'POST',
url: '/LoginAgente',
data: JSON.stringify({ "objectData": objAgente}),
success: function(data, textStatus, request){
// add redirect link here
window.location.href = '/add_link_to_redirect_here';
},
contentType: "application/json",
dataType: 'json'
});
No need to change backend code, since it may be useful in future when will need non-ajax authentication.
So simply try to get Location header from response and redirect using window.location.href
FRONTEND
var objAgente = {
"FIRSTNAME": "PEDRO",
"LASTNAME": "PEREZ",
"NRORUT": "123456789",
"NROAGENT": "3",
"HRCONNECT": "12:12:12"
};
$.ajax({
type: 'POST',
url: '/LoginAgente',
data: JSON.stringify({ "objectData": objAgente}),
success: function(data, textStatus, request){
const redirectTo = request.getResponseHeader('Location');
if (redirectTo) {
window.location.href = redirectTo;
}
},
contentType: "application/json",
dataType: 'json'
});
i think if you're trying to use and see entire body
var newUser = req.body;
console.log(newUser);
you should in your front pass the object like:
data: JSON.stringify(objAgente)
and do what you're doing:
req.body
cause if you're passing you're object into a new object he'll understand that you're gonna access these proprieties inside the obj, like:
req.body.objectData.FIRSTNAME

Resources