Grafana custom datasource - CORS and proxy

I’m trying to develop a custom plugin which can request a resource in the web (based on configuration). I’ve found this url mentioning Grafana proxy: Access data source from an app type plugin page

My understanding of it is I can use build-in proxy to make such a call, e.g.

  import { getBackendSrv } from '@grafana/runtime';
  async query(options: DataQueryRequest<HttpQuery>): Promise<DataQueryResponse> {
        getBackendSrv()
        .datasourceRequest({
          url: 'https://google.com',
          method: 'GET',
        })
        .then((data: any) => {
                console.log('DATA done, done, done', data);
        });
        
       return {};
  }

The problem is I still get a CORS error:

new-dashboard-copy?orgId=1:1 Access to fetch at 'https://google.com/' from origin 'http://grafana.staged-by-discourse.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Am I missing something here? What do I need to do to achieve this?

Hello @sathokh

I use similar way to get data from my external server. Please take a look at code:

The only difference I see - I use backendSrv from datasource constructor.

Regards,
V.

hey can you explain how you d this?

Hi @ahmedanis

Happy to help, may you be more specific with a question?

V.

hi I am having the same issue has there ever been a resolve?

Hey there, I think you need to reach out to the team that build the backend API that you wanted to fetch the API using getBackendSrv method. The team need to set the http header Access-Control-Allow-Origin to true. This, in my opinion, is the backend issue. Hope this helps.

Hey i have a similar problem can anyone check my code ?


let url = "myrq"
            const result = await getBackendSrv().datasourceRequest({
                method: "POST",
                url: url,
                headers: {
                    "Connection" : "keep-alive",
                    "Content-Type" : "application/json",
                    "Access-Control-Allow-Origin": "*",
                    'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
                    "Access-Control-Allow-Credentials": "true"
                },
                data: {
                    data
            })
            return result;

@nicolasdossantos248 these headers won’t heave effect in the request side. The headers you are trying to use here should be the ones returning in the API side.

in my api side i put this in the web config file :

<httpProtocol>
			<customHeaders>
				<add name="Access-Control-Allow-Origin" value="*" />
				<add name="Access-Control-Allow-Headers" value="Content-Type, Authorization" />
				<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
			</customHeaders>
		</httpProtocol>

Hi @nicolasdossantos248 I really can’t help you with the setup in your API side. The headers look correct to me. Verify using the browser devtools that the request from grafana to the API is receiving the headers you are sending.

I have a solution :

In the program.cs put this :

services.AddCors(options =>
            {
                options.AddPolicy("AllowedCors",
                    policy =>
                    {
                        policy.WithOrigins("*")
                                .AllowAnyMethod()
                                .AllowAnyHeader();
                                
                    });
            });

And where you have the request put this :
[EnableCors("AllowedCors")]