Make HTTP requests from plugins

Hi!
How to properly make requests to remote websites from a plugin? I tried simple fetch("URL"), but it is blocked by CORS: Access to fetch at 'https://url' from origin 'app://obsidian.md' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

3 Likes

My personal fave way to work around CORS issues is to create a middleware server that you control. From there, you can make whatever external calls you want. Then from your plugin fetch($YOUR_SERVER) because you control both ends you can set the correct CORS policy.

A super simple (and free) way to do this is using Glitch’s express server template. Add the cors npm package and use it with express: app.use(cors()). You’ll be able to fetch any endpoint you setup in express within your plugin.

There are other ways and some are faster/easier, but controlling both sides of the request is the best way imho.

4 Likes

Sorry for dumb questions, I’m not really familiar with the javascript ecosystem and approaches. I understand the CORS concept in the context of web pages. But shouldn’t it be possible to make an arbitrary web request from a local application such as obsidian and ignore CORS headers? Creating, hosting and maintaining a separate server sounds like too much of a hassle.

Obsidian is an electron app which means it is essentially Chrome under the hood. You’ll need to handle CORS like you would in any other client-side cross domain request just as the error indicates.

You could try throwing no-cors on the fetch request. Or Google handling cors with fetch.

If you want to go the quick-n-dirty route lookup ‘cors anywhere’. I wouldn’t ship a plugin with cors anywhere though as it’s liable to break.

Setting up a server of Glitch is pretty fast and easy tbh. Just use the express template and move your cross-browser fetching into the glitch app.

1 Like

Regular webpages opened in Chrome don’t get access to the file system, while obsidian plugins can use the javascript fs module for local files. I thought that something similar is available for web requests.

1 Like

If you are okay with your plugin only working in the desktop you can use the package node-fetch. GitHub - node-fetch/node-fetch: A light-weight module that brings the Fetch API to Node.js node’s libraries bypass cors restrictions but are only available in the desktop apps.

3 Likes

Hi,

I have a similar problem. I want to implement a CalDav Client Plugin and get the same error.

I try to implement a middleware with express and the cores package, but it doesn’t work. Can someone give me please a code example, a tutorial or a link to the Glichßs express server?

Thanks
Kantiran

You can overcome this by using node.js’ http/https module instead of fetch (or use a convenience module like request). It doesn’t have the same limitations.

require('request')('http://example.com/', (error, response, body) => {
    console.log(JSON.parse(body));
});

I want to get google books API data, but I’m running into this same CORs policy issue. @intellectronica, I don’t think your solution works for me, at least while trying in the dev console. Some people might have luck with this article. I haven’t got it to work yet.

I’m not working on a plugin, but I’m using a dataviewJS code block to download image data.

Hello @mjduck,

This may interest you !

It’s a script to be used inside Quickadd plugin to fetch book data from Google Books API, and then automatically create a note from a template.

You can check line 183 of the script how the request is made using request. I have not encountered CORs issues with that function.

The author of Quickadd plugin made a script to fetch movie data using OMDB API (using the same request function) which helped me a lot to write this Google Books API script.

Well that’s neat. Thanks @JamesKF !

1 Like

In plugin you should import requestUrl function provided by obsidian package, see the declaration at obsidian-api/obsidian.d.ts at c01fc3074deeb3dfc6ee02546d113b448735b294 · obsidianmd/obsidian-api · GitHub

1 Like

Is this usable from within a Templater template or DataviewJS? That is, is it usable within arbitrary JS executing within an Obsidian plugin?

Asking as something of a node/TS newbie but experienced developer. I assume that this depends on what sort of library search paths are available from within the environment provided at runtime by these respective plugins?

DataviewJS and Templater have access to most functions.
These included.
You can check by opening the Console in the Developer tools, and see if it shows up.

The one thing they can’t do is anything related to event handling.