Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wip: add airbnb eslint configuration #13

Merged
merged 6 commits into from
Aug 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"env": {
"jest": true
},
"extends": "airbnb"
}
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,15 @@ AWS Lambda
so that should be used during development. If you have [`nvm`](https://github.com/creationix/nvm)
installed you can run `$ nvm use` to use the version in the `.nvmrc` file.

## Linting

This project uses the [eslint-config-airbnb](https://www.npmjs.com/package/eslint-config-airbnb)
linting configuration. To run eslint execute the lint command:

```sh
$ npm run lint
```

## Testing

Tests are written and executed using [Jest](https://facebook.github.io/jest/). To write a test,
Expand Down
10 changes: 5 additions & 5 deletions bin/errors.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
exports.NOT_FOUND = {
statusCode: 404,
body: `{"message": "Not found"}`
statusCode: 404,
body: '{"message": "Not found"}',
};
exports.SOMETHING_WRONG = {
statusCode: 500,
body: `{"message": "Something went wrong"}`
};
statusCode: 500,
body: '{"message": "Something went wrong"}',
};
48 changes: 24 additions & 24 deletions bin/parseQueryParameters.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
'use strict';

function parseQueryParameters(query){
var format = {};
if ((query.w && parseInt(query.w) !== NaN) || (query.h && parseInt(query.h) !== NaN)){
format.gravity = 'Center';
format.resize = {};
if (query.h && query.h.length > 4){
var test_height_first = query.h.slice(0, query.h.length/2);
var test_height_second = query.h.slice((query.h.length/2));
if (test_height_first == test_height_second){
query.h = test_height_first;
}
}
if (query.f) format.filter = 'Point';
format.resize.width = (query.w && parseInt(query.w) !== NaN) ? parseInt(query.w) : null;
format.resize.height = (query.h && parseInt(query.h) !== NaN) ? parseInt(query.h) : null;
if (format.resize.height !== null && format.resize.width !== null) format.crop = {width:format.resize.width, height:format.resize.height};
}
if (query.f) format.filter = query.f;
if (query.q && parseInt(query.q) !== NaN) format.quality = parseInt(query.q);
if (query.m && parseInt(query.m)!== NaN) format.max = parseInt(query.m);
if (query.b && query.b.match(/[0-9]{1,}x[0-9]{1,}/g)) format.blur = query.b.split('x');
return format;

function parseQueryParameters(query) {
const format = {};
if ((query.w && parseInt(query.w) !== NaN) || (query.h && parseInt(query.h) !== NaN)) {
format.gravity = 'Center';
format.resize = {};
if (query.h && query.h.length > 4) {
const test_height_first = query.h.slice(0, query.h.length / 2);
const test_height_second = query.h.slice((query.h.length / 2));
if (test_height_first == test_height_second) {
query.h = test_height_first;
}
}
if (query.f) format.filter = 'Point';
format.resize.width = (query.w && parseInt(query.w) !== NaN) ? parseInt(query.w) : null;
format.resize.height = (query.h && parseInt(query.h) !== NaN) ? parseInt(query.h) : null;
if (format.resize.height !== null && format.resize.width !== null) format.crop = { width: format.resize.width, height: format.resize.height };
}
if (query.f) format.filter = query.f;
if (query.q && parseInt(query.q) !== NaN) format.quality = parseInt(query.q);
if (query.m && parseInt(query.m) !== NaN) format.max = parseInt(query.m);
if (query.b && query.b.match(/[0-9]{1,}x[0-9]{1,}/g)) format.blur = query.b.split('x');
return format;
}

module.exports = parseQueryParameters;
module.exports = parseQueryParameters;
135 changes: 64 additions & 71 deletions functions/getImage/index.js
Original file line number Diff line number Diff line change
@@ -1,122 +1,115 @@
'use strict';


const AWS = require('aws-sdk');
const s3 = new AWS.S3();

const s3 = new AWS.S3();

const parseQueryParameters = require('../../bin/parseQueryParameters');
const Errors = require('../../bin/errors');

function checkS3(key){
function checkS3(key) {
return new Promise((resolve, reject) => {
s3.headObject({"Bucket":process.env.BUCKET, "Key":key}, function(err, metadata){
s3.headObject({ Bucket: process.env.BUCKET, Key: key }, (err, metadata) => {
if (err && ['NotFound', 'Forbidden'].indexOf(err.code) > -1) return resolve();
else if (err){
let e = Object.assign({}, Errors.SOMETHING_WRONG, {err: err});
else if (err) {
const e = Object.assign({}, Errors.SOMETHING_WRONG, { err });
return reject(e);
}
return resolve(metadata);
});
})
});
}

function getS3(key){
function getS3(key) {
return new Promise((resolve, reject) => {
s3.getObject({"Bucket":process.env.BUCKET, "Key":key}, function(err, data){
s3.getObject({ Bucket: process.env.BUCKET, Key: key }, (err, data) => {
if (err && err.code == 'NotFound') return reject(Errors.NOT_FOUND);
else if (err){
let e = Object.assign({}, Errors.SOMETHING_WRONG, {err: err});
else if (err) {
const e = Object.assign({}, Errors.SOMETHING_WRONG, { err });
return reject(e);
}
let content_type = data.ContentType;
let image = new Buffer(data.Body).toString('base64');
const content_type = data.ContentType;
const image = new Buffer(data.Body).toString('base64');
return resolve({
statusCode:200,
headers:{'Content-Type': content_type},
body:image,
isBase64Encoded: true
statusCode: 200,
headers: { 'Content-Type': content_type },
body: image,
isBase64Encoded: true,
});
});
})
});
}


function stripQueryParams(query){
function stripQueryParams(query) {
query = query || {};
let return_query = {};
const return_query = {};
Object.keys(query).filter(k => ['w', 'h', 'f', 'q', 'm', 'b'].indexOf(k) > -1).sort().forEach(k => return_query[k] = query[k]);
return return_query;
}

function generateKey(image_path, query){
function generateKey(image_path, query) {
let key = image_path;
let keys = Object.keys(query);
if (query && keys.length > 0){
key += '?'
const keys = Object.keys(query);
if (query && keys.length > 0) {
key += '?';
keys.sort().forEach((k, i) => {
key += `${k}=${query[k]}`
if (i !== keys.length-1) key += '&';
key += `${k}=${query[k]}`;
if (i !== keys.length - 1) key += '&';
});
}
if (key[0] == '/') key = key.substring(1);
return key;
}



function resize(data){
const lambda = new AWS.Lambda({region:'eu-west-1'});
return new Promise((resolve, reject) => {
return lambda.invoke({
Payload:JSON.stringify(data),
FunctionName: process.env.RESIZE_LAMBDA
}, (err, result) => {
return (err) ? reject(err) :
(result.FunctionError) ? reject({statusCode:502, body:result.Payload})
: resolve(result);
});
});
function resize(data) {
const lambda = new AWS.Lambda({ region: 'eu-west-1' });
return new Promise((resolve, reject) => lambda.invoke({
Payload: JSON.stringify(data),
FunctionName: process.env.RESIZE_LAMBDA,
}, (err, result) => ((err) ? reject(err) :
(result.FunctionError) ? reject({ statusCode: 502, body: result.Payload })
: resolve(result))));
}



function processImage(image_path, query, destination_path){
function processImage(image_path, query, destination_path) {
image_path = (image_path[0] == '/') ? image_path.substring(1) : image_path;
return checkS3(image_path)
.then(metadata => {
if (!metadata) throw Errors.NOT_FOUND;
console.log('s3 base', image_path, 'exists but we need to process it into', destination_path);
let lambda_data = {
mime_type: metadata.ContentType,
resize_options: parseQueryParameters(query),
asset:image_path,
destination:destination_path,
bucket: process.env.BUCKET,
storage_class: "REDUCED_REDUNDANCY"
};
console.log(JSON.stringify(lambda_data))

return resize(lambda_data)
})
.then(() => {
return getS3(destination_path);
});
.then((metadata) => {
if (!metadata) throw Errors.NOT_FOUND;
console.log('s3 base', image_path, 'exists but we need to process it into', destination_path);
const lambda_data = {
mime_type: metadata.ContentType,
resize_options: parseQueryParameters(query),
asset: image_path,
destination: destination_path,
bucket: process.env.BUCKET,
storage_class: 'REDUCED_REDUNDANCY',
};
console.log(JSON.stringify(lambda_data));

return resize(lambda_data);
})
.then(() => getS3(destination_path));
}

module.exports.handler = (event, context, callback) => {
let query = stripQueryParams(event.queryStringParameters);
let key = generateKey(event.path, query);
const query = stripQueryParams(event.queryStringParameters);
const key = generateKey(event.path, query);
console.log(key);
return checkS3(key)
.then( metadata => {
if (metadata) return getS3(key).then(data => callback(null, data))
else if (Object.keys(query).length > 0) return processImage(event.path, event.queryStringParameters, key).then(data => callback(null, data));
return callback(null, Errors.NOT_FOUND)
})
.catch(e => {
console.log(e);
console.log(e.stack);
callback(null, e)
})
.then((metadata) => {
if (metadata) return getS3(key).then(data => callback(null, data));
else if (Object.keys(query).length > 0) return processImage(event.path, event.queryStringParameters, key).then(data => callback(null, data));
return callback(null, Errors.NOT_FOUND);
})
.catch((e) => {
console.log(e);
console.log(e.stack);
callback(null, e);
});
};

module.exports.stripQueryParams = stripQueryParams;
Expand Down
4 changes: 1 addition & 3 deletions functions/getImage/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ describe('getImage', () => {

describe('stripQueryParams', () => {
test('should filter out supported query params', () => {
'w', 'h', 'f', 'q', 'm', 'b'

const query = {
a: 'filter this',
b: 'keep this',
Expand All @@ -51,5 +49,5 @@ describe('getImage', () => {
};
expect(actual).toEqual(expected);
});
})
});
});
Loading