This guide is only for the GET method, but should get you on the right road for any method

Why you need CORS for Ionic Capacitor apps

When it came time to do my frame data JSON file fetching in Ionic 5 I was met with a sad realisation. I wouldn’t be able to take advantage of the fact that Cordova apps use a loophole in CORS to allow fetching from any source at all.

Ionic and Capacitor have (wisely!) decided that this is a terrible idea and that you’ll need to set CORS up properly if you’re hoping to fetch an asset from your server.

Server side (NGINX)

In order to fetch a file from your sevrer you’ll have to tell it that it’s okay for ionic apps to access your server. The ionic capacitor docs state that the origin of an ionic app depends on the plaform as follows

Platform Origin
iOS capacitor://localhost
Android http://localhost

This leaves us in the awkward position of having to add an exception for two sources at once. The method I used is hacky but works perfectly for a default NGINX installation.

NGINX doesn’t allow else if blocks so we’re going to have to hack one together ourselves.

First create a string variable named cors.

  set $cors '';

Next we’re going to check to see if the origin of the request is one of the above capacitor origins using a little regex. If it is, we’re going to set $cors to T for true

  if ($http_origin ~ (?:capacitor|http):\/\/localhost) {
    set $cors T;
  }

Then we’re going to check that the request type was GET. If it is, we’ll append another T to the end of $cors.

  if ($request_method = 'GET') {
    set $cors '${cors}T';
  }

If both of those checks passed then $cors should be ‘TT’. We’ll use that to allow the request to go ahead in the location block of our subdirectory that we’ll be serving files from.

  location /somesubdirectory/ {
    if ($cors = 'TT') {
      add_header 'Access-Control-Allow-Origin' $http_origin;
      add_header 'Access-Control-Allow-Methods' 'GET';
    }
  }

And that’s it for NGINX! Save the changes to your config file, and restart your server with

  sudo /etc/init.d/nginx reload

App Side

Once that’s working, you’ll be able to fetch your files on both Android, iOS and in the browser dev environment which conveniently also runs off http://localhost.

Because I need to make sure my hefty 2MB JSON file isn’t downloaded everytime the app is started, I start by downloading a tiny version check file. ?ts=${Date.now()} makes sure that the result isn’t cached.

const newVersionCheck = async () => {

  ...

  // Check if there's a new version
  const version_response = await fetch(`https://fullmeter.com/versionDetails.json?ts=${Date.now()}`)
  const SERVER_VERSION_DETAILS = await version_response.json();
  
  ...

  if (SERVER_VERSION_DETAILS.FRAME_DATA_CODE > LS_FRAME_DATA_CODE) {
    
    // New version found, fetch it
    const framedatajson_response = await fetch(`https://fullmeter.com/newrelease/SFVFrameData.json?ts=${Date.now()}`)
    const SERVER_FRAME_DATA = await framedatajson_response.json();

    // Put the new JSON file, along with it's version code into localstorage
    localStorage.setItem("lsSFVFrameData", JSON.stringify(SERVER_FRAME_DATA));
    localStorage.setItem("lsFrameDataCode", SERVER_VERSION_DETAILS.FRAME_DATA_CODE)
    
  }

}

And that’s all there is to it! async and await fetch make the code extremely easy to read and set up.

Conclusion

We’ve set up our NGINX server to accept GET requests from ionic capacitor apps and we’ve got our ionic app fetching data!