Bloody CORS and Grafana

Breaking news: see the solution where I asked on community.grafana . Spoiler: add a slash.

There’s a billion queries about this topic. Here’s some notes. I don’t understand the information flow. Maybe writing it down will help.

In our case we have a BROWSER, GRAFANA and an API. The user wants to see a webpage, served by GRAFANA. In the browser there is Javascript or whatever to request some data from the API. But it doesn’t ask the API directly, the BROWSER sends a request via GRAFANA dataproxy, which in turn makes the request to the API. The dataproxy on GRAFANA gets the data and returns it to the BROWSER.

Ok, great, so the BROWSER doesn’t ‘see’ the API, right? Wrong, I think. There is a CORS issue. The browser’s current origin is GRAFANA at (e.g. http://localhost:3000). The API is at (e.g. http://localhost:4000). Note these are considered as different domains (as the port differs). The API (:4000) sees a request from GRAFANA (:3000) which is just a client (not a browser). Confusingly, GRAFANA returns a 404 error as it silently (?) rewrites the url to remove the :4000 so the api request ends up as localhost:3000/my/api/request which doesn’t exit. What? There is a 301 redirect to the wrong place (i.e. without the port).

I don’t get it. But ok, let’s assume Grafana dataproxy is enforcing same-origin like a browser.

Let’s put GRAFANA and API on the same domain via a reverse NGINX proxy:

# sites-enables/mysite.conf
upstream api {
        server localhost:4000;
upstream grafana        {
        server localhost:3000;
server {
        location /api {
                proxy_set_header Host $http_host;
                proxy_pass http://api;
        location / {
                proxy_set_header Host $http_host;
                proxy_pass http://grafana;

Lo and behold, the BROWSER can access the API via GRAFANA. Note we didn’t muck with the Access-Control-Allow-Origin headers. The only different is they are on the same domain.

For our situation, this is ok. But want if API is on a different domain? Let’s put it back, but keep using Nginx. And yep, sure enough, putting api on a port :81 returns the problem. Maybe I we can set the Access-Control-Allow-Origin headers? No, can’t get this to work.

Many it’s not CORS at all, but a problem with dataproxy stripping the port number? There’s a 301 redirect coming from Ngnix or Grafana which doesn’t include the port. Maybe some strict-origin thing? Giving up on this one, just the method above :(.

Leave a Reply

Your email address will not be published. Required fields are marked *