CORS config for FaaS
Because I want to be able to deploy random python code easily to my own server, I have setup a "Function as a Service" thing, called faasd (think of it as poor people's AWS lambda). More details on how, why and how it turned out will come in the future. BUT: this explains how to fix the unavoidable headache CORS will give you.
The Faasd server runs in some machine, which is proxied by a Nginx server available at https://faasd.ralsina.me
Apps are just HTML pages somewhere inside either https://ralsina.me or some other similar domain.
What will happen?
You will setup your function, test it out using curl, be happy it works, then set it up in your web app and get an error in the console about how CORS is not allowing the request.
What is CORS and why is it annoying me?
CORS is a way for a service living in a certain URL to say which other URLs are allowed to call it. So, if the app are in, say, https://nombres.ralsina.me and the function lives in https://faas.ralsina.me then the ORIGIN for the app is not the same as the ORIGIN for the function, so this is a "Cross Origin Request" and you are trying to do "Cross Origin Resource Sharing" (CORS) and the browser won't let you.
How do I fix it?
There are a number of fixes you can try, but they all come down to the same two basic approaches:
Make it so the request is not cross-source. To do that, move the function somehow into the same URL as the page, and bob's your uncle.
So, just change the proxy config so nombres.ralsina.me/functions is proxied to the faasd server's /functions and change the page to use a request that is not cross-origin, and that's fixed.
I don't want to do this because I don't want to have to setup the proxy differently for each app.
Have the function return a header that says "Access-Control-Allow-Origin: something". That "something" should be the origin of the request (in our example nombres.ralsina.me) or "*" to say "I don't care".
So, you may say "Fine, I'll just add that header in my response and it will work!". Oh sweet summer child. That will NOT work (at least not in the case of Faasd)
Because web browsers don't just make the request they want and then look at the headers. They do a special preflight request, which is something like "Hey, server, if I were to ask you to give me /functions/whatever from this origin, would you give me a CORS permission or not?"
That request is done using the OPTIONS HTTP method, and Faasd (and, to be honest, most web frameworks) will not process those by passing them to your code.
So, even if your function says CORS is allowed, you still will get CORS errors.
You can see this if you examine your browser's HTTP traffic using the developer tools. There will be an OPTIONS preflight request, and that one doesn't have the header.
So, the easiest thing is to add those in the proxy.
So, in my case, in the proxy's nginx.conf, I had to add this in "the right place":
add_header 'Access-Control-Allow-Origin' '*';
What is the right place will vary depending on how you have configured things. But hey, there you go.