Request body is empty in nodejs express post request - node.js

i have troubles to send simple json data from javascript ajax client to nodejs express rest api.
Here is the server side code:
//POST api/login
app.post('/api/login', (req, res) => {
console.log(req.body)//here the body always empty object
var body = _.pick(req.body, ['email', 'password'])
console.log(body)
var user;
User.findByCredentials(body.email, body.password).then((result) => {
user = result
return user.generateAuthToken()
}).then((token) => {
res.status(200).header('x-auth', token).send(user)
}).catch((e) => {
res.status(400).send('Unauthorized')
})
})
Here is the client side:
$(document).ready(function(){
jQuery('#login-form').on('submit', function(e){
e.preventDefault()
var username = jQuery('[name=username]').val()
var password = jQuery('[name=password]').val()
if(username && password){
let dataToSend = {
"email":username,
"password":password
}
console.log(dataToSend)
$.ajax({
url:"http://192.168.1.22:3000/api/login",
type: "POST",
data: dataToSend,
headers: {
'Access-Control-Allow-Origin':"*",
'Content-Type': 'application/json; charset=utf-8',
Accept: 'application/json'
},
dataType: 'json',
cache: false,
success: function(data){
console.log('on success : '+data);
},
error: function(e){
console.log("login error, status: "+e.status +" message :
"+e.responseText);
}
})
}
})
})
The problem is if i send the request like this i get crash error on server side :
SyntaxError: Unexpected token e in JSON at position 0
at JSON.parse (<anonymous>)
at createStrictSyntaxError (D:\NodeJs-Projects\location-tracker-server\node_modules\body-parser\lib\types\json.js:158:10)
at parse (D:\NodeJs-Projects\location-tracker-server\node_modules\body-parser\lib\types\json.js:83:15)
at D:\NodeJs-Projects\location-tracker-server\node_modules\body-parser\lib\read.js:121:18
at invokeCallback (D:\NodeJs-Projects\location-tracker-server\node_modules\raw-body\index.js:224:16)
at done (D:\NodeJs-Projects\location-tracker-server\node_modules\raw-body\index.js:213:7)
at IncomingMessage.onEnd (D:\NodeJs-Projects\location-tracker-server\node_modules\raw-body\index.js:273:7)
at emitNone (events.js:106:13)
at IncomingMessage.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1056:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickCallback (internal/process/next_tick.js:180:9)
If i remove the headers data from request it will not crash but i always receive empty body at server, and the most annoying is if i make the same request from android native client with okHttp library all work perfect.
Do i miss something?

Ok so after many many of combinations i solved it, for some reason only after i called JSON.stringify(dataToSend) and added contentType: "application/json;charset=utf-8" to the request i successfully was able to receive data at the server.
Still it is not clear to me why need to stringify the data.
full client code:
$(document).ready(function(){
jQuery('#login-form').on('submit', function(e){
e.preventDefault()
var username = jQuery('[name=username]').val()
var password = jQuery('[name=password]').val()
if(username && password){
let dataToSend = {
"email":username,
"password":password
}
dataToSend = JSON.stringify(dataToSend)
console.log(dataToSend)
$.ajax({
url:"http://192.168.1.22:3000/api/login",
method: "POST",
data: dataToSend,
contentType: "application/json;charset=utf-8",
dataType: 'json',
cache: false,
success: function(data){
console.log('on success : '+data);
},
error: function(e){
console.log("login error, status: "+e.status +" message : "+e.responseText);
}
})
}
})
})

Related

Axios bad request status 400

I'm having this issue AxiosError: Request failed with status code 400
I checked the console and I test manually the url and It worked, so I don't know what's wrong, this code:
//file controller.js
//Set Create Session
exports.setSession = async (req, res) => {
const data = await request({
path: process.env.APP_LOCALHOST_URL + urlLogin.setCreateSession,
method: 'POST',
body: JSON.stringify(req.body)
});
return res.json(data);
}
//file request.js
exports.request = async ({path, method = "GET", body }) => {
try {
const response = await axios({
method: method,
url: path,
headers: {
'Content-Type': 'application/json'
},
body: body
});
return response;
} catch (error) {
console.log("error: ", error);
}
}
the function setSession is to call in my routes file, and the function request is my reusable component. My intention is to use the function request in many functions, these could be of the GET, DELETE, PUT, POST, PATCH type.
So, currently I get this on console:
data: {
error: '5',
errorId: 'badRequest',
errorString: 'Internal error: Undefined JSON value.'
}

How to make httpRequest from parser cloud server(back4app) to another server

How to make http request from parse cloud server(back4app) to another server, here i am making request to fake json api https://jsonplaceholder.typicode.com/todos/1
main.js
Parse.Cloud.define("hello", async (request) => {
return Parse.Cloud.httpRequest({
url: 'https://jsonplaceholder.typicode.com/todos/1',
followRedirects: true,
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
}
}).then(function(response){
console.log(response.text)
//return response.text;
//return response.success(response.text)
//resData=100;
return 100; //i am not even returning the response,i am returning a just a const
},function(httpResponse) {
console.error('Request failed with response code ' + httpResponse.status);
})
});
App.js
const cloudFunction=async()=>{
const someVar=10
Parse.Cloud.run('hello').then((response)=>{
console.log(response)
}).catch((error)=>{
console.log(JSON.stringify(error))
})
}
can some body help,thank you good people of stackoverflow

React-native node.js showing Error: Multipart: Boundary not found while uploading image using react-native-image-picker

While Uploading image , It is showing Error: Multipart: Boundary not found on node js server console
here is my react native code
const createFormData = async (photo, body) => {
const data = new FormData();
console.log("photoooooooooooo",photo.fileName);
data.append("photo", {
name: photo.fileName,
type: photo.type,
uri:
Platform.OS === "android" ? photo.uri : photo.uri.replace("file://", "")
});
Object.keys(body).forEach(key => {
data.append(key, body[key]);
});
console.log("datatyeeeeeeeeeeeeee",data);
return data;
};
const chooseFile = async() => {
var options = {
title: 'Select Image',
customButtons: [
{ name: 'customOptionKey', title: 'Choose Photo from Custom Option' },
],
storageOptions: {
skipBackup: true,
path: 'images',
},
};
ImagePicker.showImagePicker(options, response => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
alert(response.customButton);
} else {
let source = response;
// You can also display the image using data:
// let source = { uri: 'data:image/jpeg;base64,' + response.data };
setfilePath(source);
// postImage(source);
handleUploadPhoto(source);
}
});
};
const handleUploadPhoto = async (filePath) => {
fetch("http://192.168.43.118:3000/updateImageprofile2", {
method: "POST",
body: createFormData(filePath, { userId: "123"}),
headers: {
Accept: 'application/json',
// 'Content-Type': 'image/jpeg',
'Content-Type': 'multipart/form-data',
// 'Content-Type': 'application/octet-stream'
},
})
.then(response => response.json())
.then(response => {
console.log("upload succes", response);
alert("Upload success!");
// this.setState({ photo: null });
})
.catch(error => {
console.log("upload error", error);
alert("Upload failed!");
});
};
and backend node js
router.post("/updateImageprofile2", upload.single('photo'), (req, res,next) => {
console.log("I am in");
console.log('files', req.files)
console.log('file', req.file)
console.log('body', req.body)
res.status(200).json({
message: 'success!',
})
});
but on the node js console it is showing
Error: Multipart: Boundary not found
at new Multipart (C:\react\udemy_react\start\emb\auth_server2\node_modules\busboy\lib\types\multipart.js:58:11)
at Multipart (C:\react\udemy_react\start\emb\auth_server2\node_modules\busboy\lib\types\multipart.js:26:12)
at Busboy.parseHeaders (C:\react\udemy_react\start\emb\auth_server2\node_modules\busboy\lib\main.js:71:22)
at new Busboy (C:\react\udemy_react\start\emb\auth_server2\node_modules\busboy\lib\main.js:22:10)
at multerMiddleware (C:\react\udemy_react\start\emb\auth_server2\node_modules\multer\lib\make-middleware.js:33:16)
at Layer.handle [as handle_request] (C:\react\udemy_react\start\emb\auth_server2\node_modules\express\lib\router\layer.js:95:5)
So there is a button which I click then choosefile function calls and after choosing files it goes to handlephoto function where the body part formdata create or append the image data into body then send the data to node js server where I am trying to upload image on upload folder but it is not happening. Please help me , I am trying it since morning and its evening
TL;DR Try omitting the Content-Type header. If it's not set, the browser will set it for you and it'll also configure the boundary.
The referenced boundary is the boundary you must provide alongside multipart/form-data. In your example it has not been provided.
When sending a request with content of type multipart/form-data you must provide the boundary value.
POST /test HTTP/1.1
Host: foo.example
Content-Type: multipart/form-data;boundary="boundary"
--boundary
Content-Disposition: form-data; name="field1"
value1
--boundary
Content-Disposition: form-data; name="field2"; filename="example.txt"
value2
--boundary--
MDN: HTTP POST Method
In your post request, you are providing this content type without a boundary, which results in an error when the content is parsed.
However, often the easiest solution is to omit this header entirely. In this case the browser will configure this header for you--it'll also manage the boundary for you.

Express REST API fails when parsing a payload?

I am new to NodeJS + Express development. I want to build a REST API that can receive JSON data via POST. I was able to build the API in Express and receive a json payload from a transmission from the postman software. But when I try to simulate the same behaviour with javascript's fetch() function from a web browser, my express rest api crashes with the following error:
SyntaxError: Unexpected token o in JSON at position 1
at JSON.parse (<anonymous>)
at parse (/home/johncomputer/projects/tt/node_modules/body-parser/lib/types/json.js:89:19)
at /home/johncomputer/projects/tt/node_modules/body-parser/lib/read.js:121:18
at invokeCallback (/home/johncomputer/projects/tt/node_modules/raw-body/index.js:224:16)
at done (/home/johncomputer/projects/tt/node_modules/raw-body/index.js:213:7)
at IncomingMessage.onEnd (/home/johncomputer/projects/tt/node_modules/raw-body/index.js:273:7)
at IncomingMessage.emit (events.js:215:7)
at endReadableNT (_stream_readable.js:1184:12)
at processTicksAndRejections (internal/process/task_queues.js:80:21)
I only have this one file called src/app.js in my express project:
const express = require('express')
const port = process.env.PORT
var cors = require('cors')
const app = express()
app.use(cors())
app.use(express.json())
router = express.Router()
router.post('/users', async (req, res) => {
try {
console.log("+++++++++++")
console.log(req)
console.log("=========")
res.status(201).send({ "world":true })
} catch (error) {
res.status(400).send(error)
}
})
app.use(router)
app.listen(port, () => {
console.log(`Server running on port ${port}`)
})
I'm not sure if I'm using cors() correctly, but I threw it in there to get around a pre-flight OPTIONS issue that was causing my fetch() to generate a failed network connection error (which didn't occur for postman).
This was my javascript fetch code:
const postData = {"name":"John","email":"john#john.com","password":"chocolate-raisins!!!"};
fetch("http://johnserver.com:3000/users", {
method: "POST",
headers: {'Content-Type': 'application/json'},
body: postData
}).then((response)=>{
console.log(response);
if(!response.ok) return {}
return response.json();
}).then((result)=>{
console.log(result);return;
}).catch(function(error){
alert("Post Request Error: "+error.toString());
});
What am I doing wrong that's causing my API to fail with fetch() but not with postman?
EDIT
The output of the response variable from my fetch is this:
Response { type: "cors", url: "http://johnserver.com:3000/users", redirected: false, status: 400, ok: false, statusText: "Bad Request", headers: Headers, body: ReadableStream, bodyUsed: false }
The output of the result variable from my fetch is this:
{ }
On your fetch method please do this.
Insead of body:post Data do --> JSON.stringify(postData)
And also on your then function first return response.json() and then
check whatever parameters you want.
You're not sending valid you need to stringify your object.
fetch("http://localhost:3000/users", {
method: "POST",
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ "name": "John", "email": "john#john.com", "password": "chocolate-raisins!!!" })
}).then((response) => {
if (!response.ok) {
return {};
}
return response.json();
}).then((response) => {
console.log(response); return;
}).catch(function (error) {
alert("Post Request Error: " + error.toString());
});

make a post request with in node.js application

I've a node.js service with /api/authenticate endpoint. I can call this service successfully from POSTMAN with 'username' and 'password' as input (body parameters). How do I call the same services from another node.js server?
With postman I get,
body: {name: 'xxxxxx', password: 'xxxxxx' }
headers: { 'content-type': 'application/x-www-form-urlencoded',
host: 'xx.xx.xx.xx:xxxx',
connection: 'close',
'content-length': '0' }
POST /api/authenticate 200 1.336 ms - 72
Following is another nodejs application ... which makes a successful request call but doesn't have any body parameters (username and password) when it reaches to the authentication server api.
var my_http = require('http');
app.get('/makeacall', function(req, res) {
var output = '';
var options = {
body: { name: 'xxxxxx', password: 'xxxxxx' },
method: 'POST',
host: 'xx.xx.xx.xx',
port: 'xxxx',
path: '/api/authenticate',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};
console.log('before request');
var req = my_http.request(options, function(response) {
console.log('response is: ' + response);
console.log('Response status code: ' + response.statusCode);
response.on('data', function(chunk) {
console.log('Data ..');
output += chunk;
});
response.on('end', function(chunk) {
console.log('Whole Data ..' + output);
});
});
req.on('error', function(err) {
console.log('Error: ' + err);
});
req.end();
console.log('444');
res.send({ message: 'View record message'});
});
From this nodejs application I get empty body on the server.
body: {}
headers: { 'content-type': 'application/x-www-form-urlencoded',
host: 'xx.xx.xx.xx:xxxx',
connection: 'close',
'content-length': '0' }
POST /api/authenticate 200 1.336 ms - 72
What am I missing? Any help is appreciated.
Using stock http library of NodeJS doesn't allow you to use that syntax.
Take a look at RequestJS as a much simpler solution. It will make your life a lot easier and allow you to use the syntax you want.
This is the solution to do it with stock Node.
https://nodejs.org/api/http.html#http_http_request_options_callback
Relevant Parts:
var postData = querystring.stringify({
'msg' : 'Hello World!'
});
And then, at the end:
// write data to request body
req.write(postData);
req.end();
But use a library unless you absolutely can't.
Are you trying to get the posted data from a form/etc?
Try using express.
npm install express -save
You can get posted data from a url with the ff:
app.post('*', function(request, response){
var post = {};
if(Object.keys(request.body).length){
for(var key in request.body){
post[key] = request.body[key];
console.log(key+'=>'+post[key];
}
}
});

Resources