title: Python Flask CORS - API always allows any origin
body: <p>I've looked through many SO answers, and can't seem to find this issue.  I have a feeling that I'm just missing something obvious.</p>
  
  <p>I have a basic Flask api, and I've implemented both the flask_cors extension and the custom Flask decorator<a href="http://flask.pocoo.org/snippets/56/" rel="nofollow noreferrer"> [@crossdomain from Armin Ronacher]</a>.<a href="http://flask.pocoo.org/snippets/56/" rel="nofollow noreferrer">1</a> (<a href="http://flask.pocoo.org/snippets/56/" rel="nofollow noreferrer">http://flask.pocoo.org/snippets/56/</a>)  Both show the same issue.</p>
  
  <p>This is my example app:</p>
  
  <pre><code>application = Flask(__name__,
              static_url_path='',
              static_folder='static')
  CORS(application)
  application.config['CORS_HEADERS'] = 'Content-Type'
  
  @application.route('/api/v1.0/example')
  @cross_origin(origins=['http://example.com'])
  # @crossdomain(origin='http://example.com')
  def api_example():
    print(request.headers)
    response = jsonify({'key': 'value'})
    print(response.headers)
    return response
  </code></pre>
  
  <p>(EDIT 3 inserted):</p>
  
  <p>When I make a GET request to that endpoint from JS in a browser (from 127.0.0.1), it always returns 200, when I would expect to see:</p>
  
  <pre><code>Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:5000' is therefore not allowed access. The response had HTTP status code 403.
  </code></pre>
  
  <p><s>CURL:</p>
  
  <pre><code>ACCT:ENVIRON user$ curl -i http://127.0.0.1:5000/api/v1.0/example
  HTTP/1.0 200 OK
  Content-Type: application/json
  Content-Length: 20
  Access-Control-Allow-Origin: http://example.com
  Server: Werkzeug/0.11.4 Python/2.7.11
  Date: [datetime]
  
  {
    "key": "value"
  }
  </code></pre>
  
  <p>LOG:</p>
  
  <pre><code>Content-Length: 
  User-Agent: curl/7.54.0
  Host: 127.0.0.1:5000
  Accept: */*
  Content-Type: 
  
  
  Content-Type: application/json
  Content-Length: 20
  
  
  127.0.0.1 - - [datetime] "GET /api/v1.0/example HTTP/1.1" 200 -
  </code></pre>
  
  <p>I'm not even seeing all of the proper headers in the response, and it doesn't seem to care what the origin is in the request.</s></p>
  
  <p>Any ideas what I'm missing?  Thanks!</p>
  
  <hr>
  
  <p>EDIT:</p>
  
  <p>As a side note, looking at the documentation example <a href="https://flask-cors.readthedocs.io/en/v1.7.4/#a-more-complicated-example" rel="nofollow noreferrer">here</a> (<a href="https://flask-cors.readthedocs.io/en/v1.7.4/#a-more-complicated-example" rel="nofollow noreferrer">https://flask-cors.readthedocs.io/en/v1.7.4/#a-more-complicated-example</a>), it shows:</p>
  
  <pre><code>@app.route("/")
  def helloWorld():
      '''
          Since the path '/' does not match the regular expression r'/api/*',
          this route does not have CORS headers set.
      '''
      return '''This view is not exposed over CORS.'''
  </code></pre>
  
  <p>...which is rather interesting since I already have the root path (and others) exposed without any CORS decoration, and they are working fine from any origin.  So it seems that there is something fundamentally wrong with this setup.</p>
  
  <p>Along those lines, the tutorial <a href="https://blog.miguelgrinberg.com/post/designing-a-restful-api-with-python-and-flask" rel="nofollow noreferrer">here</a> (<a href="https://blog.miguelgrinberg.com/post/designing-a-restful-api-with-python-and-flask" rel="nofollow noreferrer">https://blog.miguelgrinberg.com/post/designing-a-restful-api-with-python-and-flask</a>) seems to indicate that Flask apis should naturally be exposed without protection (I would assume that's just since the CORS extension hasn't been applied), but my application is basically just operating like the CORS extension doesn't even exist (other than a few notes in the log that you can see).</p>
  
  <hr>
  
  <p>EDIT 2:</p>
  
  <p>My comments were unclear, so I created three example endpoints on AWS API Gateway with different CORS settings.  They are GET method endpoints that simply return "success":</p>
  
  <p>1)  CORS not enabled (default):</p>
  
  <ul>
  <li>Endpoint: <a href="https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-default" rel="nofollow noreferrer">https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-default</a></li>
  </ul>
  
  <p>Response:</p>
  
  <blockquote>
    <p>XMLHttpRequest cannot load
    <a href="https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-default" rel="nofollow noreferrer">https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-default</a>.
    Response to preflight request doesn't pass access control check: No
    'Access-Control-Allow-Origin' header is present on the requested
    resource. Origin '<a href="http://127.0.0.1:5000" rel="nofollow noreferrer">http://127.0.0.1:5000</a>' is therefore not allowed
    access. The response had HTTP status code 403.</p>
  </blockquote>
  
  <p>2) CORS enabled - Origin Restricted:</p>
  
  <ul>
  <li><p>Access-Control-Allow-Headers: 'Content-Type'</p></li>
  <li><p>Access-Control-Allow-Origin: '<a href="http://example.com" rel="nofollow noreferrer">http://example.com</a>'</p></li>
  <li>Endpoint: <a href="https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-enabled-example" rel="nofollow noreferrer">https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-enabled-example</a></li>
  </ul>
  
  <p>Response:</p>
  
  <blockquote>
    <p>XMLHttpRequest cannot load
    <a href="https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-enabled-example" rel="nofollow noreferrer">https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-enabled-example</a>.
    Response to preflight request doesn't pass access control check: The
    'Access-Control-Allow-Origin' header has a value '<a href="http://example.com" rel="nofollow noreferrer">http://example.com</a>'
    that is not equal to the supplied origin. Origin
    '<a href="http://127.0.0.1:5000" rel="nofollow noreferrer">http://127.0.0.1:5000</a>' is therefore not allowed access.</p>
  </blockquote>
  
  <p>3) CORS enabled - Origin Wildcard:</p>
  
  <ul>
  <li>Access-Control-Allow-Headers: 'Content-Type'</li>
  <li>Access-Control-Allow-Origin: '*'</li>
  <li>Endpoint: <a href="https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-enabled-wildcard" rel="nofollow noreferrer">https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-enabled-wildcard</a></li>
  </ul>
  
  <p>Response:</p>
  
  <pre><code>"success"
  </code></pre>
  
  <p>I'm not that experienced with infrastructure, but my expectation was that enabling the Flask CORS extension would cause my api endpoints to mimic this behavior depending on what I set at the <code>origins=</code> setting.  What am I missing in this Flask setup?</p>
  
  <hr>
  
  <p>SOLUTION EDIT:</p>
  
  <p>Alright, so given that something on my end was obviously not normal, I stripped down my app and re-implemented some very basic APIs for each variation of CORS origin restriction.  I've been using AWS's elastic beanstalk to host the test environment, so I re-uploaded those examples and ran a JS ajax request to each.  It's now working.  </p>
  
  <p>I'm getting the <code>Access-Control-Allow-Origin</code> error on naked endpoints.  It appears that when I configured the app for deployment I was uncommenting <code>CORS(application, resources=r'/api/*')</code>, which was obviously allowing all origins for the naked endpoints!</p>
  
  <p>I'm not sure why my route with a specific restriction (<code>origins=[]</code>) was also allowing everything, but that must have been some type of typo or something small, because it's working now.</p>
  
  <p>A special thanks to <a href="https://stackoverflow.com/users/441757/sideshowbarker">sideshowbarker</a> for all the help!</p>