Closed JoarGjersund closed 3 years ago
Hi @JoarGjersund, we currently don't support CORS and don't recommend making API calls from a web page.
A current workaround for this is to run the browser with CORS check disabled.
This will work as long as you're the only user. Anyone else who hasn't disabled that option won't be able to get the results. Pretty sure you don't expect users to disable it and you're aware of the security concerns that come with it.
In case you still need to work around the issue, I'd recommend deploying something like cors-anywhere
to one of your servers. Not the best solution but it's been super helpful to have around when I've needed to deal with this type of situations.
Thanks for the reply guys! I was hoping it would be possible to make API calls on client side from static webpage without setting up a server and configuring to much back-end stuff, but I guess that won't be possible without at least setting up a cors proxy server.
I'm not sure which framework you are using, or if is just Html and CSS, but consider using something like Next.js or Nuxt.js, as I'm doing with Next.js everything is static, and you wouldn't have this issue. A second option as stated above is using a proxy, for this, I would suggest using Cloudflare workers, I already have something like that setup here: https://cors.yasbr.com I suggest deploying your own using this repo: https://github.com/yassinebridi/cors There is no documentation yet, but just read on Cloudflare workers, and how to set up deployment using Github actions.
I am just using the simplest of the simple javascript, fetching the auth key and database via GET. Here is my initial test code where I'm inserting some test data to a table in notion.
<html>
<head>
<script>
const urlParams = new URLSearchParams(window.location.search);
var database = urlParams.get('db')
var auth = urlParams.get('auth')
const data = {
"parent": { "database_id": database },
"properties": {
"Name": {
"title": [
{
"text": {
"content": "test, test2"
}
}
]
}
}
};
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
document.getElementById("demo").innerHTML = this.responseText;
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML = this.responseText;
}
};
xhttp.open("POST", "https://api.notion.com/v1/pages", true);
xhttp.setRequestHeader("Authorization", "Bearer " + auth);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.setRequestHeader("Notion-Version", "2021-05-13");
xhttp.send(JSON.stringify(data));
}
</script>
</head>
<body>
<h1>The XMLHttpRequest Object</h1>
<p id="demo"></p>
<button type="button" onclick="loadDoc()">Request data</button>
</body>
</html>
I'm not sure which framework you are using, or if is just Html and CSS, but consider using something like Next.js or Nuxt.js, as I'm doing with Next.js everything is static, and you wouldn't have this issue. A second option as stated above is using a proxy, for this, I would suggest using Cloudflare workers, I already have something like that setup here: https://cors.yasbr.com I suggest deploying your own using this repo: https://github.com/yassinebridi/cors There is no documentation yet, but just read on Cloudflare workers, and how to set up deployment using Github actions.
Hi @yassinebridi is it just me or your worker solution does not work?
https://cors.yasbr.com/https://api.notion.com/v1/databases/[DBID_HERE]
Thanks
I think the problem can be solved by just adding a whitelist to the configuration page of the Notion Integration, indicating the domains under which the secret can be called, what is the reason for not doing so? Is it because there will be a lot of asynchronous requests from the web page that will burden the server?
I was trying to build out some cool stuff in codepen hooking into the Notion API and I ran into this same problem. bummer!! I'm hopeful you will add some kind of whitelist support soon. Full disclosure - I am a designer (working in design systems) and not a dev, so my use cases will be a bit different.
Hi @alicial / Notion - now that the API is out of beta, do any of the new updates enable this kind of functionality? I'm hoping now I can hook into the API from a webpage, and/or a Figma plugin I'm building.
Hi @alicial / Notion - now that the API is out of beta, do any of the new updates enable this kind of functionality? I'm hoping now I can hook into the API from a webpage, and/or a Figma plugin I'm building.
I second this! I am trying to make calls to the API from notion.so/user/page/xxxxxx
to implement 'custom' commands and being blocked by CORS
Hello, you could use a worker from Cloudflare to proxy your requests to the notion API: https://developers.cloudflare.com/workers/examples/cors-header-proxy/
Hi! I've been exploring this idea as a workaround, thank you. Was also thinking of using JSONP so that other users don't have to create a proxy too. Is that a feasible solution in your opinion?
I don't see how using JSONP for posting data to Notion API will work, please share your solution.
https://github.com/makenotion/notion-sdk-js/issues/96#issuecomment-898989814
Not working.Even though i tried setting up my own worker https://<my-domain>/https://api.notion.com/v1
same CORS issue. Any solution?
Hello guys, I wrote my worker because of some issues. You can implement to your side easily, here it is;
const API_END_POINT = "https://api.notion.com/v1";
export default {
async fetch(request, env) {
return await handleRequest(request)
}
}
function getCorsHeaders(request) {
return {
"Access-Control-Allow-Origin": request.headers.get("Origin"),
"Access-Control-Allow-Methods": "GET, HEAD, POST, PUT, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
};
}
function handleOptions(request) {
return new Response(null, {
headers: getCorsHeaders(request),
});
}
async function handleRequest(request) {
if (request.method === "OPTIONS") {
return handleOptions(request);
}
let url = new URL(request.url);
let requestUrl = `${API_END_POINT}${url.pathname}`;
let notionResponse = await fetch(requestUrl, {
body: request.body,
headers: {
"Authorization": "Bearer SECRET_KEY",
"Notion-Version": "2022-06-28",
},
method: request.method
});
return new Response(notionResponse.body, {
headers: {"Content-Type": "application/json", ...getCorsHeaders(request)},
status: notionResponse.status,
statusText: notionResponse.statusText
});
}
Change SECRET_KEY
value with yours
I think the problem can be solved by just adding a whitelist to the configuration page of the Notion Integration, indicating the domains under which the secret can be called, what is the reason for not doing so? Is it because there will be a lot of asynchronous requests from the web page that will burden the server?
Any practical reason to not enable this sweet solution?
@kalaomer be careful embedding secret keys directly in your worker code. Use wrangler references instead:
@Phylo229 thanks for warning, i will update my worker :)
Any updated?
I've run into the same problem, and it seems really odd to have a JavaScript SDK and then say in an issue that it shouldn't used from the browser. If that's really the intention, it would be worth making that explicit in the README so that people don't waste time having to find this thread.
@eldang agree, it's super weird. I was also interested in querying notion api from a web page.
It should be stated somewhere.
@david1542 Makes zero sense to me haha
This is just bizarre - you can't build a web app that can access Notion - am I understanding that correctly? You need to build some kind of back end?
@nyrsimon that's correct. At the moment, you can't make HTTP requests from a JavaScript in the browser. You need to do that from a server.
I think I do now understand why it's done this way. Even if a user just sniffs the API responses using Developer Tools, they would be able to construct additional requests that get more information than a given app is displaying, so there's a pretty big data leak risk (and potentially also vandalism risk if the permissions aren't locked down enough) to having the requests be visible to the client at all.
But the number of people commenting here tells me I'm not crazy for seeing "JavaScript SDK" and thinking I would be able to use it in the browser. I expect server-only SDKs to be written for PHP, Golang, Python, etc. I think it would be worth putting an explicit qualifier early in this SDK's README, and in the Notion docs where they reference the JS SDK. That could save a lot of people from wasting time trying to make this work in a way it's not intended to.
You can use notion js sdk in browser extension,not only in backend,see what i do: https://notion-flow.xheldon.com/en/
I am trying to talk to the notion api via a webpage, but it is getting blocked by the browser. I think this should be possible to fix on the server side by adding the "Access-Control-Allow-Origin: *" in the reply header.
A current workaround for this is to run the browser with CORS check disabled.