how to stub sinon for aws4 sign request - aws-sdk-nodejs

I am new to sinon and aws. I need to write a test case for the following code snip. I am unable to locate how to stub for aws4.sign. pls help
function signRequest(Parameter, creds, body) {
console.log("*********** signRequest *********************");
var hostname = Parameter.Value.split('//', 2)[1].split('/', 2)[0];
let request = {
service: 'execute-api',
region: REGION,
host: hostname,
method: 'POST',
url: `${Parameter.Value}/api`,
path: '/api',
data: body, // object describing the mappedbody
body: body,
headers: {
'content-type': 'application/json'
}
};
var signedRequest = aws4.sign(request, creds);
console.log("signRequest-->signedRequest: " + signedRequest)
return signedRequest;
}

Related

there's no question mark printing before query params

first way I tried is :
static async callSendApi(requestBody) {
let url = new URL(
`${API_URL}/${PAGE_ID}/messages`
);
url.search = new URLSearchParams({
access_token: `${PAGE_ACCESS_TOKEN}`,
});
console.warn("Request body is\n" + JSON.stringify(requestBody));
let response = await axios.post(url, {
headers: { "Content-Type": "application/json" },
body: JSON.stringify(requestBody),
// access_token: `${PAGE_ACCESS_TOKEN}`,
});
if (!response.ok) {
consoleconst`Unable to call Send API: ${response.statusText}`,
await response.json();
}
}
Second way I tried is :
static async callSendApi(requestBody) {
let url = new URL(
`${API_URL}/${PAGE_ID}/messages?access_token=${PAGE_ACCESS_TOKEN}`
);
/* url.search = new URLSearchParams({
access_token: `${PAGE_ACCESS_TOKEN}`,
});*/
console.warn("Request body is\n" + JSON.stringify(requestBody));
let response = await axios.post(url, {
headers: { "Content-Type": "application/json" },
body: JSON.stringify(requestBody),
// access_token: `${PAGE_ACCESS_TOKEN}`,
});
if (!response.ok) {
consoleconst`Unable to call Send API: ${response.statusText}`,
await response.json();
}
}
the error I get :
error: {
message: 'Unknown path components: /messagesaccess_token=access_token
type: 'OAuthException',
code: 2500,
fbtrace_id: 'AbBJGVotjz3ijKKLzVE6_CM'
}
I'm receiving this error in both ways. both ways are escaping the '?' mark. I have no idea what is happening.. I'm using heroku for this. I tried deleting and redeploying the repository to confirm if the code is not updating. but still gives this error. :( .
I tried withot using URL and URLSearchParams and it worked!
below is my code:
static async callSendApi(requestBody) {
console.warn("Request body is\n" + JSON.stringify(requestBody));
let response = await axios.post(
`${API_URL}/${PAGE_ID}/messages`,
{
params: { access_token: `${PAGE_ACCESS_TOKEN}` },
},
{
headers: { "Content-Type": "application/json" },
body: JSON.stringify(requestBody),
}
);
if (!response.ok) {
consoleconst`Unable to call Send API: ${response.statusText}`,
await response.json();
}
}

How to call a POST API from lambda function?

I am trying to integrate a POST API call from a lambda function using Node.js 12.x.
I tried like below:
var posturl = "My post api path";
var jsonData = "{'password':'abcdef','domain':'www.mydomain.com','username':'abc.def'}";
var req = require('request');
const params = {
url: posturl,
headers: { 'jsonData': jsonData }
};
req.post(params, function(err, res, body) {
if(err){
console.log('------error------', err);
} else{
console.log('------success--------', body);
}
});
But when I am execute it using state machine, I am getting the below exception:
{
"errorType": "Error",
"errorMessage": "Cannot find module 'request'\nRequire stack:\n- /var/task/index.js\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js",
"trace": [
"Error: Cannot find module 'request'",
"Require stack:",
"- /var/task/index.js",
"- /var/runtime/UserFunction.js",
"- /var/runtime/index.js",
" at Function.Module._resolveFilename (internal/modules/cjs/loader.js:815:15)",
" at Function.Module._load (internal/modules/cjs/loader.js:667:27)",
" at Module.require (internal/modules/cjs/loader.js:887:19)",
" at require (internal/modules/cjs/helpers.js:74:18)",
" at Runtime.exports.handler (/var/task/index.js:8:14)",
" at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
]
}
Here the posturl is my api path and jsondata is my key value pair data.
So How can I call a POST API from lambda function? How can I pass the entire jsondata key when call API? How can I parse the response after the service call?
Update: I have tried like below
All my details are passing with a key jsonData, where I can specify that? Without that key, it will not work.
exports.handler = (event, context, callback) => {
const http = require('http');
const data = JSON.stringify({
password: 'mypassword',
domain: 'www.mydomain.com',
username: 'myusername'
});
const options = {
hostname: 'http://abc.mydomain.com',
path: 'remaining path with ticket',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
};
const req = http.request(options, (res) => {
let data = '';
console.log('Status Code:', res.statusCode);
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('Body: ', JSON.parse(data));
});
}).on("error", (err) => {
console.log("Error: ", err.message);
});
req.write(data);
req.end();
};
source : How to Make an HTTP Post Request using Node.js
const https = require('https');
const data = JSON.stringify({
name: 'John Doe',
job: 'Content Writer'
});
const options = {
hostname: 'reqres.in',
path: '/api/users',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
};
const req = https.request(options, (res) => {
let data = '';
console.log('Status Code:', res.statusCode);
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('Body: ', JSON.parse(data));
});
}).on("error", (err) => {
console.log("Error: ", err.message);
});
req.write(data);
req.end();

How can I format the structure of my formData object to match what the backend expects?

I am using formData to POST an image I uploaded via ImagePicker. I am sending the parameters like so:
let formData = new FormData();
formData.append('image', { uri: localUri, name: filename, type });
formData.append('description', 'this is the decription');
return await fetch('https://prana-app.herokuapp.com/v1/visions/', {
method: 'POST',
body: formData,
header: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-User-Email': this.state.email,
'X-User-Token': this.state.accessToken
},
});
};
This doesn't seem to work, as I am getting a very generic NoMethodError (undefined methodbuild' for nil:NilClass):` error.
How can I POST my parameters in the correct way given that the image parameter is an image and the description parameter is a string?
Thanks
Content-Type must be different when using Formdata.
example.js:
fileSend = () => {
const apiUrl = "http://00.000.00.000:0000/upload";
const uri = this.state.image;
const stringdata = {
username: this.state.name,
introduce: this.state.introducetext,
addresstext: this.state.addresstext
};
const uriParts = uri.split(".");
const fileType = uriParts[uriParts.length - 1];
const formData = new FormData();
formData.append("userfile", {
uri,
name: `photo.${fileType}`,
type: `image/${fileType}`
});
for (var k in stringdata) {
formData.append(k, stringdata[k]);
}
const options = {
method: "POST",
body: formData,
headers: {
Accept: "application/json",
"Content-Type": "multipart/form-data"
}
};
return fetch(apiUrl, options)
As shown in the example above, Content-Type should write multipart/form-data and pass it over to For ... in if Stringdata is not one.

MS Graph Sample Application Integration Test not Working

I want to do what the MS Graph sample node app is doing in its integrationTests.js, but that test doesn't work. Here's what I've tried:
Followed the quick start for creating a node.js app.
Ran the app. Ensured it worked by sending an e-mail.
Modified the test Checking that the sample can send an email to use my account parameters.
Tried to run the test. It fails with 403: insufficient scope. The call to get the token returned scopes, but lacked Mail.Send.
In the post data for the call to login.microsoftonline.com, I added "scope: 'Mail.Send'"
I still receive a valid token, and the return scope includes Mail.Send, but when I try to post with that token, I get 400: cannot POST /beta/me/sendMail
I tried adding scope (Mail.Send) in the query string and as a header (thought I saw that somewhere), but it made no difference.
I added the Mail.Send permission (under "Application Permissions") for the app in the application registration portal.
I compared the token (using https://jwt.ms) from my test call to the call from the app when it works. I see no real difference. They both contain the Mail.Send scope.
Here is the code (which is only slightly different from what's in the sample):
// in graphHelper.js
function postSendMail(accessToken, message, callback) {
request
.post('https://graph.microsoft.com/beta/me/sendMail')
//.post('https://graph.microsoft.com/beta/me/sendMail?scope=Mail.Send') // nope
.send(message)
.set('Authorization', 'Bearer ' + accessToken)
.set('Content-Type', 'application/json')
.set('Content-Length', message.length)
.set('scope', 'Mail.Send') // nope
.end((err, res) => {
callback(err, res);
});
}
describe('Integration', function () { // mocha
var accessToken;
var scope;
const config = getConfig();
// My account variables in testConfig.json file
function getConfig() {
var configFilePath = path.join(__dirname, 'testConfig.json');
return JSON.parse(fs.readFileSync(configFilePath, { encoding: 'utf8' }));
}
function getAccessToken(done) {
var postData = querystring.stringify(
{
grant_type: 'password',
//grant_type: 'client_id', // not supported
//grant_type: 'authorization_code', // This assumes you've requested an auth code.
resource: 'https://graph.microsoft.com/',
scope: 'Mail.Send',
client_id: config.test_client_id_v2,
client_secret: config.test_client_secret_v2,
username: config.test_username,
password: config.test_password
}
);
var postOptions = {
host: 'login.microsoftonline.com',
port: 443,
path: '/common/oauth2/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
var postRequest = https.request(postOptions, function (res) {
var data = '';
res.setEncoding('utf8');
res.on('data', function (chunk) {
data += chunk;
});
res.on('end', function () {
const response = JSON.parse(data);
accessToken = response.access_token;
scope = response.scope;
done();
});
});
postRequest.on('error', function (e) {
console.log('Error: ' + e.message);
done(e);
});
postRequest.write(postData);
postRequest.end();
}
before( // eslint-disable-line no-undef
function (done) {
getAccessToken(done);
}
);
it('Checking that the sample can send an email',
function (done) {
var postBody = emailer.generateMailBody(config.test_name, config.test_username);
graphHelper.postSendMail(
accessToken, scope,
JSON.stringify(postBody),
function (error) {
assert(error === null, `The sample failed to send an email: ${error}`);
done();
});
}
);
});

HTTP request cannot get the contact photo using Microsoft Graph API

If I use the library #microsoft/microsoft-graph-client, I can get the contact photo as binary data, convert it to base64 and get the correct photo with the code below:
const request = require('request')
const microsoftGraph = require('#microsoft/microsoft-graph-client');
let token = token-value
let client = getMicrosoftGrapClient(token);
let id = contact-id;
let url = '/me/contacts/' + id + '/photo/$value';
client.api(url).get().then((res) => {
//console.log(res);
var encodedImage = new Buffer(res, 'binary').toString('base64');
console.log("encodedImage>>>>>>>>>>>>>>>>>>>>>>")
console.log (encodedImage);
}).catch((err) => {
console.log(err);
});;
function getMicrosoftGrapClient (token) {
// Create a Graph client
return microsoftGraph.Client.init({
authProvider: (done) => {
// Just return the token
done(null, token);
}});
}
I cannot get the correct contact photo with the HTTP GET. The HTTP
response code is 200 but the body is not the binary data of photo.
Please let me know what the error is. Here is the code:
const request = require('request')
request({
url: "https://graph.microsoft.com/v1.0/me/contacts/{contact_id}/photo/$value",
method: 'GET',
headers: {
'content-type': 'image/jpg',
'Authorization': 'Bearer {token}'
}
}, function (error, response, body){
console.log(error);
var encodedImage = new Buffer(body, 'binary').toString('base64');
console.log(encodedImage);
});
Encoding needs to be explicitly specified as
encoding: null
In that case the body will be of type Buffer, instead of the default (string).
And content-type could be omitted.
Example
request({
url: "https://graph.microsoft.com/v1.0/me/photo/$value",
method: 'GET',
encoding: null,
headers: {
'Authorization': 'Bearer ' + accessToken,
}
}, function (error, response, body) {
var encImage = new Buffer(body, 'binary');
fs.writeFileSync(filePath, encImage );
});

Resources