Express Post method can't read property 'toString' - node.js

I have an express server with the following Post call:
app.post('/api/guitars/' , function(req, res){
const body = req.body;
//var inputGuitar = new Guitar(body.guitarMake.toString(), body.guitarModel.toString(), body.guitarSerial.toString(), body.guitarColour.toString(), body.guitarOwnerId.toString(), body.guitarYear.toString());
db.query(`INSERT INTO Guitar (GuitarMake, GuitarModel, GuitarSerial, GuitarColour, GuitarOwnerId, GuitarYear) VALUES (?, ?, ?, ?, ?, ?)`,
[body.guitarMake.toString(), body.inputGuitar.guitarModel.toString(), body.guitarSerial.toString(), body.guitarColour.toString(), body.guitarOwnerId.toString(), body.guitarYear.toString()], function(err, res){
if (err) {
console.log(err);
} else {
res.status(200).json(res);
}
});
res.end();
});
My front end code which is a React.js app is console logging this JSON object:
{"guitarMake":"Fender",
"guitarModel":"Jazzmaster",
"guitarSerial":"000000001",
"guitarColour":"Placid Blue",
"guitarOwnerId":"dummyuser",
"guitarYear":"2019"}
Which gets generated at this block:
if (isValid) {
var guitar = {
"guitarMake" : this.state.GuitarMake,
"guitarModel" : this.state.GuitarModel,
"guitarSerial" : this.state.GuitarSerial,
"guitarColour" : this.state.GuitarColour,
"guitarOwnerId" : this.state.GuitarOwnerId,
"guitarYear" : this.state.GuitarYear
}
var json = JSON.stringify(guitar);
console.log(json);
// do something..
fetch("APIGATEWAY", {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: json,
}).then(res => {
console.log(res);
});
Everytime I send the request to the server I am getting an error saying: TypeError: Cannot read property 'toString' of undefined. When I console log the request on the backend express server it looks like this:
{ '{"guitarMake":"Fender","guitarModel":"Jazzmaster","guitarSerial":"000000001","guitarColour":"Placid Blue","guitarOwnerId":"dummyuser","guitarYear":"2019"}': '' }
I can't figure out why my request looks like this. It's only when it get sent through react app. On postman it looks normal on the server end. What am I doing wrong?

You seem to be getting the body as a string, not a json.
First, make sure you have added the json middleware to your server object:
app.use(express.json());
Second, you're using the wrong mime-type. If you intend the server to parse a json object, you should use application/json:
fetch("APIGATEWAY", {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json', // Here!
},
body: json,
}).then(res => {
console.log(res);
});

Related

Nodejs + Axios Post returns undefined value

I am using React + NodeJS & Axios but have been trying to send a post request but experiencing difficulties.
The request seems to be posting successfully, but all actions at the nodejs server is returning in the "undefined" data value, even if the data is passed successfully shown in the console.
REACT
const fireAction = (data1, data2) => {
const data = JSON.stringify({data1, data2})
const url = `http://localhost:5000/data/corr/fire`;
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'AUTHCODE',
}
}
axios.post(url, data, config)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
fireAction("Oklahoma", "Small apartment")
NODE
app.post('/data/corr/fire', async (req, res) => {
try {
const data = req.body.data1;
console.log(data)
} catch(e) {
res.send({success: "none", error: e.message})
}
});
Result of node: "undefined"
I have added the following body parser:
app.use(express.json());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
I am not sure why this error is happening. I see there is similar questions to mine: however none of them are applicable as I'm using both express and body parser which is already suggested.
You're POSTing JSON with a content-type meant for forms. There's no need to manually set content-type if you're sending JSON, but if you want to manually override it, you can use 'Content-Type': 'application/json', and access the response in your route with req.body. If it does need to be formencoded, you'll need to build the form:
const params = new URLSearchParams();
params.append('data1', data1);
params.append('data2', data2);
axios.post(url, params, config);

POST request to DeepL api through node.js not working

Can anyone spot any problems that may explain why the api client is giving me the forbidden error? I know the credentials are correct, as GET requests w the same info in the url work find.
Thank you in advance
app.get('/translate', (req, res) => {
var textToTranslate = "Hello friend"
const targetLanguage = "ES"
var link = `https://api-free.deepl.com/v2/translate`
var options =
{
method: 'POST',
headers: {
"Host": 'api-free.deepl.com',
"Content-Length": 54,
"Content-Type": 'application/x-www-form-urlencoded',
"User-Agent": "YourApp",
"Accept": "*/*",
},
body: JSON.stringify({
'auth_key': deeplAccessCode,
'text': textToTranslate,
'target_lang': targetLanguage
}),
}
return fetch(link, options)
.then((response) => {
console.log(response)
return response.json(); //Transform http body to json
})
.then((json)=> {
res.send(json) //return json to browser
})
.catch(e => {
console.log(e)
return res.sendStatus(400);
});
})
It's probably failing because you're setting your Content-Type of your body to be application/x-www-form-urlencoded (which is correct as per the DeepL API specification) but then you provide a JSON body (which would require content type to be application/json).
You need to provide a URL-encoded body instead, like the part you can also append to the URL after the ?. See also this answer on SO.

Not Able to get request body as desired

I am working on MERN stack and I have made an api for registering users. I am using axios to send request this is what i am doing with axios inside react
const body = {
'phone': phoneData.phoneNumber, \\ phoneData is a state
'lastName': 'Flintstone'
}
await axios({
method : 'post',
url : 'http://localhost:8000/userapi/register',
data : JSON.stringify(body),
header : {'Content-Type': 'application/json'}
});
After this in NodeJS i am trying to print req.body on the console an this is what i am receiving
{ '{"phone":"7428868740","lastName":"Flintstone"}': '' }
instead of that i want req.body to store
{ phone:"7428868740",lastName:"Flintstone" }
This is my route that is getting triggered
app.post('/userapi/register', (req,res) =>{
console.log(req.body);
/* rest code to register user */
}
With Axios, you don't need to call JSON.stringify, just send the object and the server will receive it correctly.
const body = {
'phone': phoneData.phoneNumber, // phoneData is a state
'lastName': 'Flintstone'
}
await axios({
method : 'post',
url : 'http://localhost:8000/userapi/register',
data : body,
headers : {'Content-Type': 'application/json'}
});
See documentation here
On the server-side, make sure there is a middleware to parse requests in JSON format.
You can
const config = {
header: {
"Content-Type": "application/json",
},
};
const res = await axios.post(url,body,config)

400 Bad request while fetching data in post call

I am running my React js web app in one port 3000.
For node server I am using 4000.
While calling fetch method it returns `400 Bad request'.
Error
POST http://localhost:4006/auth/admin 400 (Bad Request)
react code npm started in 3000 port
fetch('http://localhost:4000/auth/admin',
{ mode: 'no-cors',
method: "POST",
body: JSON.stringify({
username:"admin",
password:"1234"
}),
headers: {
"Content-Type": "application/json",
'Accept': 'application/json, text/plain, */*',
credentials: "omit", //
// "Content-Type": "application/x-www-form-urlencoded",
},
})
.then((response) => console.log(response));
node code running in 4000 port
const passport = require("passport");
const route = require("../constants/routeStrings");
const keys = require("../config/keys");
const processStatus = require("../constants/processStatus");
const success = {
status: processStatus.SUCCESS
};
const failute = {
status: processStatus.FAILURE
};
module.exports = app => {
app.post('/auth/admin', passport.authenticate("local"), (req, res) => {
res.send(success);
});
};
Do not stringify the body. Change from
body: JSON.stringify({
username:"admin",
password:"1234"
}),
to
body: {
username:"admin",
password:"1234"
},
The 400 response is raised by passport since it is unable to read your params. You need to tell your "node" app to parse them before your actual routes.
// Import body parser, you should read about this on their git to understand it fully
const parser = require('body-parser');
const urlencodedParser = parser.urlencoded({extended : false});
// before your routes
app.use(parser .json());
app.use(urlencodedParser) // This will parse your body and make it available for your routes to use
Then do your other calls.
Also, make sure that you are sending username and password keys, otherwise read the documentation on how to change these key names to something else
I suffered long hours, but I overcame it throw writing those lines of code blocks. I successfully send the request to the server's controller, hopefully yours: make it try.
First define a async function to make POST request:
async function _postData(url = '', data = {}) {
const response = await fetch(url, {
method: 'POST',
mode: 'cors',
cache: 'no-cache',
credentials: 'same-origin',
redirect: 'follow',
referrerPolicy: 'no-referrer',
headers: {
"Content-type": "application/json; charset=UTF-8"
},
body: JSON.stringify(data)
});
return response.json();
}
Now create a request JSON payload:
let requestPayload = {
propertyName1: 'property value1',
propertyName2: 'property value23',
propertyName3: 'property value',
So on
}
Note: Request model will be your desired model, what request payload you actually send.
Now make a request using this payload including your end point URL:
_postData('http://servername/example', requestPayload )
.then(json => {
console.log(json) // Handle success
})
.catch(err => {
console.log(err) // Handle errors
});
100% worked on my project.

In node-soap, how can I see/debug the generated XML SOAP request?

I try to use the node-soap module like this:
const soap = require('soap');
soap.createClient('some-wsdl-url', function(err, client) {
const args = {
'ValidateCustomerRequest': {
'memberNumber': 12345
}
};
client.ValidateCustomer(args, function(err, result) {
console.log(result);
});
});
Now I get an "invalid format" response from the webservice. To debug this I would very much like to see what the actual XML looks like that is sent to the webservice.
I already tried this one:
require('request').debug = true
... which was suggestes in another SO answer.
But the output is not that helpful:
[ERROR] REQUEST { uri:
Url { ... },
method: 'GET',
headers:
{ 'User-Agent': 'node-soap/0.18.0',
Accept: 'text/html,application/xhtml+xml,application/xml,text/xml;q=0.9,*/*;q=0.8',
'Accept-Encoding': 'none',
'Accept-Charset': 'utf-8',
Connection: 'close',
Host: 'xxx' },
followAllRedirects: true,
body: null,
callback: [Function] }
I don't see my "ValidateCustomerRequest" in there and body is null. Also I'm wondering why method is GET, shouldn't that be POST?
So does this debug output looks normal and/or is there another way to see the created XML request?
I overlooked this bit of the documentation:
Client.lastRequest - the property that contains last full soap request for client logging
You can log this within the callback of the webservice call. So above code will look like this:
const soap = require('soap');
soap.createClient('some-wsdl-url', function(err, client) {
const args = {
'ValidateCustomerRequest': {
'memberNumber': 12345
}
};
client.ValidateCustomer(args, function(err, result) {
console.log(result);
console.log('last request: ', client.lastRequest) // <-- here
});
});
This will output the generated XML request.

Resources