Express receiving empty req.body - node.js

When I call a fetch post request:
fetch('http://localhost:3001/insertUser', {
method: 'POST',
mode: "no-cors",
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify({ a: 1 })
}).then(res => {
console.log(res)
}).then(err => {
console.log(err)
})
and receive it on the server with:
const path = require("path")
const express = require("express")
const bodyParser = require('body-parser');
const app = express()
require('dotenv').config();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.post("/insertUser", (req, res) => {
console.log(req.body)
})
app.listen(process.env.PORT || 3001, () => {
console.log("Listening on port 3000");
});
I get an empty object, even though I am trying to send
{
a:1
}
I have
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
included in my server file and also tried changing the fetch mode to be cors instead of no-cors
package.json:
{
"name": "progression-tracker-server",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"env": "0.0.2",
"express": "^4.17.1",
"mongodb": "^3.6.3",
"mongoose": "^5.11.8"
}
}

The problem is caused by the no-cors option. If you remove that, then it works for me when I reproduce the code you show.
The reason for that is that no-cors only allows a limited set of headers and does not allow a content-type of application/json like you are trying to use. So, presumably that content-type is stripped by the browser and thus your bodyparser middleware does not match and doesn't do its job so the body of the post is never read and req.body ends up empty.
So, to make that type of request, you need to remove the no-cors option and if it is a cross origin request, then you need to enable that specific type of CORs request in your server or change your struture so that request isn't cross
origin.

Related

Failing to see anything on localhost using typescript for Node.js

Here is my code below:
Note: I am still learning typescript and the rest of the stuff so let me know for other stuff that I should do better!
Folder structure:
server.ts
import http, { createServer, IncomingMessage, ServerResponse }
from "http";
import * as app from "./app";
import * as dotenv from "dotenv";
dotenv.config();
const server = createServer(app);
server.listen(process.env.PORT);
app.ts
import express, { Application } from "express";
const app: Application = express();
const mealsRoutes = require("./routes/meals");
app.use("/meals", mealsRoutes);
module.exports = app;
meals.ts
import express, { Request, Response} from "express";
const router= express.Router();
//GET ROUTE for /meals/
router.get("/", (req: Request, res: Response, next) => {
res.status(200).json({
message:"Handling GET request to /meals"
});
});
//POST ROUTE for /meals/
router.post("/", (req: Request, res: Response, next) => {
res.status(200).json({
message:"Handling POST request to /meals"
});
});
module.exports = router;
package.json
{
"name": "restful-api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node dist/server.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"#types/express": "^4.17.13",
"#types/node": "^16.7.1",
"ts-node": "^10.2.1",
"typescript": "^4.3.5"
},
"dependencies": {
"dotenv": "^10.0.0",
"express": "^4.17.1"
}
}
package-lock.json: https://codeshare.io/Pd4ExY (had to share with this)
So when I run it with "node dist/server.js" and test it on the browser nothing happens, no errors, it just keeps loading. I have no clue what am I doing wrong, any help?
Make sure that the port actually is loaded correctly. If process.env.PORT ends up being undefined you get a random port. You can either add a debugger or e.g. print the port when the server has started:
const server = http.createServer(app);
server.addListener('listening', () => console.log(server.address().port));
server.listen(process.env.PORT);
The rest of the code looks fine if you are accessing the path /meals.

bodyParser response 'undefined' in node app post method console.log

I am attempting to use middleware to catch the body of a post request, and dynamically use the message ID of the telnyx API endpoint to populate other fields, etc.
Followed the documentation here to a point, several times and cannot get the terminal to output anything but undefined when I send a message to my telnyx number: https://developers.telnyx.com/docs/v2/messaging/quickstarts/receiving-sms-and-mms
I have tried cors thinking that could be the issue from what I read in other posts, and know that express and bodyParser are no longer bundled so I used all both of those as well in an attempt to capture the data. Forgive me if it is obvious.
require('dotenv').config();
const axios = require('axios').default;
const cors = require('cors');
const telnyx = require("telnyx")("MYAPIKEY")
const express = require('express');
const app = express();
app.use(express.urlencoded( {extended: true} ));
app.use(express.json());
app.post('/webhook', (req, res) => {
console.log(`New message from ${req.body.from}: ${req.body.body}`);
});
const port = 8080;
app.listen(port, () => console.log(`App running on port ${port}`));
Here are the dependencies:
{
"name": "telnyxjs",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.21.1",
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"telnyx": "^1.13.1"
}
}
terminal output
ngrok capture of post data

CORS error in nodejs app deployed on heroku using with angular 9

Server.js Code:
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors')
const db = require('./DB/db');
const routes = require('./api/routes/routes');
const app = express();
const PORT = process.env.PORT || 3000;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(cors({
origin: '*'
}));
routes(app);
app.listen(PORT, () => {
console.log(`Server started at ${PORT}`);
});
package.json file:
{
"name": "LMS_Backend",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"joi": "^14.3.1",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.9.11",
"nodemailer": "^6.4.6"
}
}
Angular service file:
import { Injectable } from '#angular/core';
import { HttpClient, HttpParams, HttpHeaders } from '#angular/common/http';
const baseUrl = 'https://lmspreject-1.herokuapp.com/api/lms_project';
// const baseUrl = 'http://localhost:3000/api/lms_project';
#Injectable({
providedIn: 'root',
})
export class AdminServiceService {
constructor(private http: HttpClient) {}
register(adminDetails) {
console.log(adminDetails);
let headers = new HttpHeaders({
'Content-Type': 'application/json',
'Accept': 'application/json'
});
let options = {
headers: headers,
};
return this.http.post(`${baseUrl}/admin/register`, adminDetails, options);
}
}
Error:
Access to XMLHttpRequest at 'https://lmspreject-1.herokuapp.com/api/lms_project/admin/register' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Note: It works fine I run the app on the localhost but gives error on Heroku URL.
Regarding CORS, localhost behaves quite differently than remote origins, this can be very confusing.
I suspect that you didn't enable the CORS pre-flight OPTIONS endpoint. Your request is using a JOSN content type and therefore is not a "simple" cors request. It will be automatically preceded by an OPTION preflight request from the browser. Your server should be able to respond to that request.
See here how to enable it - https://www.npmjs.com/package/cors#enabling-cors-pre-flight
Do:
npm i --save cors
Add app.use(cors()) in server.js file.
Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell browsers to give a web application running at one origin, access to selected resources from a different origin.
You can do a CORS request from a HTTPS domain to another HTTPS domain. If you do http requests to call your https server, it is considered insecure an considered as force request to your server with tampered data.
Here,as I can see you are trying to access https server from your local http that's why you are getting an CORS issue.

React Project - Request to ExpressJS Server returns 400 - Bad Request

Parameters are set and once button is pressed, a request [Node request package] or fetch request is made to be received by expressjs request. While link address is created, response returned is 400 Bad Request.
I've tried both a fetch request and a node package 'request' and
Server JS
const express = require ('express');
const path = require('path') //core node module
const app = express();
const cors = require('cors');
const router = express.Router();
// app.use(cors())
const publicdirpath = path.join(__dirname, '../public')
console.log(path.join(__dirname, '../public'))
app.use(cors());
app.use(express.static(publicdirpath))
app.post('/testcall', (req, res) => {
if(!req.query.startdate && !req.body.enddate &&
!req.body.projectnumber){
return res.status(400).send({
success: 'false',
message: 'dates or project or both required'
});
}
//call stored procedures
});
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
JS Class that calls express JS
handleDropdownClick = (event, selection) =>{
const { name, innerText, value } = event.target;
console.log( event.target + " : " + innerText + " : " +
this.props.formData);
const request = require('request');
switch(selection){
case 1:
//call api or stored procedure
if(this.validation()){
//call api
request.get({url:"http://localhost:3000/testcall", qs:this.state.formData} , function (err, res, body) {
if(err){
console.error('error with request: error: ' + err + '. res: ' + res + ' + body: ' + body);
}
console.log("Get response: " + res.statusCode + ". Body: " + body);
})
//Using Fetch
const jsonData = JSON.stringify(this.state.formData);
fetch('/testcall', {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'credentials': 'include'
},
body: jsonData
})
.then( response => {
return response.json();
})
.then( response => {
console.log(response);
})
.catch(function (e) {
console.log("fail: " + e);
})
}
break;
//more code
Package.json
{
"name": "app-name",
"version": "0.1.0",
"private": true,
"main": "index.js",
"dependencies": {
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"nodemon": "^1.19.1",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-scripts": "3.0.1",
"request": "^2.88.0",
"save": "^2.4.0",
"semantic-ui-react": "^0.87.2",
"table": "^5.4.1",
"tedious": "^6.2.0",
"webpack": "^4.29.6"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"dev": "run-p server start"
},
"eslintConfig": {
"extends": "react-app"
},`enter code here
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"proxy":"http://localhost:3000"
}
Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
serviceWorker.unregister();
File Path
public
src
-api
-components
-storedprocedures
-tabs
-app.js
-config.js
-index.js
-server.js
package-lock.json
package.json
Expected results would be for the expressjs to accept the call and complete logic.
Actual results are:
POST http://localhost:3000/calculatecommission 400 (Bad Request)
- for the npm package request
request.js:149 GET http://localhost:3000/calculatecommission?projectnumber=&startdate=2019-06-02&enddate=2019-06-28 400 (Bad Request)
- for fetch request
You can use axios or use proxy at front-end
I would recommend using Axios as well, it's a whole lot easier to use then fetch. You can find out more here
https://alligator.io/react/axios-react/
Got the same result with axios unfortunately. I'm wondering if the issue is that the express is server file is set up wrong. Maybe it's not getting the request at all.
request.js:149 GET http://localhost:3000/calculatecommission?projectnumber=&startdate=2019-06-02&enddate=2019-06-28 400 (Bad Request) - for fetch request
Any time you get an error like this, don't forget, you are literally allowed to run this command yourself in the command-line interface. That will give you the exact error that the install script is actually running into, i.e.:
GET https://www.google.com/
In my case, the error was: HTTPS not supported without installing LWP::Protocol::https.
So:
I resolved all of the issues from the GET command.
Since the network it was trying to access was private, I used sudo npm install --s.

node server.js return nothing

I'm very new to Node. I just installed it via Brew and when I ran node server.js in the Terminal, the Terminal does nothing for hours.
node -v
v6.6.0
This is the server file, it is from a tutorial video that I'm watching. The point of this simple express server is to allow me the ability to quickly serve test data via HTTP to the front-end.
package.json :
{
"name": "simple-server",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.14.1",
"express": "^4.13.3",
"path": "^0.12.7"
}
}
server.js file :
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var app = express();
//Allow all requests from all domains & localhost
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods", "POST, GET");
next();
});
app.use(express.static(path.join(__dirname + '/public')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
var persons = [
"person1.jpg",
"person2.jpg",
"person3.jpg",
"person4.jpg",
"person5.jpg",
"person6.png"
];
app.get('/persons', function(req, res) {
console.log("GET From SERVER");
res.send(persons);
});
app.listen(6069);
Thanks in advance
Try adding a console.log("started!") before app.listen. I'm guessing the server starts, but as is seen in your code, the only log it does is when it receives a request.
Try accessing http://localhost:6069/persons in your browser.
Edit: this defines a server response
app.get('/persons', function(req, res) {
console.log("GET From SERVER");
res.send(persons); <-- server sends persons array to client
});

Resources