Search code examples
flaskvue.jscorsvue-resource

Vue.js frontend interacting with Flask backend CORS issues due to not allowed preflight headers


I am stuck with the following error message in the Chrome browser:

Failed to load http://localhost:5000/my_endpoint: Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response.

The browser is loading a webpage from a Vue.js frontend app with webpack etc. and vue-resource to perform HTTP requests to the REST backend.

The URL http://localhost:5000/my_endpoint is a HTTP GET/POST endpoint served by a python Flask application.

On the frontend Javascript I have these CORS settings:

import VueResource from 'vue-resource'

Vue.use(VueResource)

Vue.http.options.crossOrigin = true
Vue.http.headers.common['Access-Control-Allow-Origin'] = '*'

On the backend python code in the Flask app I have the following CORS configuration details:

@app.after_request
def add_header(response):
    response.headers['Access-Control-Allow-Origin'] = '*'
    response.headers['Access-Control-Allow-Headers'] = 'Access-Control-Allow-Headers, Origin, X-Requested-With, Content-Type, Accept, Authorization'
    response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS, HEAD'
    response.headers['Access-Control-Expose-Headers'] = '*'
    return response

When performing this HTTP POST request in the Javascript frontend:

this.$http.post("http://localhost:5000/my_endpoint", { my_custom_key: "my custom value"})//, {emulateJSON: true})
  .then((response) => {
    // do stuff
  })

where { my_custom_key: "my custom value"} is the JSON body of the HTTP POST request, then in the Flask backend for some reason I see an HTTP OPTIONS request coming, cf. the Flask log:

127.0.0.1 - - [26/Jun/2018 21:45:53] "OPTIONS /ad HTTP/1.1" 200 -

There must be some sort of back/forth ceremony to honor before being able to retrieve the JSON data from the backend, but I am lost in these details.

On the internet I've seen all sorts of explanations, and I've been playing a bit with the vue-resource configuration details like:

  • adding/removing {emulateJSON: true} to the HTTP POST request
  • adding/removing Vue.http.options.xhr = { withCredentials : true }; to the configuration of Vue.js

but I am not able retrieve the JSON data coming from the backend.

Searching for "CORS" on the Vue.js documentation or on https://github.com/pagekit/vue-resource does not give any information on how to fix these issues with Cross-origin resource sharing (CORS).

How do I get a Vue.js frontend working with a Flask backend on these CORS issues?


Solution

  • The solution was to remove from the frontend: Vue.http.headers.common['Access-Control-Allow-Origin'] = '*' (which actually does not make sense as it's an HTTP header that usually goes into the response from the backend).

    Also to clean up a bit more the backend I found out that response.headers['Access-Control-Expose-Headers'] = '*' was not needed. Probably the other HTTP headers could be more slim, but for now I keep them as they are.