BodyParser causes all API requests to hang. Even basic GET requests - express

As the title says, I simply don't understand what is going on here. Once I include the app.use(bodyParser.json) line, Postman just keeps handing on any request I make. I lost a good portion of the day thinking I messed up my routes.
I narrowed it down to it in this little testing file:
const express = require("express")
const bodyParser = require("body-parser")
const env = require("dotenv");
const app = express()
env.config();
app.use(bodyParser.json);
app.get("/", (req, res) => {
res.status(200).json({
message:"Hello World"
})
});
app.post("/data", (req, res) => {
req.status(200).json({
message: req.body
})
});
app.listen(process.env.PORT, ()=>{
console.log(`Server listening at port ${process.env.PORT}`);
})
Can anyone tell me what is happening and how I can fix it?

You need to call JSON body parser as a function (with brackets):
app.use(bodyParser.json());
There is another bug in the post method "data", You should call status from "res" object:
app.post("/data", (req, res) => {
res.status(200).json({
message: req.body
})
});

Related

Why is the XMLHttpRequest request body returning null?

I am trying to send a 'POST' XMLHttpRequest to my server, which uses express.
The server is able to recieve the request, but the request's body is null.
On the server I am receiving it with :
app.post('/', function(req, res){
res.send(req.statusCode);
console.log(req.body);
})
I don't think that there is a problem with it as many sources say that this is a good way to receive the request.
This is my client side code :
const user = {
'Key' : 'user',
'Name' : 'user',
'Email' : 'user#example.com',
'Password' : 'password'
}
const jsonFileRequest = new XMLHttpRequest();
jsonFileRequest.open('POST', '/', true);
jsonFileRequest.setRequestHeader('Content-Type', 'application/json');
jsonFileRequest.onreadystatechange = function(){
console.log(`userStatus : ${jsonFileRequest.readyState},\nstatus: ${jsonFileRequest.status}`);
if(jsonFileRequest.readyState == 4 && jsonFileRequest.status == 200)
{
console.log(`userStatus : βœ…,\nstatus : βœ…`);
}
}
jsonFileRequest.send(JSON.stringify(user));
**This is my server side code : **
const express = require('express');
const app = express();
const port = 8080;
app.get('/', (req, res) => {
res.sendFile(__dirname + '/frontend/index.html');
app.get('/index.html.js', (req, res) => {
res.sendFile(__dirname + '/frontend/index.html.js');
})
app.get('/data.json', (req, res) => {
res.sendFile(__dirname + '/data.json');
})
})
app.post('/', function(req, res){
res.send(req.statusCode);
console.log(req.body);
})
app.listen(port);
console.log(`listening on http://localhost:${port}`);
Could you please help me? Thank you!
You should try using the express.json() middleware. When disabled (by default), req.body returns undefined.
You can check out the express documentation for more info:
req.body
Contains key-value pairs of data submitted in the request
body. By default, it is undefined, and is populated when you use
body-parsing middleware such as express.json() or
express.urlencoded().
See: https://expressjs.com/en/api.html
Using the following code snippet for your express server should work:
// Importing the express module
var express = require('express');
// Initializing the express and port number
var app = express();
var PORT = 3000;
// Calling the express.json() method for parsing
app.use(express.json());
// Reading content-type
app.post('/', function (req, res) {
console.log(req.body.name)
res.end();
})
// Listening to the port
app.listen(PORT, function(err){
if (err) console.log(err);
console.log("Server listening on PORT", PORT);
});
You will need a parser for the data/body you are sending. By default express does not parse the body part of the request.
You can add these two line in your express server to fix this.
app.use(express.json())
app.use(express.urlencoded({ extended: true}));

router.route() doesnt want to work at all

I am trying to run router.route() with the following code
const express = require('express');
const app = express();
const router = express.Router();
router.route('/test').get(function (req, res, next) {
res.send('You have reached localhost:9000/test');
next();
});
app.listen(9000, () => {
console.log('Running on port 9000');
});
But it doesn't seem like anything is happening at all. Regardless of what I do, localhost:9000/test will not return anything Cannot GET /test. I don't understand what I'm doing wrong. Thanks in advance
You have to hook the router into your app with app.use():
const express = require('express');
const app = express();
const router = express.Router();
router.get('/test', function (req, res, next) {
res.send('You have reached localhost:9000/test');
});
app.use(router); // <=== add this
app.listen(9000, () => {
console.log('Running on port 9000');
});
Your original code creates a router object, but that router object is not hooked up to any web server yet. Using app.use(), you can hook it up to your web server so that it actually gets a chance to see the incoming requests.
Also, do not call next() after you call res.send(). Pick one of the other. Once you send a response, you do not want to continue routing to other routes because that will often try to then send another response, but you can only send one response to a given incoming http request.
You can simply use the Router().get(...) function instead.
The <Router>.get('/path', function() {...}); function will listen for incoming traffic to the path /path and then fire the callback function with the parameters request, response and next.
Example:
router.get('/test', function (req, res) {
res.send('You have reached localhost:9000/test');
});
Full example:
const express = require('express');
const app = express();
const router = express.Router();
router.get('/test', function (req, res) {
res.send('You have reached localhost:9000/test');
});
app.listen(9000, () => {
console.log('Running on port 9000');
});
Note: Using the next() function after sending a response to an incoming HTTP request will result in an error.

AXIOS GET request to instagram not working in prod

I am stuck for a few hours and I can't find an answer.
It's a very simple request that works fine in the browser (it returns a JSON answer), for example :
https://www.instagram.com/eurosportfr/channel/?__a=1
In dev the code:
const express = require('express');
const axios = require('axios');
const cors = require('cors');
const app = express();
app.use(cors());
app.get('/instagram', (req, res) => {
async function getInstagramFeed() {
await axios
.get('https://www.instagram.com/eurosportfr/?__a=1')
.then((response) => {
console.log(response);
res.write(`${JSON.stringify(response.data)}`);
res.end();
})
.catch((err) => {
console.log(err.response);
res.write('<h1>ERROR GRAVE</h1>');
res.write(err.response);
res.end();
});
}
getInstagramFeed();
});
const PORT = process.env.PORT || 8000;
app.listen(PORT, () => console.log(`listening on ${PORT}`));
The result in DEV ENV is JSON data with all what I need.
But in production, it doesn't return me the JSON. Instead it returns me an HTML page...
You can try it here: (I display in the body the result)
https://corsmiddleware.vercel.app/instagram
When I try another api request with another API client, it works just fine in prod, example :
https://corsmiddleware.vercel.app/test
Any idea ??
Thanks
This request now requires authentification. It was working in the past, and it's still actually working here in Morocco where I am, but this solution is not reliable.
The solution is to follow the instructions on facebook :
https://developers.facebook.com/docs/instagram-basic-display-api/

keep getting a 404 on routing with params

Im doing a mern tutorial on freecodecamp and I have run into an issue that is driving me nuts.
I have a route which is localhost:5000/exercises/1234
however I keep getting a 404 on that route.
If someone could point out the error if would be appreciated.
I have a server file:
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
const exerciseRouter = require("./routes/exercises");
const usersRouter = require("./routes/users");
require("dotenv").config();
const app = express();
const port = process.env.PORT || 5000;
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true,
});
const connection = mongoose.connection;
connection.once("open", () => {
console.log("Mongo DB database connection established successfully πŸ‘ΎπŸ‘ΎπŸ‘Ύ");
});
app.use(cors());
app.use(express.json());
app.use("/exercises", exerciseRouter);
app.use("/users", usersRouter);
app.listen(port, () => {
console.log(`server is running on port ${port} 😻`);
});
and the route is defined here in an exercise.js file:
const router = require("express").Router();
const Exercise = require("../models/exercise.model");
router.route("/:id").get((req, res) => {
console.log(req.params);
Exercise.findById(req.params.id)
.then((exercise) => res.json(exercise))
.catch((err) => res.status(400).json(`Error ${req.params}`));
});
When i run this in the browser I get a 404 and not even the console log is run. Im really not sure why it isnt working.
Ah disregard this issue, i did an idiotic mistake. I had the method get inside another method (which isnt apparent in the above question).
Note to myself and others make sure your route aren't nested by accident in another route! lol

How do I get the POST data from a nuxtjs server middleware?

How do I get the POST data from a nuxtjs server middleware? So far I've managed to do it for GET, but for POST the body is just not there. req.body is undefined.
Add this to nuxt.config.js:
serverMiddleware: [
'~/api/v1/index.js'
],
and then create a file /api/v1/index.js with:
const bodyParser = require('body-parser')
const app = require('express')()
module.exports = { path: '/api', handler: app }
app.use(bodyParser.json());
app.post('/newsletter/subscribe', (req, res) => {
res.json(req.body)
})
Key line is app.use(bodyParser.json())
Even if you are not using express, the code is still very similar.
You do not need to use express because nuxt server already running connect instance for this. Just do this for receiving the POST request:
yourservermiddleware.js -
export default {
path: '/yourservermiddlware',
async handler(req, res, next) {
req.on('data', async (data) => {
let payload = JSON.parse(data.toString())
console.log("received request", payload)
res.end(JSON.stringify('send back what you want'))
next()
})
}
}
P.S. and do not forget to register servermiddleware at the nuxt.config.js