Daml-ui-template: use a different JSON API instance for each party

I would like to have a single instance of Daml-UI-template which can connect to multiple DAML JSON API instances (e.g. Alice -> localhost:7500, Bob -> localhost:7501) based on the party.

In the Layout file, where the DamlLedger react component is instantiated, I can choose the right JSON API host/port based on the party. The problem is that I get CORS errors. My understanding is that React dev server can only proxy one of the JSON API backends which means that in my case everything would be sent to the same API from all the parties - that is not what I need.

What should I do to be able to work with multiple DAML JSON API instances and avoid CORS errors?

2 Likes

Rather than having the client route the requests to the correct server, would it not be better to write a custom API server that takes a JSON API call and proxies the call to the right JSON API server?

                                /----- [JSON API server A]
[frontend] ------- [API server] ------ [JSON API server B]
                                \----- [JSON API server C]

The proxy server would need to:

  • Extract the DAML party from the request. This can be either done by inspecting the JWT token, or the DAML React Component could be extended to include a custom HTTP header for this.
  • Know what participant each party is hosted on.
  • Proxy the call to the right JSON API server. I’m sure each language has libraries to do so easily. Node.js has express-http-proxy, for example.

This also sounds similar to Running multiple instances of create-daml-app simultaneously against multiple participants. @Phoebe_Nichols, how did you solve this for your “run create-daml-app on Canton” tutorial?

3 Likes

I encountered a similar problem, thanks for flagging me in @Robert_Autenrieth.

I have created this PR to allow specifying the JSON API server port with the environment variable REACT_APP_HTTP_JSON_PORT. I plan to merge the PR today.

However, I don’t think this is sufficient for @gaborh’s use-case, since it will not allow a single instance of the UI to connect to multiple instances of the JSON API.

My suggestions for Gabor’s use-case are:

  1. Write a custom API server that takes a JSON API call and proxies the call to the right JSON API server, as suggested by @Robert_Autenrieth. This would give you maximum flexibility.
  2. Modify the file setupProxy.js from my PR to use router options, as documented here. For example, a configuration like this may work for you:
router: {
    '/bob'         : 'http://localhost:7500',  
    '/alice'        : 'http://localhost:7501'  
}

and in this example Alice’s instance of the Daml-UI-template should point at the url http://localhost:3000/alice, so that it gets proxied to http://localhost:7501. The main disadvantage here is that you need to statically pre-configure all the parties you want to use. But it will probably be faster to get running than option 1, and less code.

  1. If only for a demo on your machine, you can start chrome without the CORS check using --disable-web-security (see here) but be careful with this one ofc, perhaps turn off your network connection before you try it out
4 Likes

In production, you’d end up running each of the JSON APIs behind a reverse proxy to terminate SSL and deal with CORS so your questions is only relevant to development I think. And for development, you can get rid of CORS using CORS Anywyere. It’s a dynamic reverse proxy that just allows you to make requests from anywhere to anywhere. Since we don’t use any cookies, this Should Just Work™.

3 Likes

A post was split to a new topic: Why run a separate json-api for each party?