Postman works but not react redux action (axios.post request) - node.js

Something really weird is going on.
I am building an API using Cloud Functions. Basically the Cloud Function makes a request to the server and retrieves a token.
This is the code
exports.Klarna = functions.https.onRequest((req, res) => {
// const app = express();
// app.use(cors({ origin: true }));
res.set('Access-Control-Allow-Origin', '*');
const url = "https://someLink.com";
const creds = req.body;
const token = `Basic ${Buffer.from(
`${"Pxxx"}:${"xxx"}`
).toString("base64")}`;
request(
"https://somelink.com",
{
method: "POST",
url: url,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
Authorization: token,
},
Authorization: token,
body: creds,
json: true,
},
function (error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body);
res.json(response.body.client_token);
}
}
);
});
Then I am calling it from the frontend (reactJS) like this using redux-thunk and axios:
export function Klarna() {
return async (dispatch) => {
try {
let response = await axios('https://google.cloud.function', {
method: 'POST',
redirect: 'follow',
headers: { 'Content-Type': 'application/json', "Access-Control-Allow-Origin": "*",Authorization: "Basic XXX" },
body: JSON.stringify({
"purchase_country": "SE",
"purchase_currency": "SEK",
"locale": "sv-SE",
"order_amount": 10,
"order_tax_amount": 0,
"order_lines": [
{
"type": "physical",
"reference": "19-402",
"name": "Battery Power Pack",
"quantity": 1,
"unit_price": 10,
"tax_rate": 0,
"total_amount": 10,
"total_discount_amount": 0,
"total_tax_amount": 0
}
]
}),
json: true
})
console.log(response);
} finally {
console.log("yea!")
}
}
}
however while in postman succeeds, here I get
[Error] Failed to load resource: The request timed out. (Klarna, line 0)
[Error] Unhandled Promise Rejection: Error: timeout of 0ms exceeded
(anonymous function) (main.chunk.js:7307)
asyncFunctionResume
(anonymous function)
promiseReactionJobWithoutPromise
promiseReactionJob
Any suggestions that could help me moving forward with this? Have been 2 days around this bug and I am not seeing a way to solve it.
UPDATE:
I went around and found how to do it. Here is the code:
const functions = require("firebase-functions");
const express = require("express");
var rp = require("request-promise");
const cors = require("cors")({
origin: true,
allowedHeaders: [
"Access-Control-Allow-Origin",
"Access-Control-Allow-Methods",
"Content-Type",
"Origin",
"X-Requested-With",
"Accept",
"Authorization"
],
methods: ["POST", "OPTIONS"],
credentials: true,
});
const admin = require("firebase-admin");
const serviceAccount = require("./serviceAccountKey.json");
var request = require("request");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
exports.Klarnas = functions.https.onRequest((req, res) => {
// Google Cloud Function res.methods
res.set("Access-Control-Allow-Headers", "Content-Type");
res.set("Content-Type", "Application/JSON");
// CORS-enabled req.methods, res.methods
return cors(req, res, async () => {
res.set("Content-Type", "Application/JSON");
var origin = req.get("Origin");
var allowedOrigins = [
"https://yourLink.com",
"http://localhost:3000",
"http://localhost:5001/xxx/xxx",
];
if (allowedOrigins.indexOf(origin) > -1) {
// Origin Allowed!!
res.set("Access-Control-Allow-Origin", origin);
if (req.method === "OPTIONS") {
// Method accepted for next request
res.set("Access-Control-Allow-Methods", "POST");
//SEND or end
return res.status(200).send({});
} else {
// After req.method === 'OPTIONS' set ["Access-Control-Allow-Methods": "POST"]
// req.method === 'POST' with req.body.{name} => res.body.{name}
// req.method === 'PUT' with req.body.{name}, no res.body.{name}
const url = "https://someLink.com";
const creds = req.body;
const token = `Basic ${Buffer.from(
`${"XXXX"}:${"XXX"}`
).toString("base64")}`;
request(
"https://someLink.com",
{
method: "POST",
url: url,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
Authorization: token,
},
Authorization: token,
body: creds,
json: true,
},
function (error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body);
res.json(response.body.client_token);
}
}
);
}
} else {
//Origin Bad!!
//SEND or end
return res.status(400).send("no access for this origin");
}
});
});

Please try to use then/catch to catch the error orhandle the promise rejection.
You can use the following code:
export function Klarna() {
return async (dispatch) => {
let response = await axios('https://[REGION]-[PROJECT-ID].cloudfunctions.net/Klarna', {
method: 'POST',
redirect: 'follow',
headers: { 'Content-Type': 'application/json', "Access-Control-Allow-Origin": "*",Authorization: "Basic [Token]==" },
body: JSON.stringify({
"purchase_country": "SE",
"purchase_currency": "SEK",
"locale": "sv-SE",
"order_amount": 10,
"order_tax_amount": 0,
"order_lines": [
{
"type": "physical",
"reference": "19-402",
"name": "Battery Power Pack",
"quantity": 1,
"unit_price": 10,
"tax_rate": 0,
"total_amount": 10,
"total_discount_amount": 0,
"total_tax_amount": 0
}
]
}),
json: true
}).then(data => console.log(data))
.catch(err => console.log(err);
}
}
Please let me know if it works.

Related

cors policy error on express axios get method - error 503

I'm trying to pass throught cors policy using nodejs + express in an heroku api, but getting this error:
Access to XMLHttpRequest at 'https://....' from origin 'https://...' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource
My methods in the frontend are:
const fetchUser = async () => {
const res = await axios.get(
process.env.REACT_APP_API_URL + `/api/user/${userId}`,
{
headers: {
Authorization: `Bearer + ${token}`,
},
},
)
console.log(res.data)
setStatsInit({ waiting: false, stats: res.data })
}
in server:
const corsOptions = {
origin: true,
methods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'OPTIONS', 'DELETE'],
headers: [
'Content-Type',
'Authorization',
'application/json',
'text/plain',
'*/*',
],
credentials: true,
maxAge: 3600,
}
app.use(cors(corsOptions))
app.get('/api/user/:uid', middleware.decodeTokenContext, async (req, res) => {
const user = {
uid: req.params.uid,
}
const userStats = await FirestoreClient.getByPath(`users/${user.uid}`)
return res.json({ userStats })
})
The middleware, to check if it is authenticated:
async decodeTokenContext(req, res, next) {
let token = req.headers.authorization.split(' ')[1]
try {
const decodeValue = await admin.auth().verifyIdToken(token)
if (decodeValue) {
return next()
}
return res.json({ message: 'Não autorizado' })
} catch (e) {
return res.json({ message: 'Erro Interno' })
}
}
on the network, on browser, i got this error:
How to solve that error of cors?

warning: req is not defined in (nodejs) lambda function

This is part of my code in lambda to insert some values into an oracle database (from Amplify cli)
exports.handler = async (event, context, callback) => {
console.log(`EVENT: ${JSON.stringify(event)}`);
let conn;
try {
conn = await oracledb.getConnection(connAttr);
let result = await conn.execute(
"INSERT INTO employee VALUES (:name, :id, TO_TIMESTAMP(:date1, 'DD-MM-YYYY HH24:MI:SS'), TO_TIMESTAMP(:date2, 'DD-MM-YYYY HH24:MI:SS'))",
[req.body.name, req.body.discount, req.body.date1, req.body.date2],
{
name : req.body.name,
id : req.body.id,
date1 : req.body.date1,
date2 : req.body.date2
}
);
);
const response = {
statusCode: 200,
body: JSON.stringify(result),
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "*",
"Access-Control-Allow-Methods": "*",
"Access-Control-Allow-Credentials" : "true",
"content-type": "application/json"
}
};
callback(null, response);
console.log('Query executed');
}
catch (err) {
const response = {
statusCode: 400,
body: JSON.stringify({message: err}),
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "*",
"Access-Control-Allow-Methods": "*",
"Access-Control-Allow-Credentials" : "true",
"content-type": "application/json"
}
};
}
}
When I call the api connected, I get no response so I decided to use the aws console for some quick debugging and the code editor is giving me the warning: req is not defined; please fix or add /*globalreq*/
How can I fix this?
Seem like you were trying to extract the request body when this Lambda function was called, but you have not assigned that body to your "req" variable.
You should explicitly extract it from the event argument, you can refer that body (payload) from the document below
https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html

Uploading an image token by react native camera to express server responding 413 error

I am using react native camera to take picture and make post request to send it to server to be storted there and perform some actions:
here is the code in frontend for send the fetch request:
const takePicture = async () => {
if (camera) {
const data = await camera.current.takePictureAsync({ quality: 0.25, base64: true });
setTakingPic(true)
fetch('http://*************/users/upload', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
image: data.base64,
id: Id
}),
}).then((response) => console.log(response))
.then((res) => {
if (res.success === true) {
alert(res.message);
navigation.navigate('studentD')
}
else {
alert(res.message);
}
})
.catch(err => { console.log(err); });
}
};
and in backend:
router.post('/upload', function (req, res) {
var image = req.body.image
var id = req.body.id
var status = "on hold"
var userid = localStorage.getItem('userId');
console.log(image)
fs.writeFile('../images/' + id + '.png', image, 'base64', (err) => {
if (err) { throw err }
else {
connection.query("INSERT INTO face_status (status,imageinfo,user_id) VALUES (?,?) ", [status, image, userid], function (err, row) {
if (err) {
console.log(err);
} else {
res.send({ 'success': true, 'message': 'ok' });
}
});
}
})
})
when camera capture the picture and send the request the server is log the request as POST /users/upload 413 2068.099 ms - 1220
which something related to the upload limit size, I tried to set the following:
router.use(bodyParser.json({ limit: '50mb' }));
router.use(bodyParser.urlencoded({ limit: '50mb', extended: true }));
but still same error, I also console.log(response) the response in frontend and this what I got:
{"_bodyBlob": {"_data": {"__collector": [Object], "blobId": "2313bc80-fd1d-4059-91f8-e16ffdaaa4eb", "offset": 0, "size": 1220}}, "_bodyInit": {"_data": {"__collector": [Object], "blobId": "2313bc80-fd1d-4059-91f8-e16ffdaaa4eb", "offset": 0, "size": 1220}}, "bodyUsed": false, "headers":
{"map": {"connection": "keep-alive", "content-length": "1220", "content-type": "text/html; charset=utf-8", "date": "Mon, 08 Feb 2021 11:21:31 GMT", "etag": "W/\"4c4-N4ip9wLgHN8MkaoeSMzYtH17uPI\"", "keep-alive": "timeout=5", "x-powered-by": "Express"}}, "ok": false, "status": 413, "statusText": undefined, "type": "default", "url": "http://*************/users/upload"}

no 'Access-Control-Allow-Origin' header is present on the requested resource. while uploading image to s3 using aws lambda

var mysql = require('mysql');
var config = require('./config.json');
var jwt = require('jsonwebtoken');
var configuration = require('./jwtconfig.js');
const isBase64 = require('is-base64');
const base64mime = require('base64mime');
const AWS = require('aws-sdk');
AWS.config.update({ region: 'us-east-2' });
const s3 = new AWS.S3({ apiVersion: '2006-03-01' });
const bucket = "bucketname";
let path = "bucketpath/";
var pool = mysql.createPool({
host: config.dbhost,
user: config.dbuser,
password: config.dbpassword,
database: config.dbname
});
module.exports.handler = (event, context, callback) => {
const { eventname, event_type, event_platform, event_date, co_host, stream_url, description, event_time, user_id, zoom_id,c_id } = JSON.parse(event.body);
const image = JSON.parse(event.body).imageBase64;
//let token = event.headers['x-access-token'] || event.headers['authorization'];
context.callbackWaitsForEmptyEventLoop = false;
// if (token) {
// jwt.verify(token, configuration.secret, (err, decoded) => {
// if (err) {
// callback({
// statusCode: 201,
// headers: {
// "Access-Control-Allow-Origin": "*",
// "Access-Control-Allow-Headers": "Content-Type,x-access-token",
// // "Access-Control-Request-Headers":"x-access-token",
// "Access-Control-Allow-Methods": "OPTIONS,POST"
// },
// body: JSON.stringify(err)
// }, null);
// } else {
// event.decoded = decoded;
if (eventname && event_type && event_date) {
let key = path + "img" + "_" + new Date().getTime();
const options = {
Bucket: bucket,
Key: key,
StorageClass: 'STANDARD_IA',
ACL: 'public-read',
ContentType: base64mime(image),
ContentEncoding: 'base64',
Body: Buffer.from(image.replace(/^data:image\/\w+;base64,/, ""), 'base64')
};
s3.upload(options, (err, data) => {
if (err) {
callback({
"statusCode": 400,
"headers": {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type,x-access-token,Origin,XMLHttpRequest",
"Access-Control-Request-Headers":"x-access-token",
"Access-Control-Allow-Methods": "OPTIONS,POST",
"Access-Control-Allow-Credentials" : "true"
},
"body": JSON.stringify(err)
}, null);
} else {
var bhu = data["Location"];
callback(null, { statusCode: 200, headers: { "Access-Control-Allow-Origin": "*" , "Access-Control-Allow-Headers": "Origin, X-Requested-With,x-access-token, Content-Type, Accept, Authorization, token, XMLHttpRequest"},body:JSON.stringify(bhu)});
pool.getConnection(function (err, connection) {
if (err) {
return callback(err, null);
}
var quer = `Insert INTO event (eventname,event_type,event_platform,event_date,co_host,stream_url,description,event_time,user_id,zoom_id,image,c_id) values ('${eventname}', '${event_type}', '${event_platform}', '${event_date}','${[co_host]}', '${stream_url}', '${description}','${event_time}','${event.pathParameters.user_id}','${zoom_id}','${bhu}','${c_id}')`;
connection.query(quer, [parseInt(event.pathParameters.user_id)], function (error, results, field) {
if (error) {
callback({
statusCode: 400,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,HEAD,PUT,POST,OPTIONS,UPDATE,DELETE",
"Access-Control-Allow-Headers": "Origin, X-Requested-With,x-access-token, Content-Type, Accept, Authorization, token, XMLHttpRequest",
"Access-Control-Allow-Credentials" : "true"
},
body: JSON.stringify(error)
}, null);
} else {
var insertId = results.insertId;
var getquer = `SELECT * FROM event WHERE id = ${insertId}`;
connection.query(getquer, function (error, result) {
if (error) {
callback({
statusCode: 400,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,HEAD,PUT,POST,OPTIONS,UPDATE,DELETE",
"Access-Control-Allow-Headers": "Origin, X-Requested-With,x-access-token, Content-Type, Accept, Authorization, token, XMLHttpRequest",
"Access-Control-Allow-Credentials" : "true"
},
body: JSON.stringify(error)
}, null);
} else {
var customRes = [];
customRes = {
"statusCode": 200,
"message": "event created successfully",
"data": result,
//"token data":decoded
};
callback(null, {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,HEAD,PUT,POST,OPTIONS,UPDATE,DELETE",
"Access-Control-Allow-Headers": "Origin, X-Requested-With,x-access-token ,Content-Type, Accept, Authorization, token, XMLHttpRequest",
"Access-Control-Allow-Credentials" : "true"
},
body: JSON.stringify(customRes)
});
}
});
}
});
});
}
});
}
// });
// } else {
// var customRes = {};
// customRes = {
// "statusCode": 201,
// "message": "token is not provided",
// };
// callback(null, {
// statusCode: 201,
// headers: {
// "Access-Control-Allow-Origin": "*",
// "Access-Control-Allow-Headers": "Content-Type,x-access-token",
// "Access-Control-Allow-Methods": "OPTIONS,POST"
// },
// body: JSON.stringify(customRes)
// });
//}
};
I am getting 'Access-Control-Allow-Origin' header is present on the requested resource error when accessing this code API in front end . i am using aws lambda function to upload image to s3 bucket . i have also included . access-control-allow -origin header in my code . i have enable proxy integration in API gateway . but I am getting this error
I found that you've already open CORS in your NodeJS code but it's just for lambda part only. But all of request will be passed through API Gateway thus you may need to open CORS in AWS API Gateway.
Go to your API Gateway Path > then click Actions dropdown > Click Enable CORS as per attach for reference.

Using CSRF Token from GET and Uses that in POST | 403 Forbidden | AWS Lambda

I am creating node.js function through aws lambda which makes a GET request to Hybris Market Place and gets a CSRF Token. Then I am using that token to make another POST request to post some data to Hybris Market place but I am getting an error of 403 Forbidden. Same thing works in Postman which I believe due to POSTMAN keeps GET session alive and hence CSRF token is still valid. How May I achieve that in AWS Lambda function. Below is my code. I am using promise to make two requests.
const https = require('https');
exports.handler = async (event, context, callback) => {
const tokenOptions = {
"host": "*******.s4hana.ondemand.com",
"path": "/sap/opu/odata/sap/***********/",
"port": null,
"headers":{
"authorization": "Basic ************=",
"cache-control": "no-cache",
"x-csrf-token": "fetch"
},
"method": "GET"
};
var getToken = (tokenOptions) => {
return new Promise((resolve,reject)=>{
const req = https.request(tokenOptions, (res) => {
var xToken = res.headers["x-csrf-token"];
var sCookies = res.headers["set-cookie"];
var response = [xToken,sCookies]
res.on('data', () => {
console.log('Successfully processed HTTPS response');
resolve(response);
});
res.on('end', () => {
});
});
req.on('error', function(){
reject('Request to get token failed.');
});
req.end();
});
};
var postContent = (response) => {
return new Promise((resolve,reject)=>{
var options = {
"method": "POST",
"host": "*********-***.s4hana.ondemand.com",
"path": "/sap/opu/odata/sap/*********/*******",
"port":null,
"headers":
{ "authorization": "Basic *******==",
"x-csrf-token": response[0],
"accept": "application/json",
"content-type": "application/json",
"cache-control": "no-cache",
},
"cookie":response[1],
"body":
{
/* Data I want to POST */
},
"json": true
};
const req = https.request(options, (res,data) => {
console.log(res.statusCode);
res.on('data', () => {
resolve('Successfully submitted.');
});
res.on('end', () => {
});
});
req.on('error', function(err,res){
reject('Request to get Post failed.');
});
req.end();
});
};
getToken(tokenOptions).then((response) =>{
console.log('Result: ' +response[0]);
return postContent(response);
}).then((successMsg) =>{
callback(null,successMsg);
}).catch((errMsg)=>{
callback();
});
};

Resources