Skip to content
This repository has been archived by the owner on Nov 27, 2019. It is now read-only.

Error info and base64 #7

Merged
merged 5 commits into from
May 3, 2019
Merged
Show file tree
Hide file tree
Changes from 4 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
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,16 @@ module.exports.lambda = R((data) => {
// return Promise.reject(new Error('Some error')); // = 500 status and correct errorMessage

// or
// return Promise.reject({ data:false }); // = 500 status and UnkownError name and message
// return Promise.reject({ data:false }); // = 500 status and UnkownError name and message

// or
// throw Error('Some error'); // will be handled as error and status = 500

// or
// const e = new Error('Not found');
// e.statusCode = 404;
// e.headers = { 'NotFoundToken': 12345 }
// throw e;
});
```

Expand Down
24 changes: 19 additions & 5 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ const calculateExecution = endTime =>

const isEmpty = v => v === null || v === undefined;

const extractEventData = (event) => {
if (!event) {
return {};
}

if (event.body) {
const body = event.isBase64Encoded ? Buffer.from(event.body, 'base64').toString() : event.body;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does flag event.isBase64Encoded come from?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any mention of that flag there

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{
    "resource": "Resource path",
    "path": "Path parameter",
    "httpMethod": "Incoming request's method name"
    "headers": {String containing incoming request headers}
    "multiValueHeaders": {List of strings containing incoming request headers}
    "queryStringParameters": {query string parameters }
    "multiValueQueryStringParameters": {List of query string parameters}
    "pathParameters":  {path parameters}
    "stageVariables": {Applicable stage variables}
    "requestContext": {Request context, including authorizer-returned key-value pairs}
    "body": "A JSON string of the request payload."
    "isBase64Encoded": "A boolean flag to indicate if the applicable request payload is Base64-encode"
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also see any json examples in test/ dir

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


return JSON.parse(body);
}

return event.queryStringParameters;
};

/**
* This function is used to handle params of aws request and process them
*
Expand Down Expand Up @@ -42,7 +56,8 @@ function R(...params) {

return async (event, context) => {
const startTime = process.hrtime();
const data = event && event.body ? JSON.parse(event.body) : event.queryStringParameters || {};
const data = extractEventData(event);

let transformed = null;

try {
Expand All @@ -64,7 +79,7 @@ function R(...params) {

const { headers = {}, ...args } = options;

const requestBody = {
return {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
Expand All @@ -83,13 +98,12 @@ function R(...params) {
}),
...args,
};

return requestBody;
} catch (err) {
return {
statusCode: 500,
statusCode: err.statusCode || 500,
headers: {
'Access-Control-Allow-Origin': '*',
...(err.headers ? err.headers : null),
},
body: JSON.stringify({
status: 'error',
Expand Down
47 changes: 47 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -312,4 +312,51 @@ describe('Test handling request', () => {
}
});
});

it('should return custom status code and headers from error', () => {
const event = require('./sample-requests/GET-request-aws.json');

const handler = R((data) => {
expect(data).to.be.deep.equal(
Object.assign(
{},
event.queryStringParameters,
{
path1: 'ok',
},
{
authorizer: undefined,
headers: lowercaseKeys(event.headers),
context: { logStreamName: '1', awsRequestId: '1' },
}
)
);

const error = new Error();
error.statusCode = 405;
error.headers = { 'X-API': '1.0.0' };
cursedcoder marked this conversation as resolved.
Show resolved Hide resolved

throw error;
});

return handler(event, { logStreamName: '1', awsRequestId: '1' }).then((result) => {
expect(result.headers).to.be.an('object');
expect(result.headers).to.have.all.keys('Access-Control-Allow-Origin', 'X-API');
expect(result.headers['X-API']).to.be.equal('1.0.0');
expect(result.statusCode).to.be.equal(405);
});
});

it('should be able to decode base64 incoming request', () => {
const event = require('./sample-requests/GET-request-aws-base64encoded.json');

const handler = R((data) => {
expect(data.some).to.be.eq('json'); // base64 decoded json
});

return handler(event, { logStreamName: '1', awsRequestId: '1' }).then((result) => {
expect(result.headers).to.be.an('object');
expect(result.headers).to.have.all.keys('Access-Control-Allow-Origin');
});
});
});
51 changes: 51 additions & 0 deletions test/sample-requests/GET-request-aws-base64encoded.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"body": "eyAic29tZSI6ICJqc29uIiB9",
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "en-US,en;q=0.8,ru;q=0.6,uk;q=0.4",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "UA",
"Host": "",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3076.0 Safari/537.36",
"Via": "",
"X-Amz-Cf-Id": "",
"X-Amzn-Trace-Id": "",
"X-Forwarded-For": "37.73.233.176, 54.239.171.44",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https",
"upgrade-insecure-requests": "1"
},
"httpMethod": "GET",
"isBase64Encoded": true,
"path": "/first",
"requestContext": {
"accountId": "",
"apiId": "",
"httpMethod": "GET",
"identity": {
"accessKey": null,
"accountId": null,
"apiKey": null,
"caller": null,
"cognitoAuthenticationProvider": null,
"cognitoAuthenticationType": null,
"cognitoIdentityId": null,
"cognitoIdentityPoolId": null,
"sourceIp": "37.73.233.176",
"user": null,
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3076.0 Safari/537.36",
"userArn": null
},
"requestId": "4073894c-2a60-11e7-aa0b-3b98237f23f7",
"resourceId": "",
"resourcePath": "/first",
"stage": "dev"
},
"resource": "/first",
"stageVariables": null
}