How to make SSL-Requests with AWS-Lambda-Function? - amazon-web-services

I have a AWS-Lambda function that gots triggered after a file was placed into an S3-Bucket.
This is my lambda-function:
var http = require('http');
exports.handler = function (event, context) {
var bucket = event.Records[0].s3.bucket.name;
var key = event.Records[0].s3.object.key;
var newKey = key.split('.')[0].slice(8);
var url = 'https://xxxxx.herokuapp.com/api/messages/'+newKey+'/processingFinished'
console.log("URL:" + url)
http.get(url, function (result) {
console.log('!!!! Success, with: ' + result.statusCode);
context.done(null);
}).on('error', function (err) {
console.log('Error, with: ' + err.message);
context.done("Failed");
});
};
In CloudWatch Logfiles i see complaints that https is not supported:
2017-07-27T10:38:04.735Z 8428136e-72b7-11e7-a5b9-bd0562c862a0 Error: Protocol "https:" not supported. Expected "http:"
at new ClientRequest (_http_client.js:54:11)
at Object.exports.request (http.js:31:10)
at Object.exports.get (http.js:35:21)
at exports.handler (/var/task/index.js:18:8)
But the listed URL can be opened with any webbrowser. The Server accepts SSL and the whole API is working per SSL.
Why is AWS denying SSL-Requests? How to solve this?

Per the node documentation: (https://nodejs.org/api/https.html)
HTTPS is the HTTP protocol over TLS/SSL. In Node.js this is implemented as a separate module.
Use
http = require('https');

Related

How do you pass query string parameters to the AWS API Gateway client with the Javascript SDK?

I have an endpoint defined in AWS API Gateway that uses a Lambda integration. The Lambda function expects query string parameters that would be available in the event object passed to it.
My API is at example.execute-api.us-east-1.amazonaws.com/dev/my-resource and I have query string parameters like foo=test.
So the full endpoint would be
example.execute-api.us-east-1.amazonaws.com/dev/my-resource?foo=test
I can visit this endpoint in a browser or request it in postman, and get the expected response, so I know that the API Gateway is configured properly. However when I use the Javascript SDK, I can't seem to pass query string parameters.
According to the last part of this page from the docs, I should be able to just pass in a JSON object that will be interpreted as query string parameters, like so:
var apiClient = apigClientFactory.newClient();
var requestParams = {"foo": "test"};
apiClient.myResourceGet(requestParams).then(function(result) {
// Do something with the response
});
However, in my case requestParams seems to be ignored. In the Lambda function, the event has an empty queryStringParameters field. How can I pass the key/values defined in the requestParams object as query string parameters to this endpoint?
since your following end point passing query param , you really no need json objet
example.execute-api.us-east-1.amazonaws.com/dev/my-resource?foo=test
create variable
var test = <assign value>
now
var params = {
host: "execute-api.us-east-1.amazonaws.com",
path: "/dev/my-resource?foo="+test
};
Example :
var https = require('https');
exports.handler = (event, context, callback) => {
var params = {
host: "bittrex.com",
path: "/api/v1.1/public/getmarketsummaries"
};
var req = https.request(params, function(res) {
let data = '';
console.log('STATUS: ' + res.statusCode);
res.setEncoding('utf8');
res.on('data', function(chunk) {
data += chunk;
});
res.on('end', function() {
console.log("DONE");
console.log(JSON.parse(data));
});
});
req.end();
};

Get PDF from API using AWS API gateway and Lambda

I have an internal API that provides data in different formats by just passing the id + format. For Example if I want to get a PDF of a produc with ID = 1 I will just make a call to the app with apiurl/latest/1.pdf.
This works fine when I am in the internal network since the host is only available internally. To access it publicly, we have implemented an authorization using API gateway and Lambda. Lambda takes are of the authorization and return the result just fine :
When I request JSON data
When I request XML data
Here a sample version of the lambda:
var request = require('request');
exports.handler = function(event, context, callback) {
var fUrl = event.fUrl + event.pid;
if(event.fsUrl.indexOf('product') >-1){
fUrl = fUrl + '.' + event.format
}
request({
url: fUrl,
}, function(error, response, body) {
if(error){
return callback(error);
}else{
return callback(null, response.body);
}
});
}
but not PDF. Some screens from the postman. I used both Send and Download in Postman.
Any thoughts?

How do I get response headers for AWS JavaScript SDK calls?

I have a simple AWS Lambda function which makes an S3.getObject() call as follows:
const AWS = require('aws-sdk');
AWS.config.logger = console;
const s3 = new AWS.S3();
exports.handler = async (event) => {
return await getObject({
Bucket: "<MY-BUCKET>",
Key: "<MY-KEY>"
}).then( (res) => {
console.log('Retrieved object from S3');
console.log(res);
return res.Body.toString('ascii');
})
};
async function getObject(params){
return await s3.getObject(params).promise();
}
I've enabled logging SDK calls as per this document.
How do I get response headers for the s3.getObject() SDK call that was made? I am basically trying to retrieve the S3 request ID and extended request ID.
The in-built logger added via the "AWS.config.logger = console;" line does not seem to log response headers. How else do I get response headers for AWS JavaScript SDK calls?
P.S: Bonus points if you can let me know whether or not I need two await keywords in the code above.
Listen to httpHeaders event.
var requestObject = s3.getObject(params);
requestObject.on('httpHeaders', (statusCode, headers, response, statusMessage) => {
// your code here.
});
requestObject.promise()
.then(response => { ... })

Lambda invoke via SDK is slower than API Gateway

I have a setup like this:
Browser -> API Gateway -> Lambda: 87 ms
Browser -> Node.js Script -> AWS SDK -> Lambda: 163 ms
If i call the Lambda function via API Gateway then then response time is ok.
If i call the Lambda function via AWS SDK then the response is very slow.
I would like to get rid of API Gateway. Because it is expensive. However, AWS-SDK works very slow.
I use the SDK like this:
var http = require('http');
var url = require('url');
var AWS = require('aws-sdk');
var lambda = new AWS.Lambda({region: "eu-central-1"});
http.createServer(function (req, res) {
var url = req.url.split('/');
var data1 = url[1];
var data2 = url[2];
if ( ! data1 || ! data2 ) {
res.writeHead(500, {'Content-Type': "application/json" });
res.end("");
return;
}
var params = {
FunctionName: 'myfunc',
InvocationType: "RequestResponse",
Payload: '{"data1": "' + data1 + '", "data2": "' + data2 + '"}',
LogType : 'None'
};
lambda.invoke(params, function(err, data) {
if (err) {
console.log(err, err.stack);
} else {
var result = JSON.parse(data.Payload);
res.writeHead(200, {'Content-Type': "application/json" });
res.end(result.body);
}
});
}).listen(8080);
How can I call the Lambda function fast?
API gateway comes with the CloudFront advantage that's why it will always be faster than invoking the lambda from an external host.
If you deploy the nodejs script to a lambda in the same region and in the same vpc/subnet (if you have configured), it should be faster compared to API Gateway.

AWS Lambda web service calls

I managed to get the following working in Lambda (not throwing errors) but how can I see the actual response json?
var https = require('https');
exports.handler = function (event, context) {
https.get('https://www.quandl.com/api/v3/datasets/FRED/M12015USM144NNBR.json? api_key=XXXXXXXXXXXXXXXX', function (result) {
console.log('Success, with: ' + result.statusCode);
context.done(null);
}).on('error', function (err) {
console.log('Error, with: ' + err.message);
context.done("Failed");
});
};
HMMM... isn't (result) comes back with the object contains with the request response from data event?
Where is body in a nodejs http.get response?