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

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.

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);
}
}));

Node.js read request body from Fetch API

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?

Express server response is a stream, how to make it a string / json

I am POSTing data to my express (v.4+) server. However, the response I get back in the browser is in the form:
Response {type: "cors", url: "http://localhost:1111/", status: 200, ok: true, …}
Specifically, the body of response is a ReadbleStream, instead of json or string I expected as per the response I am sending back.
The server code is:
mongoose.connect('mongodb://localhost/block');
const app = express();
app.set('port', 1111);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/', (req, res, next) => { // for cors
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,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Credentials', true);
next();
});
app.post('/', (req, res) => {
const { dataType, table } = req.body;
const { rows } = table;
const log = {
msgArray: []
};
function saveData(dbModel) {
rows.forEach(row => {
row.data_initiated = new Date();
row.status = 'initiated';
const entry = new dbModel(row);
entry.save(err => {
if (err) {
log.msgArray.push({ err });
}
log.msgArray.push({
msg: 'saved!'
});
});
});
}
if (dataType === 'Contract') {
saveData(Contract);
} else if (dataType === 'Commodity') {
saveData(Commodity);
} else {
saveData(Client);
}
res.send(log).end();
I am using fetch on the client side to POST data.
How can I get this to correct send json / string back to the user?
Thanks,
When using fetch, the response has to be transformed into JSON, & returned back. In the subsequent then, the transformed value is available to be used.
fetch( url, config)
.then( res => res.json())
.then( json => {
console.log( json );
...
}
Its worth mentioning that this is a bit different to how we are used to handling responses when using Axios.js (promise based AJAX library).
P.S: I updated the question to fix the code so that the response is sent correctly.

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!

Categories

Resources