Moving forward with POST | GET on openmrs-module-spa in docker environment

Introduction

The Openmrs spa module provides backend functionality to serve frontend assests like configuring either the local or remote directory to store frontend files.

In case there is any requirement of storing another frontend file, like a configuration for the frontend, such a directory has to be accessed and information has to be stored in this directory.

Requirement

Issue Link: [O3-310] Application-writable config.json file in frontends/ - OpenMRS Issues

There is need to store a Configuration file in the frontend configuration directory so that when users edit widgets and pages using the implementor tools, they cannot only cache and download this information but also save this file permanently in the server so that these modifications are not limited to just the local machine but also the whole system on that server.

To be able to implement this, we needed to POST and GET this configuration file from an end-point openmrs/spa/config.json which required tweaking the openmrs-module-spa and also deploying this module in either the openmrs-sdk or a local clone of dev3 using OpenMRS docker 3.x images.

Findings

When the module with changes is deployed to the sdk, it works fine and you can POST/GET the config.json file from the frontend configuration folder.
However, when the same module with changes is deployed into the clone of dev3 using docker, the backend service is never called. This is actually the reason why when a request is executed to openmrs/spa/config.json, only the frontend and the getway services will be logged on the terminal and the user will get a 404 response.

Problem

Docker points each request to *openmrs/spa/* to the frontend container so the backend containder will never be called. As this allows provision of the “single-page” experience, this is blocking posting and getting a the config.json file because the backend is never called.

Solution

We can’t push data to the backend using the openmrs-module-spa ideally because its artifactId(spa) is blocked by docker,

  1. Reverse Proxy Server: We can Set up a reverse proxy server, such as Nginx or Apache HTTP Server, which sits in the frontend container and configure it to forward request /openmrs/spa/config.json to the backend container allowing it to handle the request while still serving the SPA architecture experience for other URLs.
    We shall also rewrite the the URL since the original url is formatted during the process.

    Something like (at-least returns a 200 rather than a 400 but the file is actually not created in the backend)

    location ~* config\.json$ {
      proxy_method POST;
      proxy_set_header Content-Length $content_length;
      proxy_set_body $request_body;
      proxy_set_header X-Original-URI $request_uri;
      proxy_pass_request_body on;
      proxy_pass_request_headers on;
      proxy_pass http://127.0.0.1:80;
      rewrite ^/([A-Za-z0-9]+) /openmrs/spa/ break;
      proxy_set_header Host $http_host;
    }
  1. Manually save and get a config.json file using ignix’s proxy_store directive to the backend container (making ignix take care of everything). However this is not scalable because in case a new feature is required whose logic is beyond ignix, the backend will definitely need to be called.

    something like (am unsure about this)

    location ~* config\.json$ {
      proxy_method POST;
      proxy_store /openmrs/data/frontend/
      proxy_store_access user:rw group:rw all:rw;
      proxy_pass http://127.0.0.1:80;
      rewrite ^/([A-Za-z0-9]+) /openmrs/spa/ break;
      ...
    }
  1. Simply change the artifact Id of the openmrs-module-spa to something else other than spa

cc @burke @ibacher @dkayiwa @dkigen

It’s nothing to do with the “artifactId being blocked”. We simply (by default) forward requests to /openmrs/spa to the frontend image.

The RefApp already has one of these; it’s what the Gateway image is.

This is probably not what you intended. This will match any request for a file that ends with config.json. We really only want this to refer to a single file.

This isn’t what the proxy_store directive does or, more exactly, it won’t store a file in a POST request to a URL. proxy_store stores responses from a backend to a local directory on the proxy, which can speed up requests in a CDN-type use-case. The best way to think about this is that reverse proxies cache responses. In any case, the container file system on the frontend image and gateway images are not persistent, so it wouldn’t be a great idea to store anything there.

A few things to keep in mind:

  1. It isn’t required that the frontend be served from /openmrs/spa. We support other URLs.
  2. How does the frontend learn about the configuration?

Otherwise, this doesn’t need a big discussion, just play around with the RefApp distro locally to get things working.

1 Like

i was really overthinking this

2 Likes

I do that all the time.

2 Likes