Skip to content
This repository has been archived by the owner on Feb 23, 2022. It is now read-only.

Commit

Permalink
Bluehost Screenshot service updates
Browse files Browse the repository at this point in the history
  • Loading branch information
wpscholar committed May 8, 2020
1 parent c914233 commit 18839d4
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 26 deletions.
49 changes: 49 additions & 0 deletions functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const {get} = require('axios');
const crypto = require('crypto');
const {readFileSync} = require('fs');
const {Readable} = require('stream');
const streamToArray = require('stream-to-array');

const lambda = new Lambda();
const s3 = new S3();
Expand Down Expand Up @@ -42,6 +43,18 @@ function bufferToStream(buffer) {
});
}

/**
* Convert a stream to a buffer.
*
* @param {Readable} stream
* @returns {Promise<Buffer>}
*/
async function streamToBuffer(stream) {
const parts = await streamToArray(stream);
const buffers = parts.map(part => Buffer.isBuffer(part) ? part : Buffer.from(part));
return Buffer.concat(buffers);
}

/**
* Get an MD5 hash of a string.
*
Expand Down Expand Up @@ -125,6 +138,24 @@ async function captureScreenshot(url) {
});
}

/**
* Asynchronously generate a screenshot given a URL.
*
* @param {string} bucket
* @param {string} key
* @param {string} url
* @returns {string}
*/
function queueScreenshotGeneration(bucket, key, url) {
const params = {
InvocationType: 'Event',
FunctionName: 'bluehost-url-to-screenshot-on-s3',
Payload: JSON.stringify({bucket, key, url}, null, 2),
};

lambda.invoke(params).send();
}

/**
* Send an image as a response.
*
Expand Down Expand Up @@ -169,6 +200,17 @@ function sendError(message = 'Unable to generate screenshot') {
};
}

function sendRedirect(location, statusCode = 301) {
return {
statusCode: 301,
headers: {
Location: location,
},
body: '',
isBase64Encoded: false,
};
}

/**
* Send a 404 response.
*
Expand All @@ -180,17 +222,24 @@ function send404() {
};
}

function getS3Url(bucket, file) {
return `http://${bucket}.s3.amazonaws.com/${file}`;
}

module.exports = {
base64Decode,
base64Encode,
bufferToStream,
captureScreenshot,
fetchFromS3,
fileExistsOnS3,
getS3Url,
md5,
queueScreenshotGeneration,
send404,
sendError,
sendImage,
sendPlaceholderImage,
sendRedirect,
uploadToS3,
};
19 changes: 16 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"license": "GPL-2.0-or-later",
"dependencies": {
"aws-sdk": "^2.547.0",
"axios": "^0.19.0"
"axios": "^0.19.0",
"stream-to-array": "^2.3.0"
},
"devDependencies": {
"husky": "^4.2.5",
Expand Down
29 changes: 7 additions & 22 deletions screenshot.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
const {
base64Decode,
base64Encode,
bufferToStream,
captureScreenshot,
fetchFromS3,
fileExistsOnS3,
getS3Url,
md5,
send404,
sendImage,
sendPlaceholderImage,
uploadToS3
queueScreenshotGeneration,
sendRedirect,
} = require('./functions');

exports.Screenshot = class {
Expand Down Expand Up @@ -37,21 +31,12 @@ exports.Screenshot = class {
}
}

async persist(base64) {
return await uploadToS3(this.bucket, this.filepath(), bufferToStream(base64Decode(base64)));
}

async fetch() {
try {
const response = await fetchFromS3(this.bucket, this.filepath());
return sendImage(base64Encode(response.Body));
} catch (e) {
try {
return sendImage(await this.persist(await captureScreenshot(this.url)));
} catch (e) {
return sendPlaceholderImage();
}
if (!await this.hasScreenshot()) {
queueScreenshotGeneration(this.bucket, this.filepath(), this.url);
return sendRedirect(getS3Url(this.bucket, 'placeholder.png'), 302);
}
return sendRedirect(getS3Url(this.bucket, this.filepath()));
}

};

0 comments on commit 18839d4

Please sign in to comment.