Skip to content

Commit 81c896c

Browse files
authored
Merge pull request #10 from Moesif/add-support-for-pfv-2
Add: Support for payload format version 2
2 parents b588bc8 + 57e701a commit 81c896c

File tree

5 files changed

+190
-72
lines changed

5 files changed

+190
-72
lines changed

event.json

Lines changed: 0 additions & 60 deletions
This file was deleted.

eventV1.json

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
{
2+
"version": "1.0",
3+
"resource": "/my/path",
4+
"path": "/my/path",
5+
"httpMethod": "GET",
6+
"headers": {
7+
"header1": "value1",
8+
"header2": "value2"
9+
},
10+
"multiValueHeaders": {
11+
"header1": [
12+
"value1"
13+
],
14+
"header2": [
15+
"value1",
16+
"value2"
17+
]
18+
},
19+
"queryStringParameters": {
20+
"parameter1": "value1",
21+
"parameter2": "value"
22+
},
23+
"multiValueQueryStringParameters": {
24+
"parameter1": [
25+
"value1",
26+
"value2"
27+
],
28+
"parameter2": [
29+
"value"
30+
]
31+
},
32+
"requestContext": {
33+
"accountId": "123456789012",
34+
"apiId": "id",
35+
"authorizer": {
36+
"claims": null,
37+
"scopes": null
38+
},
39+
"domainName": "id.execute-api.us-east-1.amazonaws.com",
40+
"domainPrefix": "id",
41+
"extendedRequestId": "request-id",
42+
"httpMethod": "GET",
43+
"identity": {
44+
"accessKey": null,
45+
"accountId": null,
46+
"caller": null,
47+
"cognitoAuthenticationProvider": null,
48+
"cognitoAuthenticationType": null,
49+
"cognitoIdentityId": null,
50+
"cognitoIdentityPoolId": null,
51+
"principalOrgId": null,
52+
"sourceIp": "IP",
53+
"user": null,
54+
"userAgent": "user-agent",
55+
"userArn": null,
56+
"clientCert": {
57+
"clientCertPem": "CERT_CONTENT",
58+
"subjectDN": "www.example.com",
59+
"issuerDN": "Example issuer",
60+
"serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
61+
"validity": {
62+
"notBefore": "May 28 12:30:02 2019 GMT",
63+
"notAfter": "Aug 5 09:36:04 2021 GMT"
64+
}
65+
}
66+
},
67+
"path": "/my/path",
68+
"protocol": "HTTP/1.1",
69+
"requestId": "id=",
70+
"requestTime": "04/Mar/2020:19:15:17 +0000",
71+
"requestTimeEpoch": 1583349317135,
72+
"resourceId": null,
73+
"resourcePath": "/my/path",
74+
"stage": "$default"
75+
},
76+
"pathParameters": null,
77+
"stageVariables": null,
78+
"body": "Hello from Lambda!",
79+
"isBase64Encoded": false
80+
}
81+

eventV2.json

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
{
2+
"version": "2.0",
3+
"routeKey": "$default",
4+
"rawPath": "/my/path",
5+
"rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
6+
"cookies": [
7+
"cookie1",
8+
"cookie2"
9+
],
10+
"headers": {
11+
"header1": "value1",
12+
"header2": "value1,value2"
13+
},
14+
"queryStringParameters": {
15+
"parameter1": "value1,value2",
16+
"parameter2": "value"
17+
},
18+
"requestContext": {
19+
"accountId": "123456789012",
20+
"apiId": "api-id",
21+
"authentication": {
22+
"clientCert": {
23+
"clientCertPem": "CERT_CONTENT",
24+
"subjectDN": "www.example.com",
25+
"issuerDN": "Example issuer",
26+
"serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
27+
"validity": {
28+
"notBefore": "May 28 12:30:02 2019 GMT",
29+
"notAfter": "Aug 5 09:36:04 2021 GMT"
30+
}
31+
}
32+
},
33+
"authorizer": {
34+
"jwt": {
35+
"claims": {
36+
"claim1": "value1",
37+
"claim2": "value2"
38+
},
39+
"scopes": [
40+
"scope1",
41+
"scope2"
42+
]
43+
}
44+
},
45+
"domainName": "id.execute-api.us-east-1.amazonaws.com",
46+
"domainPrefix": "id",
47+
"http": {
48+
"method": "POST",
49+
"path": "/my/path",
50+
"protocol": "HTTP/1.1",
51+
"sourceIp": "IP",
52+
"userAgent": "agent"
53+
},
54+
"requestId": "id",
55+
"routeKey": "$default",
56+
"stage": "$default",
57+
"time": "12/Mar/2020:19:03:58 +0000",
58+
"timeEpoch": 1583348638390
59+
},
60+
"body": "Hello from Lambda",
61+
"pathParameters": {
62+
"parameter1": "value1"
63+
},
64+
"isBase64Encoded": false,
65+
"stageVariables": {
66+
"stageVariable1": "value1",
67+
"stageVariable2": "value2"
68+
}
69+
}
70+

moesif_aws_lambda/middleware.py

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def __init__(self, handler):
6464
self.DEBUG = self.moesif_options.get('DEBUG', False)
6565
self.event = None
6666
self.context = None
67+
self.payload_version = None
6768

6869
# Intialized the client
6970
if os.environ.get("MOESIF_APPLICATION_ID"):
@@ -75,12 +76,17 @@ def clear_state(self):
7576
"""Function to clear state of local variable"""
7677
self.event = None
7778
self.context = None
79+
self.payload_version = None
7880
self.event_req = None
7981
self.metadata = None
8082
self.session_token = None
8183
self.user_id = None
8284
self.company_id = None
8385

86+
def is_payload_format_version_1_0(cls, payload_format_version):
87+
"""Function to check if the payload format version is 1.0 (old) or 2.0 (new) """
88+
return payload_format_version == "1.0"
89+
8490
def get_user_id(self, event, context):
8591
"""Function to fetch UserId"""
8692
username = None
@@ -116,14 +122,20 @@ def get_company_id(self, event, context):
116122
print(e)
117123
return company_id
118124

119-
def build_uri(self, event):
125+
def build_uri(self, event, payload_format_version_1_0):
120126

121-
uri = event['headers'].get('X-Forwarded-Proto', event['headers'].get('x-forwarded-proto', 'http')) + '://' + event['headers'].get('Host', event['headers'].get('host', 'localhost')) + event.get('path', '/')
127+
uri = event['headers'].get('X-Forwarded-Proto', event['headers'].get('x-forwarded-proto', 'http')) + '://' + event['headers'].get('Host', event['headers'].get('host', 'localhost'))
122128

123-
if event.get('multiValueQueryStringParameters', {}):
124-
uri = uri + '?' + urlencode(event['multiValueQueryStringParameters'], doseq=True)
125-
elif event.get('queryStringParameters', {}):
126-
uri = uri + '?' + urlencode(event['queryStringParameters'])
129+
if payload_format_version_1_0:
130+
uri = uri + event.get('path', '/')
131+
if event.get('multiValueQueryStringParameters', {}):
132+
uri = uri + '?' + urlencode(event['multiValueQueryStringParameters'], doseq=True)
133+
elif event.get('queryStringParameters', {}):
134+
uri = uri + '?' + urlencode(event['queryStringParameters'])
135+
else:
136+
uri = uri + event.get('rawPath', '/')
137+
if event.get('rawQueryString', {}):
138+
uri = uri + '?' + event['rawQueryString']
127139
return uri
128140

129141
def process_body(self, body_wrapper):
@@ -159,16 +171,24 @@ def before(self, event, context):
159171
# Clear the state of the local variables
160172
self.clear_state()
161173

174+
# Get the payload format version
175+
# https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html
176+
self.payload_version = event.get('version', '1.0')
177+
162178
# Set/Save event and context for use Skip Event function
163179
self.event = event
164180
self.context = context
165181

166182
# Request Method
167-
request_verb = event.get('httpMethod')
183+
if self.is_payload_format_version_1_0(self.payload_version):
184+
request_verb = event.get('httpMethod')
185+
else:
186+
request_verb = event.get('requestContext', {}).get('http', {}).get('method')
168187
if request_verb is None:
169188
print('MOESIF: [before] AWS Lambda trigger must be a Load Balancer or API Gateway See https://docs.aws.amazon.com/lambda/latest/dg/services-alb.html or https://docs.aws.amazon.com/lambda/latest/dg/with-on-demand-https.html.')
170189
self.event = None
171190
self.context = None
191+
self.payload_version = None
172192
return event, context
173193

174194
# Request headers
@@ -182,9 +202,13 @@ def before(self, event, context):
182202
print(e)
183203

184204
# Request Time
185-
epoch = event and event.get('request_context', {}).get('requestTimeEpoch')
205+
if self.is_payload_format_version_1_0(self.payload_version):
206+
epoch = event and event.get('requestContext', {}).get('requestTimeEpoch')
207+
else:
208+
epoch = event and event.get('requestContext', {}).get('timeEpoch')
186209
if epoch is not None:
187-
request_time = datetime.utcfromtimestamp(epoch)
210+
# Dividing by 1000 to convert from ms to seconds and `.0` to preserve millisecond precision
211+
request_time = datetime.utcfromtimestamp(epoch/1000.0)
188212
else:
189213
request_time = datetime.utcnow()
190214

@@ -257,11 +281,14 @@ def before(self, event, context):
257281
print(e)
258282

259283
# IpAddress
260-
ip_address = event.get('requestContext', {}).get('identity', {}).get('sourceIp', None)
284+
if self.is_payload_format_version_1_0(self.payload_version):
285+
ip_address = event.get('requestContext', {}).get('identity', {}).get('sourceIp', None)
286+
else:
287+
ip_address = event.get('requestContext', {}).get('http', {}).get('sourceIp', None)
261288

262289
# Event Request Object
263290
self.event_req = EventRequestModel(time = request_time.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3],
264-
uri = self.build_uri(event),
291+
uri = self.build_uri(event, self.is_payload_format_version_1_0(self.payload_version)),
265292
verb = request_verb,
266293
api_version = api_version,
267294
ip_address = self.client_ip.get_client_address(event['headers'], ip_address),

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
# Versions should comply with PEP440. For a discussion on single-sourcing
2929
# the version across setup.py and the project code, see
3030
# https://packaging.python.org/en/latest/single_source_version.html
31-
version='1.0.7',
31+
version='1.0.8',
3232

3333
description='Moesif Middleware to automatically log API calls from AWS Lambda functions',
3434
long_description=long_description,

0 commit comments

Comments
 (0)