Miserlou/Zappa

Allow Cross-origin Resource Sharing (CORS) Automatically / Configurable

Miserlou opened this issue · 9 comments

I've been doing this manually on the application side, which makes the most sense to me and keeps zappa out of the app and vice versa. Handling it through api gateway is 'convenient' but means that different deployments must all be cors aware, where handling it through the application means it 'just works' regardless of how it is deployed.

I'd like to have control over this on the application side as well. If modify the response headers to allow CORS, everything works as intended when I serve my API on localhost.

However, after a fresh deploy to Lambda with Zappa, the custom response headers are lost when I query the API.

I've also tried to "Enable CORS" on all the resources in API Gateway via the AWS Console (as suggested in the Readme), but that had no effect either.

@collingreen @Miserlou Any pointers as to what I'm missing here? Below is a minimal version of my API that reproduces the problem.

import json
from flask import Flask, Response

app = Flask(__name__)

@app.after_request
def after_request(response):
    response.headers.add('Access-Control-Allow-Origin', '*')
    response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
    response.headers.add('Access-Control-Allow-Methods', 'GET,POST,OPTIONS')
    return response

@app.route('/demo')
def get_benchmark():
    response = {'foo': 'bar'}
    return Response(json.dumps(response, ensure_ascii=False), mimetype='application/json')

if __name__ == '__main__':
    app.run(debug=True)

Hm, just leaving my 2c here: I have the app handling CORS by emitting the headers much as you are, @lsorber -- for me, that did not allow my ReactJS app to talk to lambda via the API Gateway. What I did in addition was Enable CORS Support /at every level of the registered path expressions on the API Gateway app created by Zappa/, and that /did/ work for me.

Thanks for your 2c @zeroaltitude, I went back to the AWS Console and tried to select the Enable CORS on individual HTTP methods, but then it auto-selects the parent resource (i.e., /, /{parameter_1}, ...) before continuing. I did Enable CORS on each of these resources previously, unfortunately with no effect in my case.

I'll also pitch in 2 cents.

First of all, @lsorber - did you also 'publish' the endpoints after changing them? The APIGW interface is terrible and you can make a bunch of changes, CORS in particular, and not actually see any results until you 'publish' them. Have you confirmed that your endpoints are returning the proper headers?

For my end of things, I have several production projects running on lambda via zappa, and I always control CORS in my application (I try to fully decouple the application from the platform when possible). I've done this both by manually adding headers and by using flask-cors -- both have worked for me so far.

@collingreen Thanks for getting back to me. Could you point me to where I can apply this 'publish' action? The below screenshots show what I see in the console when I Enable CORS for a resource (in this case /{parameter_1}).

I haven't yet been able to get the endpoints to return the proper CORS headers on Lambda. Locally, it works fine with flask-cors or the after_request hook above and I do see the Access-Control-Origin header there.

image

image

you have to click the 'stage' I think (not under resources)

I assume because that is not part of the default method_header_types, which can be set in your zappa_settings. Access-Control-Allow-BlahBlahBlah should probably become default header types.

@Miserlou That solved it, thanks!