Problem with POST request from React.js component to Node.js server - javascript

I'm trying to send data from client's inputs based on React.js to server written in Node.js which put it to DB. I have no errors and after submit, new records show in database but they are empty. I have two inputs and I'm joining them in one string and trying send it to DB (so DB has one property). Can you check my code and see what is wrong? Maybe something with headers...
This is function in React component:
addCompetitor = event => {
event.preventDefault();
const name = this.state.draftCompetitorName;
const lastname = this.state.draftCompetitorLastname;
fetch(`http://localhost:5000/competitors`, {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: `${name}${lastname}` })
})
.then(response => response.json())
};
This is server POST response:
app.post("/competitors/", urlencodedParser, function (req, res) {
const newCompetitor = new Competitor({ name: req.body.name });
newCompetitor.save().then(competitor => res.json(competitor));
});
And it's app configuration:
app.use(function (req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, OPTIONS, PUT, PATCH, DELETE"
);
res.setHeader(
"Access-Control-Allow-Headers",
"Content-Type",
"X-Requested-With"
);
res.setHeader("Access-Control-Allow-Credentials", true);
next();
});

If not first install bodyparser. This parses incoming request bodies in a middleware before your handlers, which will be available under the req.body property.
app.use(bodyParser.json({
limit: '50mb',
parameterLimit: 100000
}))
Alternatively what is the express version you are using ? Is it greater than 4.16? Then you can also use
app.use(express.json());
See notes here
https://expressjs.com/en/api.html#express.json
Modify your code
let databody = {
"name": `${name}${lastname}`,
"otherprop": this.state.otherprop
}
From frontend use
body: JSON.stringify(databody),
In express end remove urlencodedParser , should be like below:
app.post("/competitors", function (req, res) {
console.log(req.body);
});

You are using urlencodedParser as a middleware so I guess you used bodyParser.urlencoded({}) but your request is sending a json format. Try adjusting your request by adding the following header:
'Content-Type': 'application/x-www-form-urlencoded'
EDIT:
Also body should be in the following format:
body: `name=${name}${lastname}`

Related

I didn't get response from the nodejs server. It showing undefine after request to server

I hosted website on two different platforms like Firebase and Heroku
I Have some issues with that
Firstly, It showing cors errors when I post data from firebase hosted URL to the server which is hosted on Heroku
Then after resolving cors errors data couldn't from the server it showing undefined in console
Here is my server-side code which is hosted on Heroku
const express = require('express')
const path = require('path')
const PORT = process.env.PORT || 3000
const app = express()
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())
app.use(express.json({limit:'1mb'}))
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', 'https://sample-377b8.web.app');
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With,content-type,Accept,Authorization',);
res.header('Access-Control-Allow-Credentials', true);
if(req.method=="OPTIONS"){
res.header('Access-Control-Allow-Methods','PUT,POST,DELETE,PATCH')
return res.status(200).json({})
}
// Pass to next layer of middleware
next();
});
let data;
app.get('/',(req,res)=>{
res.send("hello world")
})
app.post('/',(req,res)=>{
data = req.body
console.log(data)
res.status(200).json({
"success":"200 response",
"res":"You are now just talked with server"
})
})
app.listen(PORT, () => console.log(`Listening on ${ PORT }`))
This is my client side code
document.getElementById('send').addEventListener('click',async()=>{
let data = {lat,lon}
await fetch('https://demoserver-app.herokuapp.com/',{mode:"no-cors"},{
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
}).then( async (dat) =>{
console.log(res.json())
}).then(res =>{
console.log(res)
})
})
It is giving the error on a console like
console error image
Headers information in the network tab
Header information of request image
I hope I can help you,
one issue that I see that can make this kind of output
is that you console.log(res) but .then referring to (dat)
And I don''t think you need async inside .then(it's already async function)
try this:
document.getElementById('send').addEventListener('click',async()=>{
let data = {lat,lon}
await fetch('https://demoserver-app.herokuapp.com/',{mode:"no-cors"},{
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
}).then( data =>{
data.json()
}).then(res =>{
console.log(res)
})
})
ok, so for the server side:
1)you need to destructure data from req.body, what you made is just adjust req.body to data bar.(see my solution)
2) for the post method you need to make a directory and not try it in the root directory.
try this code you will see the response you want
server:
app.post('/getmessage', (req,res) => {
const {data} = req.body;
console.log(data);
res.status(200).json({
"success":"200 response",
"res":"You are now just talked with server"
})
})
client:
fetch('http://localhost:3000/getmessage', {
method : 'post',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
data:"this is massage from client"
})
})
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.log(err))

React, axios, content-type

I have already searched a lot, but none of the solutions found work: Cannot send content-type by axios. but if I use the postman interceptor and I 'send' the request generated by axios this time it works: the node.js / express server correctly receives the request and body-parser works normally!
React side:
const API_URL = "http://localhost:8800/auth/";
const headers = {
accept: 'application/json, text/plain, */*',
'content-type': 'application/json;charset=UTF-8'
};
class AuthService {
register(pseudo, email, password) {
return axios.post(API_URL + "signup/",
{ pseudo, email, password },
{ headers: headers})
.then(response => {
if (response.data.accessToken) {
localStorage.setItem("user", JSON.stringify(response.data));
}
return response.data;
});
}
server side
const app = express();
app.use(function (req, res, next) {
console.log( req.headers);
next();
});
app.use( bodyParser.urlencoded({ extended: true }), bodyParser.json());
Usually when I use axios I send the headers in a config variable like this and I stringify the body so it sends as JSON object and not a JS object.
const config = {
headers: {
'Content-Type': 'application/json',
},
};
const body = JSON.stringify({arguments});
try {
const res = await axios.post(/url, body, config);
...
Here's a link to the docs for a little more reading about it:
https://github.com/axios/axios

node.js fetch post request returning index.html instead of json

I have a node.js app connected to a dialogflow bot I created, in which there's only one file: app.js.
I have index.html, index.js UI for the bot, which when I open unconnected to app.js, runs perfectly. I get json response from app.js
However, when I tried to include the UI (index.html and index.js) in app.js, the post method is returning index.html instead of the json it returned before, resulting in error: "SyntaxError: Unexpected token < in JSON at position 0" (because index.html is returned instead of json)
Here's my app.js
const dialogflow = require('#google-cloud/dialogflow');
const uuid = require('uuid');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const port = 9000;
const sessionId = uuid.v4();
app.use(bodyParser.urlencoded({
extended: false
}));
// ------------------The following code is the one I use for including the UI----------------------------------
const path = require('path');
app.use(express.static('botui'));
app.use('/', function(req,res){
res.sendFile(path.join(__dirname+'/botui/index.html'));
});
// ------------------------------Code for including the UI ended-----------------------------------------------
// ------------------When I did not use the above code and just opened file://index.html it worked great-------
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
app.post('/send-msg',(req,res)=>{
runSample(req.body.MSG).then(data=>{
res.send({
statusCode: 200,
body: {},
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
Reply:data})
})
})
/**
* Send a query to the dialogflow agent, and return the query result.
* #param {string} projectId The project to be used
*/
async function runSample(msg, projectId = 'bot_ID') {
// Create a new session
const sessionClient = new dialogflow.SessionsClient({
keyFilename:"BOT-KEY.json"
});
const sessionPath = sessionClient.projectAgentSessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
// The query to send to the dialogflow agent
text: msg,
// The language used by the client (en-US)
languageCode: 'en-US',
},
},
};
// Send request and log result
const responses = await sessionClient.detectIntent(request);
console.log('Detected intent');
const result = responses[0].queryResult;
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(` No intent matched.`);
}
return result.fulfillmentText;
}
app.listen(port,()=>{
console.log("Running on port: " + port)
})
And here's the code from index.js which sends the POST request:
fetch(url, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
method: 'POST',
body:data
})
.then(res => res.json())
.then(response => {
console.log(response);
serverMessage(response.Reply);
})
.catch(error => console.error('Error h:', error));
It seems you should replace app.use('/', function(req,res){ to app.get('/', function(req,res){
take a look at Difference between app.use and app.get in express.js

URL not fetching the data in React

I wanted to give a post request to the required URL but without proxy setting it was giving cors error, I have gone through and end up with setting the proxy but still it is taking the localhost as the URL. I have attached my proxyfile.js and my code snippet with the error below.
export function PostData(userData) {
var targetUrl = "/downloadableReport";
return new Promise((resolve, reject) => {
fetch(targetUrl, {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8",
Accept: "application/json"
},
body: JSON.stringify({
requestData: {
userName: userData.userName,
password: userData.password
}
})
}).then(response => response.json());
});
}
This is the setupProxy.js code:
const proxy = require("http-proxy-middleware");
module.exports = function(app) {
app.use(
proxy("/downloadableReport", {
target: "http://192.168.1.220:28080/xms/abc",
changeOrigin: true
})
);
};
And this is the error:
If CORS is the problem and you are using express as the backend server,
then
var allowCrossDomain = function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,PATCH,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, Role');
// intercept OPTIONS method
if ('OPTIONS' == req.method) {
res.sendStatus(200);
} else {
next();
}
};
and then add
app.use(allowCrossDomain);
Ditch the proxy. To me, your problem looks like, you're POSTing data to the React App itself. If you are indeed having both the API and React, in the same project, I would suggest that you split them.
If they are not indeed together, update the targetUrl to a proper url with the protocol and the domain. Like var targetURl = 'http://localhost:3000/downloadableReport.
UPDATE: I read your comment reply to Sudhir. Edit the target Url as the full path to the API var targetUrl = "http://192.168.1.220:28080/xmsreport/report/downloadableReport" and add the CORS code I have provided above to the API at 192.168.1.220:28080

body data not sent in axios request

I am trying to send data through axios request to my backend script, but the body looks empty.
Here's a request sent from front-end:
axios.request({
method: 'GET',
url: `http://localhost:4444/next/api`,
headers: {
'Authorization': token
},
data: {
next_swastik: 'lets add something here'
},
}).then((res)=>{
console.log("api call sucessfull",res);
}).catch((err)=>{
console.log("api call unsucessfull",err);
this.props.toggleLoading(false);
})
Here's a back-end:
app.get('/next/api', verifyToken, function(req, res) {
console.log(req.body);
})
But I am getting {} empty body. I am getting headers and other data but not data.
GET requests should not have a body.
Change the method from 'GET' to 'POST'
Like so:
axios.request({
method: 'POST',
url: `http://localhost:4444/next/api`,
headers: {
'Authorization': token
},
data: {
next_swastik: 'lets add something here'
},
})
and change your api to expect a post
app.post('/next/api', verifyToken, function(req, res) {
console.log(req.body);
});
or
Change the data property to params
axios.request({
method: 'GET',
url: `http://localhost:4444/next/api`,
headers: {
'Authorization': token
},
params: {
next_swastik: 'lets add something here'
},
})
and change the api to log out the params
app.get('/next/api', verifyToken, function(req, res) {
console.log(req.params);
});
and like #MaieonBrix said, make sure that your headers contain the content type that you are sending.
It looks like you only have two points left to make it work :
one : the http method should be set to POST instead of GET since you want to send something.
two : you can then add the http header (like what you did with the authorization header) Content-Type: 'application/json`
On the back-end don't forget to use some kind of body parser utility package like this one : body-parser and set it up with your app.
I suppose your server is using express, here is how you will do it with express :
const express = require('express');
const app = express();
const bodyParser = require('body-parser')
const jsonParser = bodyParser.json();
app.use(jsonParser); // use it globally
app.get('your_route', jsonParser, otherMiddleware, (req, res) => ...); // use it for specific routes
/* ... rest of your code */
If you get an error that "bodyParser is deprecated", try this -
app.use(express.json()); //To parse JSON bodies (Applicable for Express 4.16+)
And use "post" method, if you want to get data from body of the HTTP request.
Try this
this.axios('realties', { params: this.filter })

Categories

Resources