forked from aws/aws-lambda-nodejs-runtime-interface-client
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInvokeContext.js
More file actions
149 lines (136 loc) · 4.29 KB
/
InvokeContext.js
File metadata and controls
149 lines (136 loc) · 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This module defines the InvokeContext and supporting functions. The
* InvokeContext is responsible for pulling information from the invoke headers
* and for wrapping the Rapid Client object's error and response functions.
*/
'use strict';
const assert = require('assert').strict;
let { setCurrentRequestId, setCurrentTenantId } = require('./LogPatch');
const INVOKE_HEADER = {
ClientContext: 'lambda-runtime-client-context',
CognitoIdentity: 'lambda-runtime-cognito-identity',
ARN: 'lambda-runtime-invoked-function-arn',
AWSRequestId: 'lambda-runtime-aws-request-id',
DeadlineMs: 'lambda-runtime-deadline-ms',
XRayTrace: 'lambda-runtime-trace-id',
TenantId: 'lambda-runtime-aws-tenant-id',
};
module.exports = class InvokeContext {
constructor(headers) {
this.headers = _enforceLowercaseKeys(headers);
}
/**
* The invokeId for this request.
*/
get invokeId() {
let id = this.headers[INVOKE_HEADER.AWSRequestId];
assert.ok(id, 'invocation id is missing or invalid');
return id;
}
/**
* The tenantId for this request.
*/
get tenantId() {
return this.headers[INVOKE_HEADER.TenantId];
}
/**
* Push relevant invoke data into the logging context.
*/
updateLoggingContext() {
setCurrentRequestId(this.invokeId);
setCurrentTenantId(this.tenantId);
}
/**
* Attach all of the relavant environmental and invocation data to the
* provided object.
* This method can throw if the headers are malformed and cannot be parsed.
* @param callbackContext {Object}
* The callbackContext object returned by a call to buildCallbackContext().
* @return {Object}
* The user context object with all required data populated from the headers
* and environment variables.
*/
attachEnvironmentData(callbackContext) {
this._forwardXRay();
return Object.assign(
callbackContext,
this._environmentalData(),
this._headerData(),
);
}
/**
* All parts of the user-facing context object which are provided through
* environment variables.
*/
_environmentalData() {
return {
functionVersion: process.env['AWS_LAMBDA_FUNCTION_VERSION'],
functionName: process.env['AWS_LAMBDA_FUNCTION_NAME'],
memoryLimitInMB: process.env['AWS_LAMBDA_FUNCTION_MEMORY_SIZE'],
logGroupName: process.env['AWS_LAMBDA_LOG_GROUP_NAME'],
logStreamName: process.env['AWS_LAMBDA_LOG_STREAM_NAME'],
};
}
/**
* All parts of the user-facing context object which are provided through
* request headers.
*/
_headerData() {
const deadline = this.headers[INVOKE_HEADER.DeadlineMs];
return {
clientContext: _parseJson(
this.headers[INVOKE_HEADER.ClientContext],
'ClientContext',
),
identity: _parseJson(
this.headers[INVOKE_HEADER.CognitoIdentity],
'CognitoIdentity',
),
invokedFunctionArn: this.headers[INVOKE_HEADER.ARN],
awsRequestId: this.headers[INVOKE_HEADER.AWSRequestId],
tenantId: this.headers[INVOKE_HEADER.TenantId],
getRemainingTimeInMillis: function () {
return deadline - Date.now();
},
};
}
/**
* Forward the XRay header into the environment variable.
*/
_forwardXRay() {
if (this.headers[INVOKE_HEADER.XRayTrace]) {
process.env['_X_AMZN_TRACE_ID'] = this.headers[INVOKE_HEADER.XRayTrace];
} else {
delete process.env['_X_AMZN_TRACE_ID'];
}
}
};
/**
* Parse a JSON string and throw a readable error if something fails.
* @param jsonString {string} - the string to attempt to parse
* @param name {name} - the name to use when describing the string in an error
* @return object - the parsed object
* @throws if jsonString cannot be parsed
*/
function _parseJson(jsonString, name) {
if (jsonString !== undefined) {
try {
return JSON.parse(jsonString);
} catch (err) {
throw new Error(`Cannot parse ${name} as json: ${err.toString()}`);
}
} else {
return undefined;
}
}
/**
* Construct a copy of an object such that all of its keys are lowercase.
*/
function _enforceLowercaseKeys(original) {
return Object.keys(original).reduce((enforced, originalKey) => {
enforced[originalKey.toLowerCase()] = original[originalKey];
return enforced;
}, {});
}