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 })
Related
I am using expressJS on the back end to make a very simple API since I am a beginner. I am sending a request to the back end from the front end and I expect the front end to receive a response. This works fine until I change the nodejs for it to make a second request before sending the original response back to the client. The process looks something like:
Front end sends a POST request
back end receives request, then:
makes its own POST request to a source
waits for this data to come back, then:
sends back a response to the original request from the front end including the data gotten from the second request.
This process works fine when I remove the few lines of code which send the second request, but when the NodeJs back end makes this second request, I get a 404 error returned to the front end - and this error does not come from the second request.
Here is the code:
front end:
function post() {
return new Promise(() => {
$.ajax("URL of my nodejs backend", {
method: "POST",
cache: false,
data: {
action: "test-https"
},
}).then(response => {
console.log(response);
});
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
nodejs backend (only the bits needed for this question)
const express = require("express");
//const $ = require("./djax.js");
const https = require('https');
const app = express();
app.post("/", (req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
const body = [];
req.on("data", (chunk) => {
body.push(chunk);
});
req.on("end", () => {
const parsedBody = Buffer.concat(body).toString();
//res.status(200).send("bod" + parsedBody);
// Now parsedBody will be like a query string: key1=val1&key2=val2
const queryObject = new URLSearchParams(parsedBody);
parseRequest(queryObject, res);
//console.log(parsedBody);
});
//console.log(body);
next();
});
function parseRequest(queryParameters, response) {
// Here, queryParameters is a QueryParams object holding the body of the request
// sendResponseFunc is the function which sends back the response for this
// current request.
// Now, we have access to the body of the request and we can use this
// to call the neccessary functions and logic, after which
// send a response back to the front-end via the second
// parameter
const action = queryParameters.get("action");
switch(action.toLowerCase()) {
// ... other cases ...
case "test-https":
sendHttpsRequest(response);
break;
default:
response.status(200).send("Error: unknown action:'" + action.toLowerCase() + "'");
break;
}
}
function sendHttpsRequest(response) {
const postData = JSON.stringify({
works: true
});
const postOpts = {
host: "httpbin.org", // This is a test-server. Not mine.
path: "/post",
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(postData)
}
};
const newReq = https.request(postOpts, result => {
result.setEncoding("utf8");
res.on("data", chunk => {
console.log("Response" + chunk);
response.status(200).send("Request made from NodeJS end came back " + chunk);
});
});
newReq.write(postData);
newReq.end();
}
When I change the sendHttpsRequest function so that it does NOT make a request, like so:
function sendHttpsRequest(response) {
response.status(200).send("Hi");
}
... then the front-end receives the response and there is no error. There is a 500 internal server error only when the second request is made - when the function sendHttpsRequest is like in the penultimate snippet. I have tried to fix this for two days but I have no idea why this error is happening.
How can I make this second request from the NodeJS server and send back the contents of that without causing the 500 error?
You need to have error handling. You cannot expect that external requests will succeed all the time, for that reason you have to have res.on("error", ...) to respond the client appropriately.
However, I don't see a special case why you are using a data listener to collect payload chunks, it can be simplified very much.
Here is a very simple working example for you
// Backend
const express = require('express');
const axios = require('axios');
const cors = require('cors');
const app = express();
const port = 3000;
app.use(express.json()); // Accepts JSON as a payload
app.use(cors());
app.post('/', (req, res) => {
axios
.get('EXTERNAL URL')
.then((response) => {
console.log('Received payload', req.body);
// Handle response
res.json({data: response.data}).status(201);
})
.catch((error) => {
// Handle error
res.json({
message: error.message,
code: 422})
.status(422);
});
});
app.listen(port, '0.0.0.0', () => console.log(`Started at //127.0.0.1:${port}`));
Required dependencies are
ExpressJS cors package
Axios HTTP client
Axios can be used in browsers as well
Here is your jQuery Ajax request which sends JSON payload instead of FormData
// FE jQuery
function post() {
return new Promise((resolve, reject) => {
$.ajax('http://127.0.0.1:3000', {
contentType: 'application/json; charset=utf-8',
dataType: 'json',
method: 'POST',
data: JSON.stringify({
action: 'test-https',
}),
success: (data) => resolve(data),
error: (err) => reject(err),
});
});
}
post().then(console.log).catch(console.error);
I am making an Express application that takes in (binary) post data. Here is my code below.
Server-side:
var express = require('express');
var app = express();
var PORT = 3000;
app.use(express.raw());
app.post('/', function(req, res) {
console.log(req.body);
res.end();
});
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
app.listen(PORT, function() {
console.log("Server listening on port", PORT);
});
index.html:
<script>
fetch("/", {
method: "POST",
body: "hello world",
});
</script>
However, when I run this code, when logging the request body, it logs an empty object. And when I looked at the documentation, it says that the request body will be an empty object if there was no body to parse. But I had a body in the request. What am I doing wrong here?
express.raw() only works if you set your Content-Type header in your fetch to `application/octet stream. So your new fetch method would look like this.
fetch("/", {
method: "POST",
body: "hello world",
headers: {
"Content-Type": "application/octet-stream"
}
});
But what if you don't want the content type to be application/octet-stream? In this case, you can specify in the express.raw() options that the content type to parse the body can be any type. How to do this? Replace this:
app.use(express.raw());
With this:
app.use(express.raw({type: '*/*'}));
The type option is the needed content type for body-parser to parse the body, and the */* means that any content type will be accepted.
For express.raw() to parse, add "Content-Type": "application/octet-stream" inside headers in your fetch(). Like so:
fetch("/", {
method: "POST",
body: "hello world",
headers: {
"Content-Type": "application/octet-stream",
},
});
Use this for your usecase
app.use(express.text());
I made a node server with the three packages express, body-parser and cors.
I am trying to access data from client-side in my app.js with an async/await function that has a post request with the required data that I want to fetch
here's the fetch request and the post request in app.js, I am trying to pass the data [temperature, date, userResponse] via the postData function in app.js:
//post routes
const postData=async function postData(url = 'http://api.openweathermap.org/data/2.5/weather?zip=', data = {}) {
const response = await fetch(url, {
method: 'POST',
mode: 'cors',
cache: 'no-cache',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json'
},
redirect: 'follow',
referrerPolicy: 'no-referrer',
body: JSON.stringify(data)
});
return await response.json();
}
postData('/add', {temperature: '1', date: '2', userResponse: '2'});
}
and here's the server side code where I made an add route as post route:
// Setup empty JS object to act as endpoint for all routes
projectData = {};
// Require Express to run server and routes
const express = require('express');
// Start up an instance of app
const app = express();
/* Middleware*/
//Here we are configuring express to use body-parser as middle-ware.
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Cors for cross origin allowance
const cors = require('cors');
app.use(cors());
// Initialize the main project folder
app.use(express.static('website'));
const port = 3000;
// Setup Server
const server=app.listen(port, ()=>{console.log(`running on localhost: ${port}`)});
app.get('/all', sendData);
function sendData (request, response) {
response.send(projectData);
};
// TODO-ROUTES!
const data=[]
app.post('/add', function(req,res){
data.push(req.body)
console.log(data)
})
here's what I got when I ran the project on localhost:3000
I want the the parameters temperature, date and userResponse to appear in the console
the errors at line 35 related to the post request are :
app.js:35 POST http://localhost:3000/add net::ERR_EMPTY_RESPONSE
app.js:48 Uncaught (in promise) TypeError: Failed to fetch
never mind the errors at the two above lines related to the get request
in vs code I can see this(the temperature, date and userResponse appear in the terminal but don't appear in the localhost:3000 console in the browser):
I just need the client-side to pass data to server-side dynamically and not just pass the response in the server-side
You are not sending any response back from the server. Send some response as below
app.post('/add', function(req,res){
data.push(req.body)
console.log(data)
return res.send({}); //return whatever response you need to send
})
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}`
I'm sending data in my React component via the Fetch API, and returning the result as JSON. When POSTED on my Express server, I use the jsonParser method from bodyParser to parse through the data, but insead I'm only getting back a empty object. I do not understand what's the issue with jsonParser, because if I use textParser, my data get sent fine.
Edit: When printing out the request (req) on the server, it is showing that nothing was received in the body. This only happens with jsonParser though, and not textParser.
Fetch:
fetch('./test',{
method: 'POST',
body: ["{'name':'Justin'}"]
})
.then((result) => {
return result.json();
})
.then((response) => {
console.log(response);
})
.catch(function(error){
//window.location = "./logout";
console.log(error);
});
Express:
app.use('/test', jsonParser, (req,res) =>{
res.json(req.body);
})
Assuming you want to post the {name: 'Justin'} object, you'll want something like
fetch('test', {
method: 'POST',
body: JSON.stringify({name: 'Justin'}),
headers: new Headers({
'Content-Type': 'application/json; charset=utf-8'
})
})
The body parameter does not accept an array (which is what you were passing).
If you did mean to post an array, simply change the body value to
JSON.stringify([{name: 'Justin'}])