def stop(self, quiet=True): try: url = 'http%s://localhost:%s' % ('s' if use_ssl else '', port) requests.verify_ssl = False requests.post(url, headers={HEADER_KILL_SIGNAL: 'kill'}) except Exception: pass
def stop(self, quiet=True): try: url = "http%s://%s:%s" % ("s" if use_ssl else "", LOCALHOST, port) requests.verify_ssl = False requests.post(url, headers={HEADER_KILL_SIGNAL: "kill"}) except Exception: pass
def run_api_gateway_http_integration(self, int_type): test_port = get_free_tcp_port() backend_url = 'http://localhost:%s%s' % (test_port, self.API_PATH_HTTP_BACKEND) # start test HTTP backend proxy = self.start_http_backend(test_port) # create API Gateway and connect it to the HTTP_PROXY/HTTP backend result = self.connect_api_gateway_to_http( int_type, 'test_gateway2', backend_url, path=self.API_PATH_HTTP_BACKEND) url = self.gateway_request_url(api_id=result['id'], stage_name=self.TEST_STAGE_NAME, path=self.API_PATH_HTTP_BACKEND) # make sure CORS headers are present origin = 'localhost' result = requests.options(url, headers={'origin': origin}) self.assertEqual(result.status_code, 200) self.assertTrue( re.match( result.headers['Access-Control-Allow-Origin'].replace( '*', '.*'), origin)) self.assertIn('POST', result.headers['Access-Control-Allow-Methods']) custom_result = json.dumps({'foo': 'bar'}) # make test GET request to gateway result = requests.get(url) self.assertEqual(result.status_code, 200) expected = custom_result if int_type == 'custom' else '{}' self.assertEqual(json.loads(to_str(result.content))['data'], expected) # make test POST request to gateway data = json.dumps({'data': 123}) result = requests.post(url, data=data) self.assertEqual(result.status_code, 200) expected = custom_result if int_type == 'custom' else data self.assertEqual(json.loads(to_str(result.content))['data'], expected) # make test POST request with non-JSON content type data = 'test=123' ctype = 'application/x-www-form-urlencoded' result = requests.post(url, data=data, headers={'content-type': ctype}) self.assertEqual(result.status_code, 200) content = json.loads(to_str(result.content)) headers = CaseInsensitiveDict(content['headers']) expected = custom_result if int_type == 'custom' else data self.assertEqual(content['data'], expected) self.assertEqual(headers['content-type'], ctype) # clean up proxy.stop()
def _test_api_gateway_lambda_proxy_integration(self, fn_name, path): self.create_lambda_function(fn_name) # create API Gateway and connect it to the Lambda proxy backend lambda_uri = aws_stack.lambda_function_arn(fn_name) invocation_uri = 'arn:aws:apigateway:%s:lambda:path/2015-03-31/functions/%s/invocations' target_uri = invocation_uri % (config.DEFAULT_REGION, lambda_uri) result = self.connect_api_gateway_to_http_with_lambda_proxy( 'test_gateway2', target_uri, path=path) api_id = result['id'] path_map = get_rest_api_paths(api_id) _, resource = get_resource_for_path('/lambda/foo1', path_map) # make test request to gateway and check response path = path.replace('{test_param1}', 'foo1') path = path + '?foo=foo&bar=bar&bar=baz' url = self.gateway_request_url( api_id=api_id, stage_name=self.TEST_STAGE_NAME, path=path) data = {'return_status_code': 203, 'return_headers': {'foo': 'bar123'}} result = requests.post(url, data=json.dumps(data), headers={'User-Agent': 'python-requests/testing'}) self.assertEqual(result.status_code, 203) self.assertEqual(result.headers.get('foo'), 'bar123') self.assertIn('set-cookie', result.headers) parsed_body = json.loads(to_str(result.content)) self.assertEqual(parsed_body.get('return_status_code'), 203) self.assertDictEqual(parsed_body.get('return_headers'), {'foo': 'bar123'}) self.assertDictEqual(parsed_body.get('queryStringParameters'), {'foo': 'foo', 'bar': ['bar', 'baz']}) request_context = parsed_body.get('requestContext') source_ip = request_context['identity'].pop('sourceIp') self.assertTrue(re.match(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$', source_ip)) self.assertEqual(request_context['path'], '/' + self.TEST_STAGE_NAME + '/lambda/foo1') self.assertEqual(request_context.get('stageVariables'), None) self.assertEqual(request_context['accountId'], TEST_AWS_ACCOUNT_ID) self.assertEqual(request_context['resourceId'], resource.get('id')) self.assertEqual(request_context['stage'], self.TEST_STAGE_NAME) self.assertEqual(request_context['identity']['userAgent'], 'python-requests/testing') self.assertEqual(request_context['httpMethod'], 'POST') self.assertEqual(request_context['protocol'], 'HTTP/1.1') self.assertIn('requestTimeEpoch', request_context) self.assertIn('requestTime', request_context) result = requests.delete(url, data=json.dumps(data)) self.assertEqual(result.status_code, 204) # send message with non-ASCII chars body_msg = '🙀 - 参よ' result = requests.post(url, data=json.dumps({'return_raw_body': body_msg})) self.assertEqual(to_str(result.content), body_msg)
def poll_and_send_messages(params): while True: try: event = EVENT_QUEUE.get(block=True, timeout=None) event = event.to_dict() endpoint = "%s/events" % API_ENDPOINT.rstrip("/") requests.post(endpoint, json=event) except Exception: # silently fail, make collection of usage data as non-intrusive as possible time.sleep(1)
def poll_and_send_messages(params): while True: try: event = EVENT_QUEUE.get(block=True, timeout=None) event = event.to_dict() endpoint = '%s/events' % API_ENDPOINT requests.post(endpoint, json=event) except Exception: # silently fail, make collection of usage data as non-intrusive as possible time.sleep(1)
def forward_to_fallback_url(func_arn, data): """ If LAMBDA_FALLBACK_URL is configured, forward the invocation of this non-existing Lambda to the configured URL. """ if not config.LAMBDA_FALLBACK_URL: return None if config.LAMBDA_FALLBACK_URL.startswith('dynamodb://'): table_name = urlparse( config.LAMBDA_FALLBACK_URL.replace('dynamodb://', 'http://')).netloc dynamodb = aws_stack.connect_to_service('dynamodb') item = { 'id': { 'S': short_uid() }, 'timestamp': { 'N': str(now_utc()) }, 'payload': { 'S': str(data) } } aws_stack.create_dynamodb_table(table_name, partition_key='id') dynamodb.put_item(TableName=table_name, Item=item) return '' if re.match(r'^https?://.+', config.LAMBDA_FALLBACK_URL): response = safe_requests.post(config.LAMBDA_FALLBACK_URL, data) return response.content raise ClientError('Unexpected value for LAMBDA_FALLBACK_URL: %s' % config.LAMBDA_FALLBACK_URL)
def test_api_gateway_sqs_integration_with_event_source(self): # create target SQS stream aws_stack.create_sqs_queue(self.TEST_SQS_QUEUE) # create API Gateway and connect it to the target queue result = connect_api_gateway_to_sqs('test_gateway4', stage_name=self.TEST_STAGE_NAME, queue_arn=self.TEST_SQS_QUEUE, path=self.API_PATH_DATA_INBOUND) # create event source for sqs lambda processor self.create_lambda_function(self.TEST_LAMBDA_SQS_HANDLER_NAME) add_event_source(self.TEST_LAMBDA_SQS_HANDLER_NAME, aws_stack.sqs_queue_arn(self.TEST_SQS_QUEUE), True) # generate test data test_data = {'spam': 'eggs & beans'} url = self.gateway_request_url(api_id=result['id'], stage_name=self.TEST_STAGE_NAME, path=self.API_PATH_DATA_INBOUND) result = requests.post(url, data=json.dumps(test_data)) self.assertEqual(result.status_code, 200) parsed_json = xmltodict.parse(result.content) result = parsed_json['SendMessageResponse']['SendMessageResult'] body_md5 = result['MD5OfMessageBody'] self.assertEqual(body_md5, 'b639f52308afd65866c86f274c59033f')
def test_api_gateway_kinesis_integration(self): # create target Kinesis stream aws_stack.create_kinesis_stream(self.TEST_STREAM_KINESIS_API_GW) # create API Gateway and connect it to the target stream result = self.connect_api_gateway_to_kinesis('test_gateway1', self.TEST_STREAM_KINESIS_API_GW) # generate test data test_data = {'records': [ {'data': '{"foo": "bar1"}'}, {'data': '{"foo": "bar2"}'}, {'data': '{"foo": "bar3"}'} ]} url = self.gateway_request_url( api_id=result['id'], stage_name=self.TEST_STAGE_NAME, path=self.API_PATH_DATA_INBOUND ) # list Kinesis streams via API Gateway result = requests.get(url) result = json.loads(to_str(result.content)) self.assertIn('StreamNames', result) # post test data to Kinesis via API Gateway result = requests.post(url, data=json.dumps(test_data)) result = json.loads(to_str(result.content)) self.assertEqual(result['FailedRecordCount'], 0) self.assertEqual(len(result['Records']), len(test_data['records'])) # clean up kinesis = aws_stack.connect_to_service('kinesis') kinesis.delete_stream(StreamName=self.TEST_STREAM_KINESIS_API_GW)
def test_api_gateway_kinesis_integration(): # create target Kinesis stream aws_stack.create_kinesis_stream(TEST_STREAM_KINESIS_API_GW) # create API Gateway and connect it to the target stream result = connect_api_gateway_to_kinesis('test_gateway1', TEST_STREAM_KINESIS_API_GW) # generate test data test_data = { 'records': [{ 'data': '{"foo": "bar1"}' }, { 'data': '{"foo": "bar2"}' }, { 'data': '{"foo": "bar3"}' }] } url = INBOUND_GATEWAY_URL_PATTERN.format(api_id=result['id'], stage_name=TEST_STAGE_NAME, path=API_PATH_DATA_INBOUND) result = requests.post(url, data=json.dumps(test_data)) result = json.loads(to_str(result.content)) assert result['FailedRecordCount'] == 0 assert len(result['Records']) == len(test_data['records'])
def test_http_invocation_with_apigw_proxy(self, create_lambda_function): lambda_name = f"test_lambda_{short_uid()}" lambda_resource = "/api/v1/{proxy+}" lambda_path = "/api/v1/hello/world" lambda_request_context_path = "/" + TEST_STAGE_NAME + lambda_path lambda_request_context_resource_path = lambda_resource create_lambda_function( func_name=lambda_name, handler_file=TEST_LAMBDA_PYTHON, libs=TEST_LAMBDA_LIBS, ) # create API Gateway and connect it to the Lambda proxy backend lambda_uri = aws_stack.lambda_function_arn(lambda_name) target_uri = f"arn:aws:apigateway:{aws_stack.get_region()}:lambda:path/2015-03-31/functions/{lambda_uri}/invocations" result = testutil.connect_api_gateway_to_http_with_lambda_proxy( "test_gateway2", target_uri, path=lambda_resource, stage_name=TEST_STAGE_NAME, ) api_id = result["id"] url = path_based_url(api_id=api_id, stage_name=TEST_STAGE_NAME, path=lambda_path) result = safe_requests.post( url, data=b"{}", headers={"User-Agent": "python-requests/testing"}) content = json.loads(result.content) assert lambda_path == content["path"] assert lambda_resource == content["resource"] assert lambda_request_context_path == content["requestContext"]["path"] assert lambda_request_context_resource_path == content[ "requestContext"]["resourcePath"]
def test_api_gateway_lambda_proxy_integration(): # create lambda function zip_file = testutil.create_lambda_archive(load_file(TEST_LAMBDA_PYTHON), get_content=True, libs=TEST_LAMBDA_LIBS, runtime=LAMBDA_RUNTIME_PYTHON27) testutil.create_lambda_function(func_name=TEST_LAMBDA_PROXY_BACKEND, zip_file=zip_file, runtime=LAMBDA_RUNTIME_PYTHON27) # create API Gateway and connect it to the Lambda proxy backend lambda_uri = aws_stack.lambda_function_arn(TEST_LAMBDA_PROXY_BACKEND) target_uri = 'arn:aws:apigateway:%s:lambda:path/2015-03-31/functions/%s/invocations' % ( DEFAULT_REGION, lambda_uri) result = connect_api_gateway_to_http_with_lambda_proxy( 'test_gateway2', target_uri, path=API_PATH_LAMBDA_PROXY_BACKEND) # make test request to gateway and check response path = API_PATH_LAMBDA_PROXY_BACKEND.replace('{test_param1}', 'foo1') url = INBOUND_GATEWAY_URL_PATTERN.format(api_id=result['id'], stage_name=TEST_STAGE_NAME, path=path) data = {'return_status_code': 203, 'return_headers': {'foo': 'bar123'}} result = requests.post(url, data=json.dumps(data)) assert result.status_code == 203 assert result.headers.get('foo') == 'bar123' parsed_body = json.loads(to_str(result.content)) assert parsed_body.get('return_status_code') == 203 assert parsed_body.get('return_headers') == {'foo': 'bar123'} assert parsed_body.get('pathParameters') == {'test_param1': 'foo1'} result = requests.delete(url, data=json.dumps(data)) assert result.status_code == 404
def test_api_gateway_sqs_integration_with_event_source(self): # create target SQS stream aws_stack.create_sqs_queue(self.TEST_SQS_QUEUE) # create API Gateway and connect it to the target queue result = connect_api_gateway_to_sqs('test_gateway4', stage_name=self.TEST_STAGE_NAME, queue_arn=self.TEST_SQS_QUEUE, path=self.API_PATH_DATA_INBOUND) # create event source for sqs lambda processor self.create_lambda_function(self.TEST_LAMBDA_HANDLER_NAME) add_event_source(self.TEST_LAMBDA_HANDLER_NAME, aws_stack.sqs_queue_arn(self.TEST_SQS_QUEUE), True) # generate test data test_data = {'spam': 'eggs & beans'} url = INBOUND_GATEWAY_URL_PATTERN.format( api_id=result['id'], stage_name=self.TEST_STAGE_NAME, path=self.API_PATH_DATA_INBOUND) result = requests.post(url, data=json.dumps(test_data)) self.assertEqual(result.status_code, 200) parsed_content = parseString(result.content) root = parsed_content.documentElement.childNodes[1] attr_md5 = root.childNodes[1].lastChild.nodeValue body_md5 = root.childNodes[3].lastChild.nodeValue self.assertEqual(attr_md5, '4141913720225b35a836dd9e19fc1e55') self.assertEqual(body_md5, 'b639f52308afd65866c86f274c59033f')
def test_api_gateway_sqs_integration(self): # create target SQS stream aws_stack.create_sqs_queue(self.TEST_SQS_QUEUE) # create API Gateway and connect it to the target queue result = connect_api_gateway_to_sqs('test_gateway4', stage_name=self.TEST_STAGE_NAME, queue_arn=self.TEST_SQS_QUEUE, path=self.API_PATH_DATA_INBOUND) # generate test data test_data = {'spam': 'eggs'} url = INBOUND_GATEWAY_URL_PATTERN.format( api_id=result['id'], stage_name=self.TEST_STAGE_NAME, path=self.API_PATH_DATA_INBOUND) result = requests.post(url, data=json.dumps(test_data)) self.assertEqual(result.status_code, 200) messages = aws_stack.sqs_receive_message( self.TEST_SQS_QUEUE)['Messages'] self.assertEqual(len(messages), 1) self.assertEqual(json.loads(base64.b64decode(messages[0]['Body'])), test_data)
def test_api_gateway_http_integration(): test_port = 12123 backend_url = 'http://localhost:%s%s' % (test_port, API_PATH_HTTP_BACKEND) # create target HTTP backend def listener(**kwargs): response = Response() response.status_code = 200 response._content = json.dumps( kwargs['data']) if kwargs['data'] else '{}' return response proxy = GenericProxy(test_port, update_listener=listener) proxy.start() # create API Gateway and connect it to the HTTP backend result = connect_api_gateway_to_http('test_gateway2', backend_url, path=API_PATH_HTTP_BACKEND) # make test request to gateway url = INBOUND_GATEWAY_URL_PATTERN.format(api_id=result['id'], stage_name=TEST_STAGE_NAME, path=API_PATH_HTTP_BACKEND) result = requests.get(url) assert result.status_code == 200 assert to_str(result.content) == '{}' data = {"data": 123} result = requests.post(url, data=json.dumps(data)) assert result.status_code == 200 assert json.loads(to_str(result.content)) == data # clean up proxy.stop()
def poll_and_send_messages(params): while True: try: message = EVENT_QUEUE.get(block=True, timeout=None) message = str(message) endpoint = '%s/events' % API_ENDPOINT result = requests.post(endpoint, data=message) except Exception as e: # silently fail, make collection of usage data as non-intrusive as possible time.sleep(1)
def test_search(self, opensearch_endpoint, opensearch_document_path): index = "/".join(opensearch_document_path.split("/")[:-2]) # force the refresh of the index after the document was added, so it can appear in search response = requests.post(f"{opensearch_endpoint}/_refresh", headers=COMMON_HEADERS) assert response.ok search = {"query": {"match": {"last_name": "Fett"}}} response = requests.get(f"{index}/_search", data=json.dumps(search), headers=COMMON_HEADERS) assert ( "I'm just a simple man" in response.text ), f"search unsuccessful({response.status_code}): {response.text}"
def test_api_gateway_http_integration(self): test_port = 12123 backend_url = 'http://localhost:%s%s' % (test_port, self.API_PATH_HTTP_BACKEND) # create target HTTP backend class TestListener(ProxyListener): def forward_request(self, **kwargs): response = Response() response.status_code = 200 response._content = kwargs.get('data') or '{}' return response proxy = GenericProxy(test_port, update_listener=TestListener()) proxy.start() # create API Gateway and connect it to the HTTP backend result = self.connect_api_gateway_to_http( 'test_gateway2', backend_url, path=self.API_PATH_HTTP_BACKEND ) url = INBOUND_GATEWAY_URL_PATTERN.format( api_id=result['id'], stage_name=self.TEST_STAGE_NAME, path=self.API_PATH_HTTP_BACKEND ) # make sure CORS headers are present origin = 'localhost' result = requests.options(url, headers={'origin': origin}) self.assertEqual(result.status_code, 200) self.assertTrue(re.match(result.headers['Access-Control-Allow-Origin'].replace('*', '.*'), origin)) self.assertIn('POST', result.headers['Access-Control-Allow-Methods']) # make test request to gateway result = requests.get(url) self.assertEqual(result.status_code, 200) self.assertEqual(to_str(result.content), '{}') data = {'data': 123} result = requests.post(url, data=json.dumps(data)) self.assertEqual(result.status_code, 200) self.assertEqual(json.loads(to_str(result.content)), data) # clean up proxy.stop()
def test_http_invocation_with_apigw_proxy(self): lambda_name = "test_lambda_%s" % short_uid() lambda_resource = "/api/v1/{proxy+}" lambda_path = "/api/v1/hello/world" lambda_request_context_path = "/" + TEST_STAGE_NAME + lambda_path lambda_request_context_resource_path = lambda_resource # create lambda function testutil.create_lambda_function( handler_file=TEST_LAMBDA_PYTHON, libs=TEST_LAMBDA_LIBS, func_name=lambda_name, ) # create API Gateway and connect it to the Lambda proxy backend lambda_uri = aws_stack.lambda_function_arn(lambda_name) invocation_uri = "arn:aws:apigateway:%s:lambda:path/2015-03-31/functions/%s/invocations" target_uri = invocation_uri % (aws_stack.get_region(), lambda_uri) result = testutil.connect_api_gateway_to_http_with_lambda_proxy( "test_gateway2", target_uri, path=lambda_resource, stage_name=TEST_STAGE_NAME, ) api_id = result["id"] url = gateway_request_url(api_id=api_id, stage_name=TEST_STAGE_NAME, path=lambda_path) result = safe_requests.post( url, data=b"{}", headers={"User-Agent": "python-requests/testing"}) content = json.loads(result.content) self.assertEqual(lambda_path, content["path"]) self.assertEqual(lambda_resource, content["resource"]) self.assertEqual(lambda_request_context_path, content["requestContext"]["path"]) self.assertEqual( lambda_request_context_resource_path, content["requestContext"]["resourcePath"], ) # clean up testutil.delete_lambda_function(lambda_name)
def test_api_gateway_sqs_integration_with_event_source(self): # create target SQS stream queue_name = 'queue-%s' % short_uid() queue_url = aws_stack.create_sqs_queue(queue_name)['QueueUrl'] # create API Gateway and connect it to the target queue result = connect_api_gateway_to_sqs('test_gateway4', stage_name=self.TEST_STAGE_NAME, queue_arn=queue_name, path=self.API_PATH_DATA_INBOUND) # create event source for sqs lambda processor self.create_lambda_function(self.TEST_LAMBDA_SQS_HANDLER_NAME) event_source_data = { 'FunctionName': self.TEST_LAMBDA_SQS_HANDLER_NAME, 'EventSourceArn': aws_stack.sqs_queue_arn(queue_name), 'Enabled': True } add_event_source(event_source_data) # generate test data test_data = {'spam': 'eggs & beans'} url = gateway_request_url(api_id=result['id'], stage_name=self.TEST_STAGE_NAME, path=self.API_PATH_DATA_INBOUND) result = requests.post(url, data=json.dumps(test_data)) self.assertEqual(result.status_code, 200) parsed_json = xmltodict.parse(result.content) result = parsed_json['SendMessageResponse']['SendMessageResult'] body_md5 = result['MD5OfMessageBody'] self.assertEqual(body_md5, 'b639f52308afd65866c86f274c59033f') # clean up sqs_client = aws_stack.connect_to_service('sqs') sqs_client.delete_queue(QueueUrl=queue_url) lambda_client = aws_stack.connect_to_service('lambda') lambda_client.delete_function( FunctionName=self.TEST_LAMBDA_SQS_HANDLER_NAME)
def test_api_gateway_kinesis_integration(): # create target Kinesis stream aws_stack.create_kinesis_stream(TEST_STREAM_KINESIS_API_GW) # create API Gateway and connect it to the target stream result = connect_api_gateway_to_kinesis('test_gateway1', TEST_STREAM_KINESIS_API_GW) # generate test data test_data = {'records': [ {'data': '{"foo": "bar1"}'}, {'data': '{"foo": "bar2"}'}, {'data': '{"foo": "bar3"}'} ]} url = INBOUND_GATEWAY_URL_PATTERN.format(api_id=result['id'], stage_name=TEST_STAGE_NAME, path=API_PATH_DATA_INBOUND) result = requests.post(url, data=json.dumps(test_data)) result = json.loads(to_str(result.content)) assert result['FailedRecordCount'] == 0 assert len(result['Records']) == len(test_data['records'])
def test_api_gateway_http_integration(): test_port = 12123 backend_url = 'http://localhost:%s%s' % (test_port, API_PATH_HTTP_BACKEND) # create target HTTP backend class TestListener(ProxyListener): def forward_request(self, **kwargs): response = Response() response.status_code = 200 response._content = kwargs.get('data') or '{}' return response proxy = GenericProxy(test_port, update_listener=TestListener()) proxy.start() # create API Gateway and connect it to the HTTP backend result = connect_api_gateway_to_http('test_gateway2', backend_url, path=API_PATH_HTTP_BACKEND) url = INBOUND_GATEWAY_URL_PATTERN.format(api_id=result['id'], stage_name=TEST_STAGE_NAME, path=API_PATH_HTTP_BACKEND) # make sure CORS headers are present origin = 'localhost' result = requests.options(url, headers={'origin': origin}) assert result.status_code == 200 assert re.match(result.headers['Access-Control-Allow-Origin'].replace('*', '.*'), origin) assert 'POST' in result.headers['Access-Control-Allow-Methods'] # make test request to gateway result = requests.get(url) assert result.status_code == 200 assert to_str(result.content) == '{}' data = {'data': 123} result = requests.post(url, data=json.dumps(data)) assert result.status_code == 200 assert json.loads(to_str(result.content)) == data # clean up proxy.stop()
def test_api_gateway_lambda_proxy_integration(): # create lambda function zip_file = testutil.create_lambda_archive(load_file(TEST_LAMBDA_PYTHON), get_content=True, libs=TEST_LAMBDA_LIBS, runtime=LAMBDA_RUNTIME_PYTHON27) testutil.create_lambda_function(func_name=TEST_LAMBDA_PROXY_BACKEND, zip_file=zip_file, runtime=LAMBDA_RUNTIME_PYTHON27) # create API Gateway and connect it to the Lambda proxy backend lambda_uri = aws_stack.lambda_function_arn(TEST_LAMBDA_PROXY_BACKEND) target_uri = 'arn:aws:apigateway:%s:lambda:path/2015-03-31/functions/%s/invocations' % (DEFAULT_REGION, lambda_uri) result = connect_api_gateway_to_http_with_lambda_proxy('test_gateway2', target_uri, path=API_PATH_LAMBDA_PROXY_BACKEND) # make test request to gateway and check response path = API_PATH_LAMBDA_PROXY_BACKEND.replace('{test_param1}', 'foo1') url = INBOUND_GATEWAY_URL_PATTERN.format(api_id=result['id'], stage_name=TEST_STAGE_NAME, path=path) data = {'return_status_code': 203, 'return_headers': {'foo': 'bar123'}} result = requests.post(url, data=json.dumps(data)) assert result.status_code == 203 assert result.headers.get('foo') == 'bar123' parsed_body = json.loads(to_str(result.content)) assert parsed_body.get('return_status_code') == 203 assert parsed_body.get('return_headers') == {'foo': 'bar123'} assert parsed_body.get('pathParameters') == {'test_param1': 'foo1'}
def test_api_gateway_lambda_proxy_integration(self): # create lambda function zip_file = testutil.create_lambda_archive( load_file(TEST_LAMBDA_PYTHON), get_content=True, libs=TEST_LAMBDA_LIBS, runtime=LAMBDA_RUNTIME_PYTHON27) testutil.create_lambda_function( func_name=self.TEST_LAMBDA_PROXY_BACKEND, zip_file=zip_file, runtime=LAMBDA_RUNTIME_PYTHON27) # create API Gateway and connect it to the Lambda proxy backend lambda_uri = aws_stack.lambda_function_arn( self.TEST_LAMBDA_PROXY_BACKEND) invocation_uri = 'arn:aws:apigateway:%s:lambda:path/2015-03-31/functions/%s/invocations' target_uri = invocation_uri % (DEFAULT_REGION, lambda_uri) result = self.connect_api_gateway_to_http_with_lambda_proxy( 'test_gateway2', target_uri, path=self.API_PATH_LAMBDA_PROXY_BACKEND) api_id = result['id'] path_map = get_rest_api_paths(api_id) _, resource = get_resource_for_path('/lambda/foo1', path_map) # make test request to gateway and check response path = self.API_PATH_LAMBDA_PROXY_BACKEND.replace( '{test_param1}', 'foo1') path = path + '?foo=foo&bar=bar&bar=baz' url = INBOUND_GATEWAY_URL_PATTERN.format( api_id=api_id, stage_name=self.TEST_STAGE_NAME, path=path) data = {'return_status_code': 203, 'return_headers': {'foo': 'bar123'}} result = requests.post( url, data=json.dumps(data), headers={'User-Agent': 'python-requests/testing'}) self.assertEqual(result.status_code, 203) self.assertEqual(result.headers.get('foo'), 'bar123') parsed_body = json.loads(to_str(result.content)) self.assertEqual(parsed_body.get('return_status_code'), 203) self.assertDictEqual(parsed_body.get('return_headers'), {'foo': 'bar123'}) self.assertDictEqual(parsed_body.get('pathParameters'), {'test_param1': 'foo1'}) self.assertDictEqual(parsed_body.get('queryStringParameters'), { 'foo': 'foo', 'bar': ['bar', 'baz'] }) request_context = parsed_body.get('requestContext') source_ip = request_context['identity'].pop('sourceIp') self.assertTrue( re.match(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$', source_ip)) self.assertEqual(request_context['path'], '/lambda/foo1') self.assertEqual(request_context['accountId'], TEST_AWS_ACCOUNT_ID) self.assertEqual(request_context['resourceId'], resource.get('id')) self.assertEqual(request_context['stage'], self.TEST_STAGE_NAME) self.assertEqual(request_context['identity']['userAgent'], 'python-requests/testing') result = requests.delete(url, data=json.dumps(data)) self.assertEqual(result.status_code, 404)
def test_api_gateway_http_integration(self): test_port = 12123 backend_url = 'http://localhost:%s%s' % (test_port, self.API_PATH_HTTP_BACKEND) # create target HTTP backend class TestListener(ProxyListener): def forward_request(self, **kwargs): response = Response() response.status_code = 200 result = { 'data': kwargs.get('data') or '{}', 'headers': dict(kwargs.get('headers')) } response._content = json.dumps(json_safe(result)) return response proxy = GenericProxy(test_port, update_listener=TestListener()) proxy.start() # create API Gateway and connect it to the HTTP backend result = self.connect_api_gateway_to_http( 'test_gateway2', backend_url, path=self.API_PATH_HTTP_BACKEND) url = self.gateway_request_url(api_id=result['id'], stage_name=self.TEST_STAGE_NAME, path=self.API_PATH_HTTP_BACKEND) # make sure CORS headers are present origin = 'localhost' result = requests.options(url, headers={'origin': origin}) self.assertEqual(result.status_code, 200) self.assertTrue( re.match( result.headers['Access-Control-Allow-Origin'].replace( '*', '.*'), origin)) self.assertIn('POST', result.headers['Access-Control-Allow-Methods']) # make test GET request to gateway result = requests.get(url) self.assertEqual(result.status_code, 200) self.assertEqual(json.loads(to_str(result.content))['data'], '{}') # make test POST request to gateway data = json.dumps({'data': 123}) result = requests.post(url, data=data) self.assertEqual(result.status_code, 200) self.assertEqual(json.loads(to_str(result.content))['data'], data) # make test POST request with non-JSON content type data = 'test=123' ctype = 'application/x-www-form-urlencoded' result = requests.post(url, data=data, headers={'content-type': ctype}) self.assertEqual(result.status_code, 200) content = json.loads(to_str(result.content)) headers = CaseInsensitiveDict(content['headers']) self.assertEqual(content['data'], data) self.assertEqual(headers['content-type'], ctype) # clean up proxy.stop()
def test_step_function_integrations(self): client = aws_stack.connect_to_service('apigateway') sfn_client = aws_stack.connect_to_service('stepfunctions') lambda_client = aws_stack.connect_to_service('lambda') state_machine_name = 'test' state_machine_def = { 'Comment': 'Hello World example', 'StartAt': 'step1', 'States': { 'step1': { 'Type': 'Task', 'Resource': '__tbd__', 'End': True }, } } fn_name = 'test-stepfunctions-apigw' # create state machine testutil.create_lambda_function(handler_file=TEST_LAMBDA_ECHO_FILE, func_name=fn_name, runtime=LAMBDA_RUNTIME_PYTHON36) resp = lambda_client.list_functions() role_arn = aws_stack.role_arn('sfn_role') definition = clone(state_machine_def) lambda_arn_1 = aws_stack.lambda_function_arn(fn_name) definition['States']['step1']['Resource'] = lambda_arn_1 definition = json.dumps(definition) sm_arn = 'arn:aws:states:%s:%s:stateMachine:%s' \ % (aws_stack.get_region(), TEST_AWS_ACCOUNT_ID, state_machine_name) sfn_client.create_state_machine(name=state_machine_name, definition=definition, roleArn=role_arn) rest_api = client.create_rest_api(name='test', description='test') resources = client.get_resources(restApiId=rest_api['id']) client.put_method(restApiId=rest_api['id'], resourceId=resources['items'][0]['id'], httpMethod='POST', authorizationType='NONE') client.put_integration( restApiId=rest_api['id'], resourceId=resources['items'][0]['id'], httpMethod='POST', integrationHttpMethod='POST', type='AWS', uri='arn:aws:apigateway:%s:states:action/StartExecution' % aws_stack.get_region(), requestTemplates={ 'application/json': """ #set($data = $util.escapeJavaScript($input.json('$'))) {"input": "$data","stateMachineArn": "%s"} """ % sm_arn }, ) client.create_deployment(restApiId=rest_api['id'], stageName='dev') url = gateway_request_url(api_id=rest_api['id'], stage_name='dev', path='/') test_data = {'test': 'test-value'} resp = requests.post(url, data=json.dumps(test_data)) self.assertEqual(resp.status_code, 200) self.assertIn('executionArn', resp.content.decode()) self.assertIn('startDate', resp.content.decode()) client.delete_integration( restApiId=rest_api['id'], resourceId=resources['items'][0]['id'], httpMethod='POST', ) client.put_integration( restApiId=rest_api['id'], resourceId=resources['items'][0]['id'], httpMethod='POST', integrationHttpMethod='POST', type='AWS', uri='arn:aws:apigateway:%s:states:action/StartExecution' % aws_stack.get_region(), ) test_data = { 'input': json.dumps({'test': 'test-value'}), 'name': 'MyExecution', 'stateMachineArn': '{}'.format(sm_arn) } resp = requests.post(url, data=json.dumps(test_data)) self.assertEqual(resp.status_code, 200) self.assertIn('executionArn', resp.content.decode()) self.assertIn('startDate', resp.content.decode()) # Clean up lambda_client.delete_function(FunctionName=fn_name) sfn_client.delete_state_machine(stateMachineArn=sm_arn) client.delete_rest_api(restApiId=rest_api['id'])