Post req.body is always empty object - node.js

I'm using Typescript Fetch wrapper to do post and get requests and getting empty object on post(get works fine) (Before I used Vanilla Js and all worked fine)
Nodejs:
const express = require('express');
const fs = require('fs');
const app = express();
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
);
next();
});
app.use(express.json());
app.post('/login', (req, res) => {
let isLogged = login(req.body);
console.log(req.body);
res.status(200).json(isLogged);
});
My Typescript fetch Wrapper:
async function fetchWrapper<T>(path: string, config: RequestInit): Promise<T> {
const request = new Request(path, config);
const response = await fetch(request);
if (!response.ok) {
throw new Error(
`name: ${response.status}, message: ${response.statusText}`
);
}
// return empty object
return response.json().catch(() => ({}));
}
export async function post<T, U>(
path: string,
body: T,
config?: RequestInit
): Promise<U> {
const init = { method: 'post', body: JSON.stringify(body), ...config };
return await fetchWrapper<U>(path, init);
}
my post request:
const res = await fetch.post(`${url}/login`, {
body: inputData,
headers: { 'Content-Type': 'application/json' },
});
input data is not empty

The problem here that you are using wrong Content-Type header value. express.json parses application/json content type, while you are sending application/x-www-form-urlencoded. The solution is either to change the content-type you are sending, or add another middleware like bodyparser to parse application/x-www-form-urlencoded body.

Related

Angular post request to NodeJS JSON error

So i am sending a POST request to a nodeJS app, my request in Angular looks like this:
export class SearchComponent {
constructor(private http: HttpClient) {}
newWord = '';
keyword = '';
onClick() {
const headers = new HttpHeaders()
.set('Authorization', 'my-auth-token')
.set('Content-Type', 'application/json');
this.http
.post('http://localhost:3000/search', JSON.stringify(this.keyword), {
responseType: 'text',
headers: headers,
})
.subscribe((data) => {
this.newWord = data;
});
}
}
When i try to console.log the request i get an Unexpected token " in JSON at position 0 error even though i tried all the solutions i could find on stackoverflow this is how my NodeJS app is set and the error:
const bodyParser = require("body-parser");
const express = require("express");
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.all("/*", function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS");
res.header(
"Access-Control-Allow-Headers",
"Content-Type, Authorization, Content-Length, X-Requested-With"
);
next();
});
app.listen(3000, () => {
console.log("Server is running on port 3000");
});
app.post("/search", (req, res) => {
res.send(req.body);
});
The error i get is this:
SyntaxError: Unexpected token " in JSON at position 0
at JSON.parse (<anonymous>)....
Note that the this.keyword gets its value from a input field if i dont use JSON.stringify no error is happening but the req variable is "undefined".
Assuming you are asking how to get back the data. I'm not sure if this will work, but you can give it a try:
Under comments, see that you mean this.keyword. Here is the change I would make
going by axis format, this may be incorrect
.post('http://localhost:3000/search', JSON.stringify(this.keyword), {
responseType: 'text',
headers: headers,
})
instead, try:
.post('http://localhost:3000/search', {
keyword: this.keyword, // changed this
responseType: 'text',
headers: headers,
})
also in your server, you can change to this:
const app = express();
app.use(express.json())
app.use(express.text())
app.use(express.urlencoded({ extended: true }))
(body parser included in express now)
new to the mern stack (have never used Angular) so kind of iffy but hopefully that can help

Message received from background. Values reset

I'm sending post request from "angular->port 4200" to "expressjs server->port 8000".
As an example i'm folowing this example: https://github.com/kuncevic/angular-httpclient-examples/blob/master/client/src/app/app.component.ts
I'm getting two error :
1)undefined from Nodejs(data and req.body.text)
2)Message received from background. Values reset
Angular side:
callServer() {
const culture = this.getLangCookie().split("-")[0];
const headers = new HttpHeaders()
headers.set('Authorization', 'my-auth-token')
headers.set('Content-Type', 'application/json');
this.http.post<string>(`http://127.0.0.1:8000/appculture`, culture, {
headers: headers
})
.subscribe(data => {
});
}
expressjs side:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
var path = require('path');
app.all("/*", function(req, res, next){
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
next();
});
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
app.post('/appculture', function (req, res) {
var currentCulture = `${req.body.text} from Nodejs`;
req.body.text = `${req.body.text} from Nodejs`;
res.send(req.body)
})
app.listen(8000, () => {
console.log('server started');
})
Either you are not sending anything of there is no value in body.text
Try to console.log(req.body) instead of req.body.text.
Try to console.log(culture) and this.getLangCookie() on the client side to see if you are actually sending something.
You can also make use of the network tab in the browser to inspect the request that you are sending.
Angular side:
callServer() {
const culture = this.getLangCookie().split("-")[0];
const headers = new HttpHeaders()
headers.set('Authorization', 'my-auth-token')
headers.set('Content-Type', 'application/json');
this.http.get(`http://127.0.0.1:8000/appculture?c=` + culture, {
headers: headers
})
.subscribe(data => {
});
}
Nodejs side:
app.get('/appculture', function (req, res) {
currentCulture = req.query.c;
res.send(req.body)
})

Firebase Functions - cannot read req.body

I'm having a problem with my Firebase Functions https request.
This is my code to trigger it:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
app.use(function(req, res, next) {
res.setHeader('Content-Type', 'application/json');
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods", "GET, POST");
next();
});
app.use((err, req, res, next) => {
if (err instanceof SyntaxError) {
return res.status(400).send();
};
next();
});
app.post('/fetchPosts', (req, res) => {
exports.fetchPosts(req, res);
});
exports.widgets = functions.https.onRequest(app);
const cors = require('cors')({ origin: true })
exports.fetchPosts = (req, res) => {
console.log(req.body)
console.log(res)
let topics = req.body.topics || ['live'];
let start = req.body.start || 0;
let num = req.body.num || 10;
let next = start+num;
// setting up the response.
});
That looks good as far as I can tell..
Now when I do my api call I do:
var headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
headers.append('Content-Type', 'application/json; charset=UTF-8');
const request = new RequestOptions({ headers: headers });
const url = 'https://my-link.cloudfunctions.net/widgets/fetchPosts';
let payload = {
topics: ["live", "pets"]
}
console.log(JSON.stringify(payload))
this.http.post(url, JSON.stringify(payload), request)
.pipe(map((res:Response) => {
console.log(res.json())
}))
.subscribe(
data => console.log(data),
err => console.log(err),
() => console.log('Got feed')
);
and it just returns topics with just ['live'].. because of the failsafe that I set up on the backend.. but why isn't getting my topics that I'm sending?
Also, when I console.log(req.body) on the backend it just shows {}.. an empty object..
Any ideas why the req.body doesn't seem to work? I do it with start and num as well, but they all revert back to the failsafe.
You must use POST method to handle req.body . In your case, you can handle your variable with req.query
To handle req.body . You can use Postman, then select POST method and post data as JSON . You can read more to use Postman well.

Express isn't sending JSON, but it's sending other strings fine

Here's the code:
res.status(400).send('{"test":1}');
This returns an empty response. This returns "test":
res.status(400).send('test');
Here's the only extension I'm using:
app.use(bodyParser.json({ limit: '50mb', type: 'application/*' }));
How do I make Express send JSON? I'm using Express 4.16.3 (latest version).
Edit, here's the whole file. I'm using Express as a proxy:
const express = require('express');
const path = require('path');
const qs = require('qs');
const bodyParser = require('body-parser');
const fetch = require('node-fetch');
const API_URL = 'https://api.example.com/';
const app = express();
app.set('json spaces', 2);
Error.stackTraceLimit = 100;
app.use(bodyParser.json({ limit: '50mb', type: 'application/*' }));
app.options(/\/api\/(.+)/, async (req, res) => {
res.writeHead(200, {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, GET, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Credentials': false,
'Access-Control-Max-Age': '86400',
'Access-Control-Allow-Headers': 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept',
});
res.end();
});
app.all(/\/api\/(.+)/, async (req, res) => {
let url = API_URL + req.params[0];
if (Object.keys(req.query).length) {
url += `?${qs.stringify(req.query)}`;
}
const opts = {
method: req.method,
headers: {
'content-type': req.headers['content-type'] || 'application/json',
},
};
if (req.headers.authorization) {
opts.headers.authorization = req.headers.authorization;
}
if (req.method.toUpperCase() !== 'GET') {
opts.body = JSON.stringify(req.body);
}
res.setHeader('content-type', 'application/json');
try {
const result = await fetch(url, opts);
const data = await result.text();
res.status(result.status).send({"test":1});
} catch (err) {
res.status(500).send(err.message || err);
}
});
app.listen(9002, () => console.log('Server started.'));
It was a CORS issue. It worked after adding:
res.header('access-control-allow-origin', '*');
res.header('access-control-allow-headers', 'origin, x-requested-with, content-type, accept');
I don't know why it worked with a non-JSON string, but it was blocked if the response was JSON.
To let express pass json object you can try to use this:
app.use(express.json());

Angular2 http.post not working

Service:
postJson() {
var json = JSON.stringify({
"key": "CT",
"values": ["FSP", "HMC", "PHYP","hell"]
});
let headers = new Headers({'Content-Type':'application/json'});
//let options = new RequestOptions({headers: headers});
//headers.append('Access-Control-Allow-Origin', '*');
return this._http.post('http://localhost:8080/add',json,headers)
.map(res => res.json());
}
Component:
postData;
onTestPost() {
this._httpService.postJson()
.subscribe(
data=> this.postData = JSON.stringify(data),
error=> alert(error),
() => console.log("finished")
)
}
Node.js Script
var express = require('express');
var path = require('path');
var app = express();
var fs = require("fs");
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use("/node_modules", express.static('node_modules'));
console.log( __dirname);
app.post('/add', (req, res) => {
console.log('Received request'+JSON.stringify(req.body));
fs.writeFile(__dirname + '/CTRoot/data.json', JSON.stringify(req.body), (err) => {
//if (err) throw err;
console.log('File written to JSON.json');
res.setHeader('Access-Control-Allow-Origin', '*')
//Add as many Headers as you want to line below
//If you use "Authentication" Header, insert it like 'Content-type, Authentication'
res.setHeader('Access-Control-Allow-Headers', 'Content-type')
res.setHeader("Content-type", "application/json");
res.setHeader('Access-Control-Allow-Methods',
'GET,PUT,POST,DELETE,OPTIONS')
res.send('File written to JSON.json')
})
});
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
I have tried adding many headers, but it's not working.
following output is coming
File written to JSON.json
req.body is coming empty, but in web network request header and body is as expected
Why are you using JSON.stringify to create the request body? that makes the request body type text instead of application/json.
So try:
postJson() {
let json = {
"key": "CT",
"values": ["FSP", "HMC", "PHYP","hell"]
};
let headers = new Headers({'Content-Type':'application/json'});
return this._http.post('http://localhost:8080/add',json,headers)
.map(res => res.json());
}
I ran a quick test trying to send request body as text, where my api expects application/json, I get this error back:
{"code":500,"message":"Content type 'text/plain;charset=UTF-8' not supported"}

Resources