Node.js read request body from Fetch API - javascript

I have the following method on my frontend:
price.addEventListener("click", function() {
fetch("http://localhost:3000/payment", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
amount: {
currency: "EUR",
amount: "10.00"
},
description: "Description of the item to buy"
})
})
});
and the following is my Node.js server code:
const express = require('express');
const app = express();
app.listen(3000);
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Credentials", "true");
res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
res.header("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
next();
});
app.post("/payment", function (req, res) {
// console.log(req.body);
// console.log(req.method);
// console.log(req.headers);
client.payments.create({
amount: {
value: req.body.amount.amount,
currency: req.body.amount.currency
},
description: req.body.description,
})
.then(payment => {
// Forward the customer to the payment.getCheckoutUrl()
res.redirect(payment.getCheckoutUrl());
})
.catch(error => {
// Handle the error
console.log(error);
});
});
I do not get why my req.body returns undefined and I cannot access those values. When I click to buy an item from UI, in the console I get POST 500 (Internal Server Error) and it may be intuitive that this does not work and this might explain this. But I can see that req.method and req.headers have values and it seems they are working properly. What am I doing wrong?

Related

How to add a jwt in the headers (Authorization : Bearer <token>)?

I am new to node.js. I need to use Json Web Tokens to authenticate my login requests.
In Postman and in the devtools, POST requests are working well : a new jwt is created for each request (seePOSTMAN, see DEVTOOLS
But, my authorization headers does not contain any jwt...
I got something like "Authorization : Bearer " (see AUTHORIZATION).
Here is my code :
**user.js/controllers
**
exports.login = (req, res, next) => {
User.findOne({ email: req.body.email })
.then(user => {
if(!user) {
return res.status(401).json({ message: 'Utilisateur non trouvé !'});
}
bcrypt.compare(req.body.password, user.password)
.then(valid => {
if(!valid) {
return res.status(401).json({ message: 'Mot de passe incorrect !'});
}
res.status(200).json({
userId: user._id,
token: jwt.sign(
{ userId: user._id},
'RANDOM_TOKEN_SECRET',
{ expiresIn: '24h' }
)
});
})
.catch(error => res.status(500).json({ error }));
})
.catch(error => res.status(500).json({ error }));
};
**app.js
**
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content, Accept, Content-Type, Authorization');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
next();
});
How can I fix that ?
I'm running out of leads or solutions...
Thanks !
I am expecting to see the jwt appears just next to "Authorization: Bearer".

http-proxy-middleware adding custom header

I'm using http-proxy-middleware to setup request proxy from auth service to secured API.
Here I need to add custom header with authenticated user auth ID for every incoming request to the authentication layer. But with following implementation header not adding to the request. Here I've used on.proxyReq,
app.use('/info', auth, createProxyMiddleware({
target: process.env.BASE_API_URL,
changeOrigin: false,
on: {
proxyReq: (proxyReq, req, res) => {
console.log(`On Proxy Request ${proxyReq}`);
proxyReq.setHeader('x-auth-user', 'b05ff410-fbba-11ec-bfce-ddefb9f79237');
},
proxyRes: (proxyRes, req, res) => {
console.log(`On Proxy Response ${proxyRes}`);
},
error: (err, req, res) => {
console.log(`On Error Request ${err}`);
},
},
}));
This issue has resolved with following,
app.use('/info', auth, createProxyMiddleware({
target: process.env.BASE_API_URL,
changeOrigin: false,
onError: (err, req, res, target) => {
res.writeHead(500, {
'Content-Type': 'application/json',
});
res.end({ message: 'Something went wrong on proxy request. Please retry.' });
},
onProxyReq: (proxyReq, req, res) => {
proxyReq.setHeader('x_auth_user', req.user.email);
}
}));

Problem with POST request from React.js component to Node.js server

I'm trying to send data from client's inputs based on React.js to server written in Node.js which put it to DB. I have no errors and after submit, new records show in database but they are empty. I have two inputs and I'm joining them in one string and trying send it to DB (so DB has one property). Can you check my code and see what is wrong? Maybe something with headers...
This is function in React component:
addCompetitor = event => {
event.preventDefault();
const name = this.state.draftCompetitorName;
const lastname = this.state.draftCompetitorLastname;
fetch(`http://localhost:5000/competitors`, {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: `${name}${lastname}` })
})
.then(response => response.json())
};
This is server POST response:
app.post("/competitors/", urlencodedParser, function (req, res) {
const newCompetitor = new Competitor({ name: req.body.name });
newCompetitor.save().then(competitor => res.json(competitor));
});
And it's app configuration:
app.use(function (req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, OPTIONS, PUT, PATCH, DELETE"
);
res.setHeader(
"Access-Control-Allow-Headers",
"Content-Type",
"X-Requested-With"
);
res.setHeader("Access-Control-Allow-Credentials", true);
next();
});
If not first install bodyparser. This parses incoming request bodies in a middleware before your handlers, which will be available under the req.body property.
app.use(bodyParser.json({
limit: '50mb',
parameterLimit: 100000
}))
Alternatively what is the express version you are using ? Is it greater than 4.16? Then you can also use
app.use(express.json());
See notes here
https://expressjs.com/en/api.html#express.json
Modify your code
let databody = {
"name": `${name}${lastname}`,
"otherprop": this.state.otherprop
}
From frontend use
body: JSON.stringify(databody),
In express end remove urlencodedParser , should be like below:
app.post("/competitors", function (req, res) {
console.log(req.body);
});
You are using urlencodedParser as a middleware so I guess you used bodyParser.urlencoded({}) but your request is sending a json format. Try adjusting your request by adding the following header:
'Content-Type': 'application/x-www-form-urlencoded'
EDIT:
Also body should be in the following format:
body: `name=${name}${lastname}`

Angular 5 node js express POST JSON Obj. to Amazon Aws [External API] (formerly CORS issue)

SOLVED, see my answer below
My server runs on localhost:3000
I develop on localhost:4200
I am creating something and trying to post it on an Amazon API
Angular side code:
sendSomething(something) {
const body = JSON.stringify(something);
// const headers = new Headers({'Content-Type': 'application/json'});
const headers = new Headers({'Access-Control-Allow-Origin': '*'});
return this.http.post('http://Amazon-API:port/send', body, {headers: headers})
.map((response: Response) => response.json())
.catch((error: Response) => {
this.error.handleError(error.json());
return Observable.throw(error.json());
});
}
Server side:
//////////////app.js//////////////
app.use(cors());
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", '*'); //<-- you can change this with a specific url like http://localhost:4200
// res.header("Access-Control-Allow-Credentials", true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header("Access-Control-Allow-Headers", 'Origin,X-Requested-With,Content-Type,Accept,content-type,application/json');
next();
});
app.use('http://Amazon-API:port', engineRoutes);
//////////////routes/engine.js//////////////
router.post('/send', engine_controller.send_something);
//////////////controllers/engine.controller.js//////////////
exports.send_something = function (req, res, next) {
const somethingID = req.body.something;
Something.findById(somethingID, function(err, something) {
if (err) {
res.status(404).json({
title: 'Something not found',
error: {message: 'Something went wrong'}
});
}
console.log(something);
if (something) {
res.status(200).json({
message: 'Something successfully sent',
something: something
});
}
})
};
I have tried posting to that API with cors, without cors and with the res.headers appended, and every other variation I could think of
I still get this error which I've seen so common around here, but still, their solutions don't seem to work for me. Still getting this error...
Failed to load http://Amazon-API:port/send: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 403.
That's from NETWORK tab:
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:he-IL,he;q=0.9,en-US;q=0.8,en;q=0.7
Access-Control-Request-Headers:access-control-allow-origin
Access-Control-Request-Method:POST
Connection:keep-alive
Host:Amazon-API:port
Origin:http://localhost:4200
Any kind of help would be so much appreciated
I see you added this code but I can't post comment yet, you may try to add this code before other routes
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With,
Content-Type, Accept');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, PATCH, DELETE,
OPTIONS');
next();
});
Solved,
What I did was routing back to the server on the front:
sendSomething(something) {
const body = JSON.stringify(something);
const headers = new Headers({'Content-Type': 'application/json'});
return this.http.post('http://localhost:3000/api/somethings/send-something', body, {headers: headers})
.map((response: Response) => response.json())
.catch((error: Response) => {
this.error.handleError(error.json());
return Observable.throw(error.json());
});
}
And then accepting this route as it is on the back:
//////////////app.js//////////////////
app.use('/api/somethings/send-something', engineRoutes);
/////////////routes/engine.js/////////
router.post('/', engine_controller.send_something);
And most importantly, in the controller itself I used the newly downloaded request lib to send my json data to my external API:
////////////controlllers/engine.controller.js////////////
const request = require('request');
exports.send_something = function (req, res, next) {
const SomethingID = req.body.something;
Something.findById(SomethingID, function(err, something) {
if (err) {
res.status(404).json({
title: 'Something not found',
error: {message: 'Something went wrong'}
});
}
request({
url: app.get('amazon-API:port/method'),
method: "POST",
json: something
}, function (error, response, body) {
// console.log(error) <--- returns null or error
// console.log(response.statusCode <--- returns 200 / 403 / w.e
// console.log(body) <--- returns response pure html
res.status(200).json({
message: 'Something successfully sent',
response: body,
status: response.statusCode
});
});
})
};
Now as a response I'm getting what the server which I posted to sends me back, which is exactly what I need.
Ultimately I figured my way thanks to many other questions posted here
So thank you SOF once again!

Getting "ProgressEvent" Instead of json from response in Angular + NodeJS

Here is my get function in my message.service
message.service.ts
addMessage(message: Message) {
const body = JSON.stringify(message);
const headers = new Headers({ 'Content-Type': 'application/json' });
return this.http.post('http://localhost:3000/messages', body, { headers: headers })
.map((response: Response) => {
const result = response.json();
const message = new Message(result.obj.title, result.obj.content, 'Dummy', result.obj._id, null);
this.messages.push(message);
return message;
})
.catch((error: Response) => Observable.throw(error.json()));
}
And here is in my backend. If the user is not loggedin. It will return an error (Unauthorized).
routes/messages.js
router.use('/', (req, res, next) => {
jwt.verify(req.query.token, 'secret', (err, decoded) => {
if (err) {
return res.status(401).json({
title: 'Not Authenticated',
error: err
});
}
next();
});
});
And some posts says that it's related to CORS.
But I have this on my backend too.
app.js
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, PATCH, DELETE, OPTIONS');
next();
});
app.use('/messages', messageRoutes);
app.use('/users', userRoutes);
app.use('/api', appRoutes);
And this is in my component.
message-input.component.ts
this.messageService.addMessage(message)
.subscribe(
data => this.snackBar.open('Your message is added!', 'Success!', {duration: 3000, extraClasses: ['success-snackbar']}),
error => console.error(error)
);
When there's an error because of authorization. The error is not the one I return from my backend. Instead it's this "Progress Event"
ProgressEvent {isTrusted: true, lengthComputable: false, loaded: 0, total: 0, type: "error", …}
I want to know how to show the error from my backend in json format. The error that should show to my console log.

Categories

Resources