How to set CORS headers on public API

Solved!
AndresSilva
Level 2
How to set CORS headers on public API

Hi!

I have created an API in Dataiku, with the endpoint being a Python Function.

I am able to call the API from python using both a) dataiku's dataikuapi, and b) using a plain HTTP requests.

However, due to some company policies, I'll have to call the API from Javascript, with a cross-origin request, and thus will need to setup a CORS header on the API.

Here it is mentioned that is is posible to do so in Dataiku. However I haven't found any additional documentation on that regard.

Could anyone please give me further information on how this would be done?

Thank you very much!

0 Kudos
1 Solution
Andrey
Dataiker Alumni

Hi @AndresSilva ,

Thanks for clarification, I can confirm that CORS filters are only available for the design node public API defined here:

https://doc.dataiku.com/dss/api/8.0/rest/

 

Since you're trying to reach the API node this feature is not available.

 

However you may overcome this limitation by modifying the ./install-support/nginx.conf in the API node datadir.

 

inside of it you'll find a section like

 

 

location /public/ {
            proxy_pass http://127.0.0.1:11811/public/;
        }

 

 

 

so next to it you paste the following code:

 

 

set $cors '';
        if ($http_origin ~ '.*') {
            set $cors 'true';
        }


        location /public-cors/ {
            if ($cors = 'true') {
                add_header 'Access-Control-Allow-Origin' "$http_origin" always;
                add_header 'Access-Control-Allow-Credentials' 'true' always;
                add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
                add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;
            }

            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' "$http_origin" always;
                add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;

                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain charset=UTF-8';
                add_header 'Content-Length' 0;
                return 204;
            }
            proxy_pass http://127.0.0.1:11811/public/;
        }

 

 

 

of course, the port 11811 should be modified to match whatever you have in your config. Also I'm using the pattern that matches all of the http origins (.*) you may want to restrict it.

 

After doing that and restarting DSS, in addition to the standard /public/* endpoints you'll also get a /public-cors/* that will add the CORS headers to the responses

 

Regards

Andrey Avtomonov
R&D Engineer @ Dataiku

View solution in original post

0 Kudos
6 Replies
Andrey
Dataiker Alumni

Hi @AndresSilva ,

Public API CORS headers are available under Administration -> Misc -> Public API CORS headers

Regards,

Andrey Avtomonov
R&D Engineer @ Dataiku
0 Kudos
AndresSilva
Level 2
Author

@Andrey, thank you very much for your help.

We just tried it but unfortunately, with no luck. Maybe if I share with you additional information you could help us.

We are setting up a web app in Dataiku. In it we are launching a request to an API on the same project.

The Api is working correctly (we have called it from Python and it works as expected).

In our web app, we are calling the Api with the following code:

function dataikuREST() {
    url = 'apiNodeIP_And_Port/public/api/v1/Service_ID/Endpoint/run/?var1=SOMETHING'
    var apiKey = 'ourApiKey';
    // We use fetch API (https://developer.mozilla.org/fr/docs/Web/API/Fetch_API/Using_Fetch)
    fetch(url, {
        headers: {
            'Authorization': 'Basic ' + btoa(apiKey + ':' + '')
        }
    })
    .then(response => {
        if (response.ok) {
                response.json().then(
                    result => console.log("Success")
                );
            } else {
                response.json().then(
                    err => console.log(err.message)
                );
            }
    });
}

(Note: The same get requests works ok in Python.)

However, our DesignNode server is different from our AppiNode server, thus, we are getting this error:

Access to fetch at 'apiNodeIP_And_Port/public/api/v1/Service_ID/Endpoint/run/?var1=SOMETHING' from origin 'http://designNodeIP' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: 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.

 

Thanks to your help we then went into 'Administration -> Misc -> Public API CORS headers' and tried to set it up, as follows:

CORS headers.png

(Note: We are trying with '*' first, just to get it to work. Then we would change it back to the DesignNode IP).

However, we are still getting the same 'http://designNodeIP' has been blocked by CORS policy' error. 

Any ideas?

Thank you very much!

0 Kudos
Andrey
Dataiker Alumni

Hi @AndresSilva ,

Thanks for clarification, I can confirm that CORS filters are only available for the design node public API defined here:

https://doc.dataiku.com/dss/api/8.0/rest/

 

Since you're trying to reach the API node this feature is not available.

 

However you may overcome this limitation by modifying the ./install-support/nginx.conf in the API node datadir.

 

inside of it you'll find a section like

 

 

location /public/ {
            proxy_pass http://127.0.0.1:11811/public/;
        }

 

 

 

so next to it you paste the following code:

 

 

set $cors '';
        if ($http_origin ~ '.*') {
            set $cors 'true';
        }


        location /public-cors/ {
            if ($cors = 'true') {
                add_header 'Access-Control-Allow-Origin' "$http_origin" always;
                add_header 'Access-Control-Allow-Credentials' 'true' always;
                add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
                add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;
            }

            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' "$http_origin" always;
                add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;

                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain charset=UTF-8';
                add_header 'Content-Length' 0;
                return 204;
            }
            proxy_pass http://127.0.0.1:11811/public/;
        }

 

 

 

of course, the port 11811 should be modified to match whatever you have in your config. Also I'm using the pattern that matches all of the http origins (.*) you may want to restrict it.

 

After doing that and restarting DSS, in addition to the standard /public/* endpoints you'll also get a /public-cors/* that will add the CORS headers to the responses

 

Regards

Andrey Avtomonov
R&D Engineer @ Dataiku
0 Kudos
rafael_rosado97
Level 4

Hello, @Andrey 

I remember that I had the same problem. I set the same parameters but it did not work.
Should I make any other configuration, for example, on CentOs etc/nginx/nginx.conf file?

 

Thanks!!

0 Kudos

Rafael please start a new thread. This old thread is from 2020 and has been solved already. 

0 Kudos
rafael_rosado97
Level 4

Thank you, @Turribeach .
I already posted it here

0 Kudos