Skip to content

Commit 9e034ba

Browse files
authored
return CORS headers on API Gateway OPTIONS requests (localstack#418)
1 parent 7ef299a commit 9e034ba

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

localstack/services/apigateway/apigateway_listener.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,19 @@ def get_resource_for_path(path, path_map):
124124
return matches[0]
125125

126126

127+
def get_cors_response(headers):
128+
# TODO: for now we simply return "allow-all" CORS headers, but in the future
129+
# we should implement custom headers for CORS rules, as supported by API Gateway:
130+
# http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html
131+
response = Response()
132+
response.status_code = 200
133+
response.headers['Access-Control-Allow-Origin'] = '*'
134+
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE'
135+
response.headers['Access-Control-Allow-Headers'] = '*'
136+
response._content = ''
137+
return response
138+
139+
127140
class ProxyListenerApiGateway(ProxyListener):
128141

129142
def forward_request(self, method, path, data, headers):
@@ -147,6 +160,11 @@ def forward_request(self, method, path, data, headers):
147160
integration = integrations.get(method, {})
148161
integration = integration.get('methodIntegration')
149162
if not integration:
163+
164+
if method == 'OPTIONS' and 'Origin' in headers:
165+
# default to returning CORS headers if this is an OPTIONS request
166+
return get_cors_response(headers)
167+
150168
return make_error('Unable to find integration for path %s' % path, 404)
151169

152170
uri = integration.get('uri')

tests/integration/test_api_gateway.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import re
12
import json
23
from requests.models import Response
34
from localstack.constants import DEFAULT_REGION
@@ -139,9 +140,19 @@ def forward_request(self, **kwargs):
139140
# create API Gateway and connect it to the HTTP backend
140141
result = connect_api_gateway_to_http('test_gateway2', backend_url, path=API_PATH_HTTP_BACKEND)
141142

142-
# make test request to gateway
143143
url = INBOUND_GATEWAY_URL_PATTERN.format(api_id=result['id'],
144144
stage_name=TEST_STAGE_NAME, path=API_PATH_HTTP_BACKEND)
145+
146+
# make sure CORS headers are present
147+
origin = 'localhost'
148+
result = requests.options(url, headers={'origin': origin})
149+
print(result.status_code)
150+
print(result._content)
151+
assert result.status_code == 200
152+
assert re.match(result.headers['Access-Control-Allow-Origin'].replace('*', '.*'), origin)
153+
assert 'POST' in result.headers['Access-Control-Allow-Methods']
154+
155+
# make test request to gateway
145156
result = requests.get(url)
146157
assert result.status_code == 200
147158
assert to_str(result.content) == '{}'

0 commit comments

Comments
 (0)