I am currently developing a website that will entirely be a Single Page Application (SPA). I started building the back-end in D and the front-end in AngularJS. I decided after a couple of weeks that Jeff Atwood was right in saying "Storage is cheap, programmers are expensive." Though D is a useful language, it was taking me too long to produce useful RESTful API endpoints, so I decided to make the switch to Flask given my familiarity with it.
In the first iteration of the project I had a simple index.html being served from the same application that the API was running, accessing all my scripts, styles, images, etc... from a CDN. This was a fairly simple CORS setup and a little bit of tweaking in Angular to make it all work.
When I made the switch to Flask I changed the structure of the hosting so that the static content was being served from www.example.com
and the API was accessed from api.example.com
. I figured this wouldn't cause too many issues and it should again just be a simple CORS setup. Unfortunately there was a little more to it than that. I found that when making requests with Angular's $http
provider cookies that were being set were immediately being discareded. I ended up routing all my requests through nginx so that the API was hosted at www.example.com/api
and the cookies were being retained correctly.
The solution was simple in the end. All I needed to do was add the following code to my Angular module .config()
method.
1$httpProvider.defaults.withCredentials = true;
On the server-side initially I was using Flask-CORS but it was frustrating to have to decorate all my REST endpoints (essentially every single route in my application) with @cross_domain()
, so I ended up writing my own basic Flask context processor.
1@app.after_request 2def add_cors_headers(response): 3 response.headers.add('Access-Control-Allow-Origin', 'www.example.com') 4 response.headers.add('Access-Control-Allow-Credentials', 'true') 5 response.headers.add('Access-Control-Allow-Headers', 'Content-Type') 6 return response
The Access-Control-Allow-Credentials
is necessary when specifying withCredentials
on $http
requests.