Fetch API not posting to Node.js server (body is empty) - javascript

I'm trying to use fetch() to post to another Node.js server I am running. When I take out the headers, my console prints '{}'. When I keep them in, nothing is printed when I call the function.
I have tried using curl and I receive '{}' as well.
//Server.js (what I am trying to POST to)
var express = require('express');
var app = express();
var PORT = 4000;
app.use(express.json());
app.post('/', function (req, res) {
console.log(req.body);
})
app.listen(PORT, function () {
console.log('server running on port: ' + PORT);
})
//Post function (this is inside a separate React component which will perform the POST)
postContents() {
var data = { username: 'example' };
fetch('http://localhost:4000/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.catch(error => console.error('Error:', error))
.then(response => console.log('Success:', JSON.stringify(response)));
}

You have to use the body-parser as a middleware for your express server.
const express = require('express');
const app = express();
const PORT = 4000;
const bodyParser = require('body-parser');
app.use(bodyParser.json());

without headers and with headers the result is different
the URL is fully qualified with host and port
These two points suggest you are making a cross origin request.
The solution is to have the server
accept and handle OPTIONS requests when required
issue CORS headers in the response

Related

How to handle parameter in POST request in expressJS

I am working on my first project in my company and stuck at post request using expressjs.
Below is my code for post request
const express = require('express')
const app = express()
const request = require('request')
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: true}))
app.use(bodyParser.json())
app.post('/cruamsApi/updateUsers', (req, res) => {
const DisplayName = req.body.DisplayName
const EmployeeNumber = req.body.EmployeeNumber
const RegDate = req.body.RegDate
const url = 'http://localhost:8009/CruAmsAPI/Employee'
request (
{
url: url,
json: true,
body: {
"EmployeeNumber": EmployeeNumber,
"DisplayName": DisplayName,
"RegDate": RegDate
}
},
function (error, response, body) {
if(!error) {
res.send(response)
} else {
res.send(error)
}
}
)
})
app.listen(PORT, () => {
console.log('server is listening port ' + PORT)
})
When I make a POST request, it is keep returning "EmployeeNumber parameter is required" error message from an API. I tried to double quote the keys "EmployeeNumber" but still having a same issue. Included headers too but didn't really work. POST request does work in POSTMAN.
Have you tried to send the EmployeeNumber in your request?
If it works in Postman, it should work. I think that your issue is in your front-end which doesn't send any EmplyeeNumber in the request.

Put request req.body is empty

As all my requests are working fine, I have a problem with the put. req.body stays empty and then gives that error :
errmsg: "'$set' is empty. You must specify a field like so: {$set:
{: ...}}"
PUT :
router.put('/books/:name', (req, res, next) => {
const localdb = db.client.db(process.env.DB_NAME);
const collection = localdb.collection(process.env.COLL_BOOKS);
collection.replaceOne(
{ "name": req.params.name },
{ $set: req.body },
function (err) {
if (err) throw err
res.status(201).send(true);
});
App.js
const express = require('express'),
app = express();
os = require('os');
const bodyParser = require('body-parser');
const cors = require('cors');
const router = require('./router.js')
require('dotenv').config()
app.use(cors());
app.use(bodyParser.json());
app.use('/api/v1', router);
const port = (process.env.PORT || '3001');
let server = app.listen(port, os.hostname(), () => {
let host = server.address().address,
port = server.address().port;
console.log("Example app listening at http://%s:%s", host, port);
});
axios request :
updateItem = newBook => {
Axios.put(process.env.REACT_APP_API_PATH_BOOKS + `${newBook.name}`, newBook)
.then(res => {
this.setState({ newBook: res.data });
this.props.history.push('/admin');
})
.catch(err => console.log(err));
}
I don't understand what I am doing wrong
Make sure you don't have any middlware stripping or incorrectly parsing the body. For instance, you may have a JSON body parser, and not be sending JSON data with JSON application headers.
Can you give a bit of context, in code, for how you are making the put request and also the result of logging the req in a pastebin?

Multiple axios calls in single route call: error: can't set headers after they are sent

I've read all the threads on stack I could find regarding this error, and while I have learned a lot about what could possibly be wrong conceptually, nothing I've applied from that learning has worked yet.
The problem is, in my app.get (using express) for the index page I first do an axios post for basic auth to the Jira Api. Then in the same .get method I do an axios get with an initial query I'd like to run. I am not explicitly setting headers again in this call, but when I try to render my results, I get the error. If I take out the res.render calls from my axios.get method, the rest of my script works fine.
I have tried to move all renders to a single render still in the app.get method, but outside of any promise callbacks from my axios calls. At that point my variables I set are undefined (I believe they're not being returned from the promise the way I want. It's not still in my code, but I have tried explicitly returning my variables inside my promise, but that doesn't work. I've also tried to return the entire axios.post function, no dice).
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const axios = require('axios');
const hbs = require('express-handlebars');
const port = process.env.PORT || 3000;
var app = express();
app.engine('.hbs', hbs({defaultLayout: 'main', extname: '.hbs'}));
app.set('view engine', '.hbs');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(cors());
app.get('/', (req, res) => {
const username = "jirauser";
const password = "jirapassword"
axios.post('https://myjirainstance.atlassian.net', {
username: username,
password: password,
headers: {
'Authorization': 'Basic ' + new Buffer(username + ":" + password).toString('base64'),
'Content-Type': 'application/json'
}
}).then (response => {
// console.log(res);
const message = response.data;
message;
res.render('index', {
message: "you're logged in"
});
}).catch(function(error) {
authError = error;
res.render('index', {
error: error
})
});
return axios.get('https://jamfsoftware.atlassian.net/rest/api/2/search?jql=assignee=carlton.brumbelow')
.then (response => {
console.log(response);
queryResponse = 'your query was successful'
}).catch( error => {
console.log(error);
queryError = error
});
// res.render('index', {
// message: message,
// authError: authError,
// queryResponse: queryResponse,
// queryError: queryError
// })
})
app.listen(port, () => {
console.log(`Server started on port ${port}`);
})

Req.body is empty, express

I am trying to make some client-server program using express. But no matter what I try req.body is always empty. I have searched for solutions, but the main problem in most cases is that 'Content-Type' or app.use(bodyParser.json()); are missing. I have got both, but it still doesn't work.
Here is my server side:
const express = require('express');
const app = express();
const port = 5000;
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.post('/', (req, res) => {
console.log(req.body);
res.send(req.body);
});
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
Here is client side:
const promise = fetch('http://127.0.0.1:5000', {
mode: 'no-cors',
credentials: 'include',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
'Accept' : 'text/plain;charset=UTF-8',
},
method: 'POST',
body: JSON.stringify({x: 2, y:3}),
});
The problem is the mode: 'no-cors'. You won't be able to set the Accept and Context-Type headers.

Parsing POST data with body-parser in Node.js app

I am trying to build a simple Node.js app which will parse data passed to it as POST requests from my AngularJS app. Below is the code used in my AngularJS app and my Node.js app. Problem I am facing is that I've searched the web trying to find how to parse (data and header) information passed in POST requests but failed to find any example, so any help with an example of parsing (data and header) passed in POST requests will help me a lot. Thanks.
Note: I am using express 4.1.2, body-parser 1.8.0.
Node app:
var express = require('express');
var http = require('http');
var bodyParser = require('body-parser');
var app = express();
app.set('port', process.env.PORT || 3000);
app.use(bodyParser.json());
app.post('/', function (req, res) {
console.log(req.body);
res.send(200);
});
http.createServer(app).listen(app.get('port'), function(){
console.log('Server listening on port ' + app.get('port'));
});
POST request code
var deferred = $q.defer();
var dataObj = {};
dataObj.name = 'Chan';
dataObj.email_address = 'email#domain.com';
var myToken = '1234567890';
$http({ method:'POST',
url: '/',
data: dataObj,
headers: { 'Token' : myToken
}
}).success(function(data,status,headers,config){
deferred.resolve(data);
}).error(function(data,status,headers,config){
deferred.reject(status);
});
return deferred.promise;
If you're setting data to a plain js object, angular is interpreting that as a urlencoded form with the various keys and values in that object.
So there's two possible fixes here. One is to add something like app.use(bodyParser.urlencoded({ extended: false })); after app.use(bodyParser.json());
The second possible fix is to change your $http call to post JSON instead of urlencoded data. For that, change data: dataObj, to data: JSON.stringify(dataObj), and add 'Content-Type': 'application/json' to your headers so that it looks like this:
headers: {
'Token' : myToken,
'Content-Type': 'application/json'
}

Categories