Node.js/express - server can't get my body from client - javascript

I am able to retrieve(get) data from express but cannot post data to express...
client:
<html>
<button onclick="myFunction()">send</button>
<script>
const data = {"experience" : 0};
function myFunction(){
fetch("/post", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
}
</script>
</html>
express:
Here I was getting undefined, but when I added express.json(), I got "{}". The client's and the server's conections are good, but there is no body where the data is stored?
I made sure my client code was working fine by posting data to webhooks.site, it worked fine.
I think there is some kind of rookie mistake... Btw, I am using react and express, I just simplified my code... any suggestions will be appreciated
const express = require("express");
const app = express();
app.post("/post", express.json() ,function (req,res){
console.log(req.body)
})
const port = 5000;
app.listen(port, () => `Server running on port ${port}`);

I have had to use Body Parser (simple) or Busboy (advanced) to access data in POST body with Express.
An example might look like:
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());
app.post("/post",(req,res,next)=>{
console.log(req.body);
})

Related

Error: Request failed with status code 404, React, Axios

I have built a form which I want to be able to send emails, to do this I have attempted to follow this youtube tutorial: https://www.youtube.com/watch?v=_3-By9QfFa0
However I am running into an issue where I am getting the error in the question title which is coming up in my console web browser when trying to submit the form. I realize the issue might have something to do with one of the routes somewhere but I just cant figure it out (unless it's something completely different).
schoolForm.js
const handleSubmit = async(e) => {
e.preventDefault();
try { //I also tried using only: "/send_mail" here like I have in server.js but it didnt work
await axios.post("http://localhost:3000/send_mail", {
name
});
}
catch (error) {
console.log(error);
}
}
server.js
const express = require("express");
const app = express();
require("dotenv").config();
const bodyParser = require("body-parser");
const cors = require("cors");
const nodemailer = require("nodemailer");
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(cors());
app.post("/send_mail", cors(), async (req, res) => {
let {text} = req.body;
const transport = nodemailer.createTransport({
host: "smtp-mail.outlook.com",
port: 587,
auth: {
user: "someone#hotmail.com",
pass: "password"
},
tls: {
rejectUnauthorized: false
}
});
await transport.sendMail({
from: "someone#hotmail.com",
to: "someone#hotmail.com",
subject: "subject",
html: `<p>${text}</p>`
})
});
app.listen(4000, () => {
console.log("Server is listening on port 4000");
});
Edit: The error I get in the browser:
Is there anyone that can help me solve this issue? Help would be greatly appreciated!
Your server is listening on port 4000. // server.js
app.listen(4000, () => {
console.log("Server is listening on port 4000");
});
You should use below URL for Axios call. // schoolForm.js
await axios.post("http://localhost:4000/send_mail", { // use port 4000 not 3000
name
});
You've set up your server to listen to port 4000 but your axios request is to port 3000.
Make sure you send the request to the correct port:
await axios.post("http://localhost:4000/send_mail", {
name
});
Also note the body-parser is deprecated and you should use express built-in middleware. so instead of:
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
you should have:
app.use(express.urlencoded({extended: true}));
app.use(express.json());
and you can remove body-parser dependency.
You can read here to learn more about express built-in middleware and their optional properties.
EDIT:
The reason it wasn't working is because body is an object created by the middleware itself. Therefore req.body is undefined since the body object doesn't exists

How to parse JSON assigned to a variable in POST request? [duplicate]

I am using nodejs + Express (v3) like this:
app.use(express.bodyParser());
app.route('/some/route', function(req, res) {
var text = req.body; // I expect text to be a string but it is a JSON
});
I checked the request headers and the content-type is missing. Even if "Content-Type" is "text/plain" it is parsing as a JSON it seems. Is there anyway to tell the middleware to always parse the body as a plain text string instead of json? Earlier versions of req used to have req.rawBody that would get around this issue but now it does not anymore. What is the easiest way to force parse body as plain text/string in Express?
By default bodyParser.text() handles only text/plain. Change the type options to include */json or */*.
app.use('/some/route', bodyParser.text({type: '*/*'}), function(req, res) {
var text = req.body; // I expect text to be a string but it is a JSON
});
//or more generally:
app.use(bodyParser.text({type:"*/*"}));
You can find the docs here
In express 4.x you can use the text parser from bodyParser
https://www.npmjs.org/package/body-parser
just add in app.js
app.use(bodyParser.text());
Also in the desired route
router.all('/',function(req,res){
console.log(req.body);
})
If you remove the use of the bodyParser() middleware, it should be text. You can view the bodyParser docs for more info: http://www.senchalabs.org/connect/middleware-bodyParser.html
Remove this line:
app.use(express.bodyParser());
EDIT:
Looks like you're right. You can create your own rawBody middleware in the meantime. However, you still need to disable the bodyParser(). Note: req.body will still be undefined.
Here is a demo:
app.js
var express = require('express')
, http = require('http')
, path = require('path')
, util = require('util');
var app = express();
function rawBody(req, res, next) {
req.setEncoding('utf8');
req.rawBody = '';
req.on('data', function(chunk) {
req.rawBody += chunk;
});
req.on('end', function(){
next();
});
}
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.use(rawBody);
//app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
});
app.post('/test', function(req, res) {
console.log(req.is('text/*'));
console.log(req.is('json'));
console.log('RB: ' + req.rawBody);
console.log('B: ' + JSON.stringify(req.body));
res.send('got it');
});
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
test.js
var request = require('request');
request({
method: 'POST',
uri: 'http://localhost:3000/test',
body: {'msg': 'secret'},
json: true
}, function (error, response, body) {
console.log('code: '+ response.statusCode);
console.log(body);
})
Hope this helps.
Express understands by content-type how to decode a body.
It must have specific decoders in middlewares, which is embedded into the library from 4.x:
app.use(express.text())
app.use(express.json())
Two important things to achieve this.
You need to add the text middleware in order to process text in the body
You need to set the content type by adding the right header "Content-type: text/plain" in the request
Here is the sample code for both.
const express = require('express');
const app = express();
const bodyParser = require('body-parser')
//This is the needed text parser middleware
app.use(bodyParser.text());
app.post('/api/health/', (req, res) => {
res.send(req.body);
});
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on ${port} ${new Date(Date.now())}`));
Save this as index.js.
Install dependencies.
npm i -S express
npm i -S body-parser
Run it.
node index.js
Now send a request to it.
curl -s -XPOST -H "Content-type: text/plain" -d 'Any text or json or whatever {"key":value}' 'localhost:3000/api/health'
You should be able to see it sending back whatever you posted.
You can use the plainTextParser (https://www.npmjs.com/package/plaintextparser) middleware..
let plainTextParser = require('plainTextParser');
app.use(plainTextParser());
or
app.post(YOUR_ROUTE, plainTextParser, function(req, res) {
let text = req.text;
//DO SOMETHING....
});
I did it:
router.route('/')
.post(function(req,res){
var chunk = '';
req.on('data', function(data){
chunk += data; // here you get your raw data.
})
req.on('end', function(){
console.log(chunk); //just show in console
})
res.send(null);
})
Make sure the version of express and bodyParser has been upgraded to the appropriate versions.
Express ˜4.x and bodyParser ˜1.18.x. That should do it. With that in place the following should work
app.use(bodyParser.text());

Express body-parser req.body with formdata is empty object

Somehow my req.body is always empty, maybe you have an idea:
here is my server code:
const Express = require('express');
const bodyParser = require('body-parser');
const app = new Express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.post('/save', (req, res) => {
console.log(req.body) // => {}
res.send(req.body);
});
const env = process.env.NODE_ENV || 'production';
app.listen(3000, err => {
if (err) { return console.error(err); }
console.info(`Server running on http://localhost:${port} [${env}]`);
});
When I try to send formdata with javascript the req.body is empty:
const data = new FormData(document.querySelector('form'));
console.log(data); // seems empty already??? FormData{}??
const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost:3000/save');
xhr.send(data);
Same with postman:
I don’t understand this…
Sending x-www-form-urlencoded with postman or raw (application/json) works in postman. But sending the same headers with Formdata in javascript will still result in an empty object…
To log every field in formData
let myForm = document.getElementById('myForm');
formData = new FormData(myForm);
for (let [key, value] of formData.entries()) {
console.log(key, value);
}
Fiddle - https://jsfiddle.net/thesumit67/j4znhxa5/1/
To handle it via express use multer.
Here is an example -
https://www.npmjs.com/package/multer
Make sure to add enctype="multipart/form-data" on form element. Otherwise Multer will ignore it.
let multer = require('multer');
let upload = multer();
app.post('/save', upload.fields([]), (req, res) => {
console.log( req.body );
console.log( req.files );
res.sendStatus(200);
});
body-parser is deprecated and isn't a part of Express anymore.
Also, body-parser does not provide the functionality to parse form-data post data.
From the body-parser repository description:
This does not handle multipart bodies, due to their complex and typically large nature. For multipart bodies, you may be interested in the following modules:
busboy and
connect-busboy
multiparty and
connect-multiparty
formidable
multer
From what I understand, the problem may be in the HTML form.
<form action="" method="POST">
<input type="text" name="foo[bar]">
<button>Submit</button>
</form>
Then in the server code it may look something like this.
app.post('/save', (req, res) => {
console.log(req.body.foo) // => {}
res.send(req.body.foo);
});
Again, this post is older so you've probably already fixed it.
I had this same problem, I was using the fetch api, sending form data to an node.js/express backend. The problem was that I had set enctype='multipart/form-data' on the form and I was also setting Content-type: multipart/form-data in the fetch Headers.
Removing the Content-type from the Headers got everything to work.
I got the solution from here => https://github.com/expressjs/multer/issues/411
Express and body parser Version :
"dependencies": {
"body-parser": "^1.19.0",
"express": "^4.17.1"
}
app.js:
const express = require('express');
var bodyParser = require('body-parser')
const app = express();
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
app.use( bodyParser.json());
const baseUrl = '/api/v1/tours';
app.post(baseUrl, (req, res)=>{
console.log(req.body);
res.send('Done');
})
//starting server
const port = 3000;
app.listen(port, ()=>{
console.log(`app running on port ${port}...`);
});
To send raw data please select JSON from the list

req.body isn't appearing as one of key-value pairs, but req.headers and others do

Sample 'Advanced REST Client' Request
I'm using Postman and Advanced REST client to create a basic POST request for the following code -
'use strict';
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var http = require('http');
// configure the app to use bodyParser()
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
//app.listen(6666);
http.createServer(function (req, res) {
h2s(req, res);
}).listen(6666, '127.0.0.1');
console.log('Server running at http://127.0.0.1:6666/');
module.exports = function h2s(req, res) {
console.log("inside h2s");
app.use(function (req, res) {
console.log("req.body : " + req.body);
res.send("OK");
});
}
But, when I debug, I find that req.body is missing in the "req object tree". What's more strange is all the changes that I make to req.headers are available in the req object tree.
Looks like I seem to be making a trivial mistake, but I'm unable to figure it out. Been trouble-shooting for an hour or so but no luck!
Can anyone of you figure out why req.body seems to be missing from the req object tree?
Will be of great help to me. Thanks!
It looks like you have several issues in your code:
instead of
http.createServer(function (req, res) {
h2s(req, res);
}).listen(6666, '127.0.0.1');
console.log('Server running at http://127.0.0.1:6666/');
module.exports = function h2s(req, res) {
console.log("inside h2s");
app.use(function (req, res) {
console.log("req.body : " + req.body);
res.send("OK");
});
}
For creating the server, try
http.createServer(app).listen(8000, '127.0.0.1'); //using http
Or (using express directly)
app.listen(8000,function(){
console.log('Server running at http://127.0.0.1:8000/');
});
Then register an handler function for your requests, there you can access req.body
app.use(function (req, res) {
console.log("req.body : " + req.body);
res.send("OK");
});
Dear u set body parser Url Encoding to true
// configure the app to use bodyParser()
app.use(bodyParser.urlencoded({
extended: true
}));
and check by printing the req.body, it work for me and might for u also
the req.body can be accessed also when
content-type:"application/x-www-form-urlencoded"
read this
In your case , your content-type is application/json"
so try changing the content-type to "application/x-www-form-urlencoded"
also url encode the parameters while sending to the server from JS
also solution can be
// fire request
request({
url: url,
method: "POST",
json: true,
headers: {
"content-type": "application/json",
},
body: JSON.stringify(requestData)
}, ...

Node - Post request showing undefined

Im making a angular2/Node.js application. Right now when i try to get a object from the node server, it returns just fine. However, when i try to post data to the node server. The request.body shows undefined. What am i doing wrong ?
server.js
// Test
router.get('/test', function (req, res) {
res.json({test:true}); // Works
});
// Post
router.post('/rest', function (req, res) {
var body = req.body;
console.log(body); // Undefined
res.json({test:true});
});
app.ts
constructor(private http:Http){
console.log("Test")
http.get('/api/User/test').subscribe(result => {
console.log(result.json());
});
let headers = new Headers({ 'Content-Type': 'application/json' });
this.http.post('/api/User/rest',{test:'Testing req'},{headers:headers})
.subscribe(result => {
console.log(result.json());
});
}
Did you install body-parser?
npm install body-parser --save
and before your routes, add it to your express application
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
see also: https://github.com/expressjs/body-parser

Categories

Resources