-1

Here's the workflow:

Get a https link --> write to filesystem --> read from filesystem --> Get the sha256 hash.

It works all good on my local machine running node 10.15.3 But when i initiate a lambda function on AWS, the output is null. Some problem may lie with the readable stream. Here's the code. You can run it directly on your local machine. It will output a sha256 hash as required. If you wish to run on AWS Lambda, Comment/Uncomment as marked.

//Reference: https://stackoverflow.com/questions/11944932/how-to-download-a-file-with-node-js-without-using-third-party-libraries



var https = require('https');
var fs = require('fs');
var crypto = require('crypto')
const url = "https://upload.wikimedia.org/wikipedia/commons/a/a8/TEIDE.JPG"
const dest = "/tmp/doc";
let hexData;


async function writeit(){
  var file = fs.createWriteStream(dest);
  return new Promise((resolve, reject) => {
    var responseSent = false;
    https.get(url, response => {
      response.pipe(file);
      file.on('finish', () =>{
        file.close(() => {
          if(responseSent)  return;
          responseSent = true;
          resolve();
        });
    });

}).on('error', err => {
        if(responseSent)  return;
        responseSent = true;
        reject(err);
    });
  });

}



const readit = async () => {

await writeit();

var readandhex = fs.createReadStream(dest).pipe(crypto.createHash('sha256').setEncoding('hex'))
try {
  readandhex.on('finish', function () {       //MAY BE PROBLEM IS HERE.
    console.log(this.read())
    fs.unlink(dest, () => {});
   })
}
catch (err) {
    console.log(err);
    return err;
}
}



const handler = async() =>{                  //Comment this line to run the code on AWS Lambda
//exports.handler = async (event) => {       //UNComment this line to run the code on AWS Lambda
    try {
        hexData = readit();
    }
    catch (err) {
        console.log(err);
        return err;
    }
    return hexData;
};



handler()                                   //Comment this line to run the code on AWS Lambda

damn
  • 1
  • 1

2 Answers2

0

There can be multiple things that you need check.

  1. Since, the URL you are accessing is a public one, make sure either your lambda is outside VPC or your VPC has NAT Gateway attached with internet access.

  2. /tmp is valid temp directory for lambda, but you may need to create doc folder inside /tmp before using it.

You can check cloud-watch logs for more information on what's going if enabled.

Atul Sharma
  • 9,397
  • 10
  • 38
  • 65
  • 1. I think the default lambda configuration is able to access the https. I placed a dummy print statement after `file.on('finish', ()=>{` and i got it on cloudwatch. 2. doc is a placeholder for any format document. 3. Why the Question is being downvoted? The question has been presented after some initial work and thought and is not just a random opinion question. – damn Dec 25 '20 at 03:06
  • Why @Magic Dev reviewed it as 'No Action Needed'? Is this how stack overflow works? – damn Dec 25 '20 at 03:15
  • did you enabled cloud-watch logs for lambda ? it will help you in pointing to the main issue. – Atul Sharma Dec 25 '20 at 09:57
  • Thanks @Atul but as I've already mentioned in the previous response - I checked it on cloudwatch. – damn Dec 27 '20 at 20:44
0

I've seen this difference in behaviour between local and lambda before.

All async functions return promises. Async functions must be awaited. Calling an async function without awaiting it means execution continues to the next line(s), and potentially out of the calling function.

So your code:

exports.handler = async (event) => {
    try {
        hexData = readit();
    }
    catch (err) {
        console.log(err);
        return err;
    }
    return hexData;
};

readit() is defined as const readit = async () => { ... }. But your handler does not await it. Therefore hexData = readit(); assigns an unresolved promise to hexData, returns it, and the handler exits and the Lambda "completes" without the code of readit() having been executed.

The simple fix then is to await the async function: hexData = await readit();. The reason why it works locally in node is because the node process will wait for promises to resolve before exiting, even though the handler function has already returned. But since Lambda "returns" as soon as the handler returns, unresolved promises remain unresolved. (As an aside, there is no need for the writeit function to be marked async, because it doesn't await anything, and already returns a promise.)

That being said, I don't know promises well, and I barely know anything about events. So there are others things which raise warning flags for me but I'm not sure about them, maybe they're perfectly fine, but I'll raise it here just in case:

file.on('finish' and readandhex.on('finish'. These are both events, and I believe are non-blocking, so why would the handler and therefore lambda wait around for them?

In the first case, it's within a promise and resolve() is called from within the event function, so that may be fine (as I said, I don't know much about these 2 subjects so am not sure) - the important thing is that the code must block at that point until the promise is resolved. If the code can continue execution (i.e. return from writeit()) until the finish event is raised, then it won't work.

The second case is almost certainly going to be a problem because it's just saying that if x event is raised, then do y. There's no promise being awaited, so nothing to block the code, so it will happily continue to the end of the readit() function and then the handler and lambda. Again this is based on the assumption that events are non blocking (in the sense of, a declaration that you want to execute some code on some event, does not wait at that point for that event to be raised).

404
  • 8,022
  • 2
  • 27
  • 47
  • Really appreciate that @404 took time to understand the problem. Before posting my lambda code here i was trying out few things. I went back and checked that in one of the versions i had already put `hexData = await readit()` and it was a null reponse. Anyway, I am also getting used to Promises/Aysnc way. Let me just learn from some examples and then go back and iterate the code again. I will post when I'll get it done. Thanks! – damn Dec 27 '20 at 20:43