Could not access the module download URL with Angular GET request

Hi All,

I am working on SysAdmin OWA to implement the Manage modules functionalities. Here I am getting the module information using OpenMRS Addons API (https://addons.openmrs.org/api/v1/addon/org.openmrs.module.uilibrary). The response from the AddOns REST calls contains the module information with OMOD download url. Those download URL addressed to JFrog Distribution: Get your software to where it needs to be -- ASAP!.

But I could not handle requests using the Angular REST. It shows me the Access-Control-Allow-Origin error.

Cc : @dkayiwa and @darius

Hi @suthagar23, I just saw a video on this issue HERE, maybe it can be of help.

@jeiddiah It would be a server side CORS problem, I think we can’t do anything from the client side. So there are some required headers wanted to add with the server’s response

@dkayiwa and @darius Can you please take a look at here :slight_smile:

@suthagar23 is this reproducible on modules-refapp?

@dkayiwa Yah. Now there are no problem with OpenMRS AddOns REST APIs.

Response from the Add-Ons REST APIs contains the download URL from https://binary.com/openmrs. When I tried to download the modules from https://binary.com/openmrs It shows me that error :frowning:

What are the exact steps for reproducing this?

  1. Just go to Search Module and search for a module.
  2. Then Click View to go to the module page
  3. Then Click Download button.

At this point, you will get this error message :slight_smile:

If you’re trying to download from bintray to the user’s browser, can’t you just put a plain <a href="..."> element there?

Nope, Here I am using Angular GET Request to download the file and then upload that file data to Module Resuoure to install the module

  var fd = new FormData();
  var moduleUrl = "https://bintray.com/openmrs/omod/download_file?file_path=uilibrary-2.0.6.omod";
  $http.get(moduleUrl, {responseType: "arraybuffer"})
  .success(function (data){ 
        var filename = moduleUrl.substring(moduleUrl.lastIndexOf('/')+1);
        let blob = new Blob([data], {type: 'application/octet-stream'});  
        var url=(window.URL).createObjectURL(blob);
        var file = new File([data], filename, {type:"application/octet-stream", lastModified: new Date().getTime()});
        fd.append('file', file);

       // Then upload this file to the Module Resource

}

I think that’s the wrong way to do it. It doesn’t make sense to pass the file through the user’s web browser.

Is the workflow here that the administrative user says “upgrade to the latest version of xyz module”? If so I would expect that OpenMRS already has a Java API for this, and you should expose that java API via REST. If we don’t have the Java API yet, you should add it.

(Also, we don’t control bintray, it’s an external service, so we have no was of enabling CORS there.)

Yah you are correct!

But in that way also, JAVA API want to use that binary REST endpoint to download the modules. In this situation, there might be a same access-control-origin problem :frowning:

I got some solutions from Google to access binary.com REST end points properly. I will check it and update the status.

CORS and access-control-allow-origin is a browser thing, owing to the “same origin” policy that’s applied by default to AJAX requests. It doesn’t apply to the server downloading a file.

If you need to do this because of time constraints in finishing this feature during GSoC, I understand that.

But in general this approach is not right. :slight_smile: If the OpenMRS server needs to update a module, it should download the new version itself, not transfer it via a user’s browser.

Also, btw, the module is actually supposed to indicate its own update url in its config.xml file, like this example. You’re not actually supposed to assume that it’s hosted/indexed on a particular server.

Yah @darius. I can able to download and install from modules server previously. (When download URL is like - OpenMRS Add Ons).

But Now When I am getting the newest download URL from AddOns REST response, It contains the URL from bintary.com (like Service End for Bintray, JCenter, GoCenter, and ChartCenter | JFrog). So now I am facing access-origin problem from their server :frowning:

What will be the possible solution to this problem?

CC : @dkayiwa

@suthagar23 why not do it from the server as Darius suggested, instead of the user’s browser?

Specifically, this method in ModuleFactory is supposed to update a module to its latest version: https://github.com/openmrs/openmrs-core/blob/2.1.0/api/src/main/java/org/openmrs/module/ModuleFactory.java#L1546

I assume you’d just need to expose this method via a REST resource, and then you can call it and all of the logic should be taken care of on the server-side.

If this code is actually broken by our shift from Modulus to Bintray+Addons, then that’s a serious bug we need to fix in openmrs-core.

@darius Will it break OpenMRS core just yet? Because modules.openmrs.org is still accessible , so technically, if I’m not mistaken, once modulus is completely shut down, then only should we find any issues with core right?

You’re right that it won’t break openmrs core (maybe) until after we shut down modulus.

What I’m saying is that we should reason about whether that’s going to happen and fix the problem (if there is one) before real users encounter it.

-Darius (by phone)

1 Like

True,

Off-topic but worth mentioning : I’ll look through any code that uses modulus using GitHub search and let you know. If found then we shall take that up as another task to be completed.

@dkayiwa

Yah That is a good way, and It’s a suggested way also for the access-control problem. :slight_smile:

So I will create a REST Resource for this purpose / Modify the ModuleAction Resouce to achieve this action from the server side. I will start to work on this asap and continue the discussion in a different thread about the progress.