Grafana plugin - CORS issue with REST API

I’m currently developing grafana plugin using Angular-1 and ES6, retrieving data from REST API and representing them in grafana. The problem is that as far as grafana plugin is working within the browser, it sends ajax calls to our REST API and they are blocked:

No ‘Access-Control-Allow-Origin’ header is present on the requested resource. The response had HTTP status code 401.

We were required to solve this issue without adding that header on the REST API side. One simple solution was to use corsproxy.

But I’m curios to know whether there is some other way to use REST API within grafana. If I set up some datasource to my plugin, will it work as a kind of backend or my calls to REST API will still be AJAX calls?

Grafana has a proxy feature for data sources so that any calls to a data source go through the backend server and one of the reasons to do this is to add cors headers.

When configuring a data source you can choose between proxy and direct mode. If you use direct mode, then ajax calls are made directly from the Grafana frontend to the data source and you can get CORS errors.

Thanks for your response, one thing is still unclear for me, sorry I’m new to grafana.
Currently, I’m using embedded angular $http service to make a call to REST API.
As I understood from your post I have to configure datasource for my plugin, which will proxy these calls. But what is unclear for me:

  1. From the very name “datasource” I’m thinking it should store some data, however I don’t need any. I’m just making a call, parsing response and immediately render it.
  2. Which one (I see multiple available datasources) is it better to choose?

A data source in Grafana contains the following:

  • connection configuration (connection string etc.) and this is saved in the Grafana database.
  • code for the query editor (every data source has its own specialized query editor)
  • code that makes a call to the database and parses the response. Read more about the four methods a data source should implement here.

That is hard to answer. Depends on your needs. It is not clear to me if you just want to use an existing data source or if you want to build your own.

That is hard to answer. Depends on your needs. It is not clear to me if you just want to use an existing data source or if you want to build your own.

Currently, I don’t use any datasource at all, so all I need from the datasource it actually adding CORS headers to all the http requests (I use GET only). That’s it.

I don’t think I understand what you are developing. That would be a lot of overhead just to get a CORS header.

The main reason to build a data source is to be able to use your data in any Grafana panel (graph, table, singlestat etc.). Data sources return data in the time series format which nearly all panels can visualize.

Are you building a custom panel plugin or a custom data source?

I’m building a custom panel plugin. I took this clock plugin as example:

As you can see it’s Angular-1 + ES6. clock_ctrl.js is a kind of entry point where you store all the logic. I have the same file [my_name]_ctrl.js where I’m making http calls to the existing external REST API. I use for it embedded angular $http service which applies callback, where I parse response and render (using angular 2-ways data binding) it in module.html file.
As you can see I don’t use datasource as well, however I use corsproxy (corsproxy-https - npm) to add headers.
Now I have a task to replace somehow this corsproxy with some internal grafana things.

If you are making direct ajax calls from a plugin then there is nothing in the Grafana codebase that can help you with CORS. That is just general web development. A server has to add CORS headers - you cannot do it with frontend javascript.

If instead of making direct AJAX calls, you want to make a Grafana data source plugin (to be able to visualize time series data from your external REST API) then you will get the proxying for free. But that proxying is only done for predefined calls - queries, annotation queries and template variable queries.

Does it mean I won’t be able to use calls based on user input? For example, I’m rendering some input field and after client clicks “submit” I send http get with input as parameter

Not sure I understand. I thought that you were already calling your api from a panel? It is really hard to give any concrete advice without knowing any details of what you are building.

You can of course use direct Ajax calls if that is what makes sense for your custom panel. If (and only if), your api is returning time series data (a timestamp, a value and metric name) or data that could be parsed into time series data then you could write a custom data source that can be then used for any Grafana panel.

If direct Ajax calls is what makes most sense, then you are going to have to figure out a way to handle CORS. The Grafana front end code cannot help you there. It is a browser security feature and there is no way around it - a server has to add CORS headers (which is what corsproxy-http does).

Hello,

Have you find a way to use Grafana’s own proxy ?
I’m struggling to find a way to do it !

Regard

AFAIK you can use NGINX as a reverse proxy and avoid CORS on it (e.g. link)

Thank you for your answer, I used grafana internal proxy to handle it

I found that using the grafana datasource url enables the option to leverage the Grafana proxy server.
the requests uses this format:
/api/datasources/proxy/1/query/<your-api-route>
then have your API side listen on /query/

1 Like

If problem is actual yet - U can check this repo:

Can you please help me how to configure this to call api’s of grafana?