def test_parse_chunked_data(self): # See: https://en.wikipedia.org/wiki/Chunked_transfer_encoding chunked = '4\r\nWiki\r\n5\r\npedia\r\nE\r\n in\r\n\r\nchunks.\r\n0\r\n\r\n' expected = 'Wikipedia in\r\n\r\nchunks.' parsed = parse_chunked_data(chunked) self.assertEqual(parsed.strip(), expected.strip())
def invoke_function(function): """ Invoke an existing function --- operationId: 'invokeFunction' parameters: - name: 'request' in: body """ # function here can either be an arn or a function name arn = func_arn(function) # arn can also contain a qualifier, extract it from there if so m = re.match('(arn:aws:lambda:.*:.*:function:[a-zA-Z0-9-_]+)(:.*)?', arn) if m and m.group(2): qualifier = m.group(2)[1:] arn = m.group(1) else: qualifier = request.args.get('Qualifier') if arn not in arn_to_lambda: return error_response('Function does not exist: %s' % arn, 404, error_type='ResourceNotFoundException') if qualifier and not arn_to_lambda.get(arn).qualifier_exists(qualifier): return error_response('Function does not exist: {0}:{1}'.format(arn, qualifier), 404, error_type='ResourceNotFoundException') data = request.get_data() if data: data = to_str(data) try: data = json.loads(data) except Exception: try: # try to read chunked content data = json.loads(parse_chunked_data(data)) except Exception: return error_response('The payload is not JSON: %s' % data, 415, error_type='UnsupportedMediaTypeException') # Default invocation type is RequestResponse invocation_type = request.environ.get('HTTP_X_AMZ_INVOCATION_TYPE', 'RequestResponse') def _create_response(result, status_code=200): """ Create the final response for the given invocation result """ if isinstance(result, Response): return result details = { 'StatusCode': status_code, 'Payload': result, 'Headers': {} } if isinstance(result, dict): for key in ('StatusCode', 'Payload', 'FunctionError'): if result.get(key): details[key] = result[key] # Try to parse parse payload as JSON payload = details['Payload'] if payload and isinstance(payload, (str, bytes)) and payload[0] in ('[', '{'): try: details['Payload'] = json.loads(details['Payload']) except Exception: pass # Set error headers if details.get('FunctionError'): details['Headers']['X-Amz-Function-Error'] = str(details['FunctionError']) # Construct response object response_obj = details['Payload'] if isinstance(response_obj, (dict, list, bool)) or is_number(response_obj): # Assume this is a JSON response response_obj = jsonify(response_obj) else: response_obj = str(response_obj) details['Headers']['Content-Type'] = 'text/plain' return response_obj, details['StatusCode'], details['Headers'] if invocation_type == 'RequestResponse': result = run_lambda(asynchronous=False, func_arn=arn, event=data, context={}, version=qualifier) return _create_response(result) elif invocation_type == 'Event': run_lambda(asynchronous=True, func_arn=arn, event=data, context={}, version=qualifier) return _create_response('', status_code=202) elif invocation_type == 'DryRun': # Assume the dry run always passes. return _create_response('', status_code=204) return error_response('Invocation type not one of: RequestResponse, Event or DryRun', code=400, error_type='InvalidParameterValueException')
def invoke_function(function): """ Invoke an existing function --- operationId: 'invokeFunction' parameters: - name: 'request' in: body """ # function here can either be an arn or a function name arn = func_arn(function) # arn can also contain a qualifier, extract it from there if so m = re.match('(arn:aws:lambda:.*:.*:function:[a-zA-Z0-9-_]+)(:.*)?', arn) if m and m.group(2): qualifier = m.group(2)[1:] arn = m.group(1) else: qualifier = request.args.get('Qualifier') if arn not in arn_to_lambda: return error_response('Function does not exist: %s' % arn, 404, error_type='ResourceNotFoundException') if qualifier and not arn_to_lambda.get(arn).qualifier_exists(qualifier): return error_response('Function does not exist: {0}:{1}'.format( arn, qualifier), 404, error_type='ResourceNotFoundException') data = request.get_data() if data: data = to_str(data) try: data = json.loads(data) except Exception: try: # try to read chunked content data = json.loads(parse_chunked_data(data)) except Exception: return error_response( 'The payload is not JSON: %s' % data, 415, error_type='UnsupportedMediaTypeException') # Default invocation type is RequestResponse invocation_type = request.environ.get('HTTP_X_AMZ_INVOCATION_TYPE', 'RequestResponse') if invocation_type == 'RequestResponse': result = run_lambda(asynchronous=False, func_arn=arn, event=data, context={}, version=qualifier) if isinstance(result, dict): return jsonify(result) if result: return result return make_response('', 200) elif invocation_type == 'Event': run_lambda(asynchronous=True, func_arn=arn, event=data, context={}, version=qualifier) return make_response('', 202) elif invocation_type == 'DryRun': # Assume the dry run always passes. return make_response('', 204) else: return error_response( 'Invocation type not one of: RequestResponse, Event or DryRun', code=400, error_type='InvalidParameterValueException')