@63klabs/cache-data 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,323 @@
1
+
2
+ const ImmutableObject = require("./ImmutableObject.class");
3
+
4
+ /* ****************************************************************************
5
+ * ClientRequest Data Model
6
+ * ----------------------------------------------------------------------------
7
+ *
8
+ * Provides a class that stores information about the request
9
+ *
10
+ *************************************************************************** */
11
+
12
+ /**
13
+ * Processes the request from the event data. Parses out
14
+ * client details such as ip and user agent. May be extended
15
+ * to provide custom processing for the application.
16
+ */
17
+ class RequestInfo {
18
+
19
+ _requestInfo = null;
20
+ _isValid = false;
21
+
22
+ /**
23
+ * Process the event
24
+ * @param {object} event
25
+ */
26
+ constructor(event) {
27
+ let req = this._gatherRequest(event);
28
+ this._requestInfo = new ImmutableObject( req , true);
29
+ };
30
+
31
+ /**
32
+ * Is the request valid? Validity is set by a series of checks
33
+ * during child class construction.
34
+ * Validity needs to be set by a child class, not this (super)
35
+ * class.
36
+ * @returns {boolean} Whether or not the request is valid.
37
+ */
38
+ isValid() {
39
+ return this._isValid;
40
+ };
41
+
42
+ /**
43
+ * Standard toObject() but by default sensitive information is stripped out.
44
+ * Additional sensitive information may be stripped out by overriding this
45
+ * method. To receive the full object pass true.
46
+ *
47
+ * @param {boolean} full
48
+ * @returns {object} By default sensitive information is stripped out
49
+ */
50
+ toObject(full = false) {
51
+ let obj = this._requestInfo.toObject();
52
+
53
+ if ( !full ) {
54
+ // strip out any fields we don't want in the logs
55
+ if ("client" in obj) {
56
+ if ("allHeaders" in obj.client) { delete obj.client.allHeaders; }
57
+ if ("headers" in obj.client) { delete obj.client.headers; }
58
+ }
59
+ }
60
+
61
+ return obj;
62
+ };
63
+
64
+ /**
65
+ * Gets an object with data. So far the only key available is "client"
66
+ * which contains request fields from the client such as ip, user agent,
67
+ * etc.
68
+ * @param {string} key
69
+ * @returns {object} Data relating to the key
70
+ */
71
+ get(key = "") {
72
+ return this._requestInfo.get(key);
73
+ };
74
+
75
+ /**
76
+ * Get a data object associated with the client request.
77
+ * @param {*} key such as "userAgent", "ip", etc.
78
+ * @returns {*} Return a object ("headers", "userAgent", etc) from the client data
79
+ */
80
+ getClient(key = "") {
81
+ let value = null;
82
+ let clientObj = this.get("client");
83
+
84
+ if ( key !== "" ) {
85
+ if (key in clientObj) { value = clientObj[key]; }
86
+ } else {
87
+ value = clientObj;
88
+ }
89
+
90
+ return value;
91
+ };
92
+
93
+ /**
94
+ * User Agent of client request
95
+ * @returns {string} The user agent string supplied by the client request
96
+ */
97
+ getClientUserAgent() {
98
+ return this.getClient("userAgent");
99
+ };
100
+
101
+ /**
102
+ * IP of client request
103
+ * @returns {string} The IP string from the client request
104
+ */
105
+ getClientIp() {
106
+ return this.getClient("ip");
107
+ };
108
+
109
+ /**
110
+ * @see getClientIp
111
+ * @returns {string}
112
+ */
113
+ getClientIP() {
114
+ return this.getClientIp();
115
+ };
116
+
117
+ /**
118
+ * Referrer of client request
119
+ * @param {boolean} full If true, return the full referrer string supplied by the client request. If false (default), return only the domain from the referrer string (no https:// and no path
120
+ * @returns {string} The referrer string supplied by the client request
121
+ */
122
+ getClientReferrer(full=false) {
123
+ let referrer = this.getClient("referrer");
124
+ if (full) {
125
+ return referrer;
126
+ } else if (referrer !== null && referrer !== undefined) {
127
+ // return only the domain from the referrer string (no https:// and no path)
128
+ // remove 'https://' and 'http://' from the beginning.
129
+ referrer = referrer.replace(/^https?:\/\//, "");
130
+ // remove everything after the first '/'
131
+ referrer = referrer.split("/")[0];
132
+ }
133
+
134
+ return referrer;
135
+ };
136
+
137
+ /**
138
+ * @see getClientReferrer
139
+ * @returns {string} The referrer string supplied by the client request
140
+ */
141
+ getClientReferer(full=false) {
142
+ return this.getClientReferrer(full);
143
+ };
144
+
145
+ /**
146
+ * Origin of client request
147
+ * @returns {string} The origin string supplied by the client request
148
+ */
149
+ getClientOrigin() {
150
+ return this.getClient("origin");
151
+ };
152
+
153
+ /**
154
+ * If client requested data using the if-modified-since header field,
155
+ * the date that was supplied.
156
+ * @returns {string} The if modified since date string supplied by the client request
157
+ */
158
+ getClientIfModifiedSince() {
159
+ return this.getClient("ifModifiedSince");
160
+ };
161
+
162
+ /**
163
+ * If client requested data using an eTag header field, the etag that
164
+ * was supplied.
165
+ * @returns {string} eTag supplied by the client for a match
166
+ */
167
+ getClientIfNoneMatch() {
168
+ return this.getClient("ifNoneMatch");
169
+ };
170
+
171
+ /**
172
+ * Response data format accepted by the client request
173
+ * @returns {string} Response data format accepted by the client request
174
+ */
175
+ getClientAccept() {
176
+ return this.getClient("accept");
177
+ };
178
+
179
+ /**
180
+ *
181
+ * @returns {object} The headers supplied in the client request
182
+ */
183
+ getClientHeaders() {
184
+ return this.getClient("headers");
185
+ };
186
+
187
+ /**
188
+ *
189
+ * @returns {object} The query string parameters supplied in the client request
190
+ */
191
+ getClientParameters() {
192
+ return this.getClient("parameters");
193
+ };
194
+
195
+ /**
196
+ * For POST requests, if a body was supplied in the request.
197
+ * @returns {string} The body supplied in the client request
198
+ */
199
+ getClientBody() {
200
+ return this.getClient("body");
201
+ };
202
+
203
+ /**
204
+ * There may be headers to pass along to an endpoint if our application
205
+ * is working as a proxy.
206
+ * @param {array} headerKeysToProxy An array of strings listing the header keys/fields to proxy
207
+ * @returns {array} Header keys to proxy
208
+ */
209
+ getClientHeadersToProxy(headerKeysToProxy = []) {
210
+ let headers = {};
211
+ let clientHeaders = this.getClientHeaders();
212
+
213
+ if ( headerKeysToProxy.length === 0) {
214
+ headerKeysToProxy = ["accept", "if-modified-since", "if-none-match"];
215
+ }
216
+
217
+ headerKeysToProxy.forEach(function( h ) { headers[h] = clientHeaders[h]; });
218
+
219
+ return headers;
220
+ };
221
+
222
+
223
+ /**
224
+ * Obtain lambda event request details for logging
225
+ * @param {*} event
226
+ * @returns Information about the requesting client including IP and user agent
227
+ */
228
+ _clientRequestInfo (event) {
229
+
230
+ let client = { ip: null, userAgent: null, origin: null, referrer: null, ifModifiedSince: null, ifNoneMatch: null, accept: null, headers: {}, parameters: {}, body: null };
231
+ let identity = {};
232
+ let headers = {};
233
+
234
+ // identity data
235
+ if ( "requestContext" in event && "identity" in event.requestContext && event.requestContext.identity !== null ) {
236
+ identity = event.requestContext.identity;
237
+ }
238
+
239
+ // header data
240
+ if ( "headers" in event && event.headers !== null) {
241
+ // extract just the keys so we can iterate and lowercase
242
+ let hkeys = Object.keys(event.headers);
243
+
244
+ // move each value from event.headers to headers but lowercase the key
245
+ hkeys.forEach( function( k ) { headers[k.toLowerCase()] = event.headers[k]; });
246
+ } else {
247
+ headers = {};
248
+ }
249
+
250
+ client.headers = headers;
251
+
252
+ // set the source IP immediately for logging
253
+ if ( "sourceIp" in identity && identity.sourceIp !== null){
254
+ client.ip = identity.sourceIp;
255
+ }
256
+
257
+ // if there is a user-agent header, set it
258
+ if ( "userAgent" in identity && identity.userAgent !== null ) {
259
+ client.userAgent = identity.userAgent;
260
+ }
261
+
262
+ // if there is an origin header, set it
263
+ if ( headers?.origin) {
264
+ client.origin = headers.origin;
265
+ } // otherwise we'll just leave it as the default ""
266
+
267
+ // if there is a referrer header, set it
268
+ if ( headers?.referer) {
269
+ client.referrer = headers.referer.split("?")[0]; // for privacy we don't want the query string
270
+ } else {
271
+ client.referrer = client.origin;
272
+ }
273
+
274
+ // if there is a if-modified-since header, copy over
275
+ if ( "if-modified-since" in headers && headers['if-modified-since'] !== "" && headers['if-modified-since'] !== null) {
276
+ client.ifModifiedSince = headers['if-modified-since'];
277
+ }
278
+
279
+ // if there is a if-none-match header, set it
280
+ if ( "if-none-match" in headers && headers['if-none-match'] !== "" && headers['if-none-match'] !== null ) {
281
+ client.ifNoneMatch = headers['if-none-match'];
282
+ }
283
+
284
+ // if there is an accept header, set it
285
+ if ( "accept" in headers && headers.accept !== "" && headers.accept !== null ) {
286
+ client.accept = headers['accept'];
287
+ }
288
+
289
+ // if query string parameters were passed, set it
290
+ if ( "queryStringParameters" in event && event.queryStringParameters !== null) {
291
+ client.parameters = event.queryStringParameters
292
+ } else {
293
+ client.parameters = {};
294
+ }
295
+
296
+ // TODO:
297
+ // if body was passed in a post request, set it
298
+ if ( false ) {
299
+ client.body = null;
300
+ }
301
+
302
+ return client;
303
+
304
+ };
305
+
306
+ /**
307
+ *
308
+ * @param {*} event
309
+ * @returns Token and client info of the request. This is the stored object.
310
+ */
311
+ _gatherRequest (event) {
312
+
313
+ let r = {
314
+ client: this._clientRequestInfo(event)
315
+ };
316
+
317
+ return r;
318
+
319
+ };
320
+
321
+ };
322
+
323
+ module.exports = RequestInfo;