Express REST API fails when parsing a payload? - node.js

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());
});

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

Reactjs axios post response is not returning anything

I'm using axios.post() to edit a mysql database on the back end of my Reactjs app. The data gets through the post request to the back end fine. But I need to know when the post request finished and return some data from it to know if what the back end code ran worked correctly. I've tried the following where newEdit is an object with the information that's need in the back end
axios
.post('http://ip:3001/edit_table', newEdit)
.then((response) => {
console.log("response: ",response);
}, (error) =>{
console.log("error: ",error)
});
Neither of the console log statements get ran. Once again, the object does get to the routed nodejs file fine, I am just unable to get any kind of response. Anyone know what's happening? thanks.
if your backend code is OK and return response then you can following below example that works perfectly.
const updateData = async () => {
try {
const response = await axios.put(`https://jsonplaceholder.typicode.com/posts/${id}`, {
method: 'PUT',
body: JSON.stringify({
id: id,
title: post.title,
body: post.body,
userId: 1
}),
headers: {
"Content-type": "application/json; charset=UTF-8"
}
})
.then(response => response.json())
.then(json => console.log(json));
console.warn(response.data);
} catch (error) {
console.warn(error);
}
};
Make sure that your backend is returning a response to the client.
You can either use res.send or res.json. res.send([body]) is used to send HTTP response to the client while res.json(body) is used to send JSON response.
res.send([body])
res.send(new Buffer('whoop'));
res.send({ some: 'json' });
res.send('<p>some html</p>');
Example:
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('hello world')
})
app.listen(3000)
res.json([body])
res.json(null)
res.json({ user: 'tobi' })
res.status(500).json({ error: 'message' })
Example:
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.json({ success: true })
})
app.listen(3000)
References:
Express API reference
Node.js response object methods res.send and res.json

Proxy API request through Express return pending Promise instead of response

I am currently trying to work with the Atlassian Jira rest API. In order to not get a CORS error I go through the recommended route of not sending the request from the browser but proxy it through my express server.
Now as I am doing this, all I receive back in the app is a pending promise. I assume that I have not correctly resolved it at one point but I cant figure out where.
API Handler sending the request to the proxy:
const baseURL = `${apiConfig}/jiraproxy`;
export const testConnection = integration => {
return fetch(`${baseURL}/get`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(integration)
})
.then(handleResponse)
.catch(handleError);
};
Jira Proxy Endpoint on the Express Server
const baseURL = `rest/api/3/dashboard`;
router.post("/get", (req, res) => {
fetch(req.body.link + baseURL, {
method: "GET",
headers: { Accept: "application/json" },
auth: {
username: req.body.credentials.username,
password: req.body.credentials.token
}
})
.then(handleResponse)
.catch(handleError);
});
handleResponse & handle Error Methods:
async function handleResponse(response) {
if (response.ok) {
return response.json();
}
if (response.status === 400) {
const error = await response.text();
throw new Error(error);
}
throw new Error("Network response was not ok.");
}
function handleError(error) {
// eslint-disable-next-line no-console
console.error(`API call failed. ${error}`);
throw error;
}
Goal:
Send the request of sending a request to the proxy and return the resonse of the proxy as the return of the initial "testConction" method.
Error:
No errors thrown, but the response received in the Browser is a pending promise.
Change to the Jira Proxy router fixed it. Thanks to #jfriend00.
router.post("/get", (req, res) => {
return fetch(req.body.link + baseURL, {
method: "GET",
headers: { Accept: "application/json" },
auth: {
username: req.body.credentials.username,
password: req.body.credentials.token
}
})
// This is the part that changed
.then(response => handleResponse(response))
.then(jiraResponse => res.status(200).json(jiraResponse))
.catch(handleError);
});

Request body is empty in nodejs express post request

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

Resources