Skip to content
This repository was archived by the owner on Mar 6, 2025. It is now read-only.
Open
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
27 changes: 0 additions & 27 deletions .gitignore

This file was deleted.

1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ for common usecases when using AWS Lambda with Python.
* `cors_headers <http://lambda-decorators.rtfd.io#lambda_decorators.cors_headers>`_ - automatic injection of CORS headers
* `dump_json_body <http://lambda-decorators.rtfd.io#lambda_decorators.dump_json_body>`_ - auto-serialization of http body to JSON
* `load_json_body <http://lambda-decorators.rtfd.io#lambda_decorators.load_json_body>`_ - auto-deserialize of http body from JSON
* `load_json_queryStringParameters <http://lambda-decorators.rtfd.io#lambda_decorators.load_json_queryStringParameters>` - auto-deserialize of http queryStringParameters from JSON
* `json_http_resp <http://lambda-decorators.rtfd.io#lambda_decorators.json_http_resp>`_ - automatic serialization of python object to HTTP JSON response
* `json_schema_validator <http://lambda-decorators.rtfd.io#lambda_decorators.json_schema_validator>`_ - use JSONSchema to validate request&response payloads
* `load_urlencoded_body <http://lambda-decorators.rtfd.io#lambda_decorators.load_urlencoded_body>`_ - auto-deserialize of http body from a querystring encoded body
Expand Down
57 changes: 57 additions & 0 deletions lambda_decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def handler(event, context):
* :func:`cors_headers` - automatic injection of CORS headers
* :func:`dump_json_body` - auto-serialization of http body to JSON
* :func:`load_json_body` - auto-deserialize of http body from JSON
* :func:`load_json_queryStringParameters` - auto-deserialize of http queryStringParameters from JSON
* :func:`json_http_resp` - automatic serialization of python object to HTTP JSON response
* :func:`json_schema_validator` - use JSONSchema to validate request&response payloads
* :func:`load_urlencoded_body` - auto-deserialize of http body from a querystring encoded body
Expand Down Expand Up @@ -144,6 +145,7 @@ def handler(event, context):

import json
import logging
import ast
import boto3
from functools import wraps, update_wrapper

Expand Down Expand Up @@ -489,6 +491,61 @@ def wrapper(event, context):
return wrapper


def load_json_queryStringParameters(handler):
"""
Automatically deserialize event queryStringParameters with ast.literal_eval

Automatically returns a 400 if there is an error while parsing.

Usage::

>>> from lambda_decorators import load_json_queryStringParameters
>>> @load_json_queryStringParameters
... def handler(event, context):
... return event['queryStringParameters']
>>> handler({'queryStringParameters': '{"foo": ["bar1", "None"]'}, object())
{"foo": ["bar1", None]}

"""
@wraps(handler)
def wrapper(event, context):
isObject = lambda x: type(x) in [list, dict, tuple]

def evaluate_items(obj):
def seq(obj):
if isinstance(obj, dict):
keys = obj.keys()
return zip([key for key in keys], [obj[key] for key in keys])
else:
return enumerate(obj)

tuple_flag = isinstance(obj, tuple)
obj = list(obj) if tuple_flag else obj
for i, value in seq(obj):
try:
obj[i] = ast.literal_eval(value)
except ValueError as e:
pass
if isObject(obj[i]):
obj[i] = evaluate_items(obj[i])
obj = tuple(obj) if tuple_flag else obj

return obj

if isinstance(event.get('queryStringParameters'), str):
try:
event['queryStringParameters'] = ast.literal_eval(event['queryStringParameters'])
if isObject(event['queryStringParameters']):
event['queryStringParameters'] = evaluate_items(event['queryStringParameters'])


except Exception as exception:
return {'statusCode': 400, 'body': str(exception) }
return handler(event, context)

return wrapper


def json_schema_validator(request_schema=None, response_schema=None):
"""
Validate your request & response payloads against a JSONSchema.
Expand Down
80 changes: 80 additions & 0 deletions tests/test_load_json_queryStringParameters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from mock import MagicMock

from lambda_decorators import load_json_queryStringParameters


def test_queryStringParameters_empty():
@load_json_queryStringParameters
def hello(example, context):
return example
assert hello({}, MagicMock()) == {}


def test_queryStringParameters_no_parameters():
@load_json_queryStringParameters
def hello(example, context):
return example

query_parameters = '{}'
result = {}
assert hello({'queryStringParameters': query_parameters},
MagicMock()) == {'queryStringParameters': result}


def test_queryStringParameters_1level_str():
@load_json_queryStringParameters
def hello(example, context):
return example

query_parameters = '{"foo": "bar"}'
result = {"foo": "bar"}
assert hello({'queryStringParameters': query_parameters},
MagicMock()) == {'queryStringParameters': result}



def test_queryStringParameters_1level_list():
@load_json_queryStringParameters
def hello(example, context):
return example

query_parameters = '{"foo": ' + str(["bar1", "bar2"]) + '}'
result = {"foo": ["bar1", "bar2"]}
assert hello({'queryStringParameters': query_parameters},
MagicMock()) == {'queryStringParameters': result}


def test_queryStringParameters_2level_dict():
@load_json_queryStringParameters
def hello(example, context):
return example

query_parameters = '{"foo": {"bar1": "baz1", "bar2": "baz2"}}'
result = {"foo": {"bar1": "baz1", "bar2": "baz2"}}
assert hello({'queryStringParameters': query_parameters},
MagicMock()) == {'queryStringParameters': result}

def test_queryStringParameters_2level_list():
@load_json_queryStringParameters
def hello(example, context):
return example

query_parameters = '{"foo": {"bar1": ' + str(["(1.0)", "(1, 2)"]) + ', "bar2": "baz2"}}'
result = {"foo": {"bar1": [(1.0), (1, 2)], "bar2": "baz2"}}
assert hello({'queryStringParameters': query_parameters},
MagicMock()) == {'queryStringParameters': result}


def test_queryStringParameters_2level_None_bool():
@load_json_queryStringParameters
def hello(example, context):
return example

query_parameters = '{"foo": {"bar1": ' + str(["(1.0)", "(1, 2)"]) + ', "bar2": ' + str(("None", "True")) + '}}'
result = {"foo": {"bar1": [(1.0), (1, 2)], "bar2": (None, True)}}
assert hello({'queryStringParameters': query_parameters},
MagicMock()) == {'queryStringParameters': result}