dspace-angular icon indicating copy to clipboard operation
dspace-angular copied to clipboard

Unable to route network requests to different DSpace REST API URL during SSR

Open ghost opened this issue 3 years ago • 5 comments

Is your feature request related to a problem? Please describe.

With Angular Universal, during server-side-rendering (SSR), REST requests are made from server-to-server. After rehydration the client-side-renderting (CSR) REST requests are made from the browser. Using the same URL for both is limiting for production infrastructure deployment causing server-to-server communication to route out of the internal network and back through the public URL which is often through load balancer or proxy. This decreases initial page load performance due to the increased network latency.

Additionally, running locally in a docker network requires either running dspace-angular in development mode or having a public IP for the host machine.

Describe the solution you'd like

The configuration should support providing both URL for DSpace API for when SSR makes requests and for when CSR makes requests. The implementation should alternate which URL to use based on isPlatformBrowser().

Describe alternatives or workarounds you've considered

N/A

Additional context

N/A

ghost avatar Jan 06 '22 17:01 ghost

Thanks for creating this ticket @wwelling . For now, I'm pulling this into the 7.3 board, as it might be too late for 7.2 (due Feb 7) unless this work ends up moving quickly & being easy to review. If somehow it moves quickly, we can see whether it's possible to fit into 7.2.

@artlowel and @atarix83 : just pinging you to make you aware of this ticket & get any initial feedback/ideas you may have. This is something I stumbled on in trying to enable SSR in Docker on localhost (which doesn't work because SSR and CSR need different URLs in that environment). @wwelling kindly offered to create the ticket & look into it.

tdonohue avatar Jan 06 '22 17:01 tdonohue

@wwelling and I chatted a bit more about this privately via Slack today, and ran into a significant complication.

Because our REST API uses HATEOAS, and has absolute URIs in the _links section (see for example https://api7.dspace.org/server/), this makes using two different REST API URLs quite complex.

The end goal here is that when the UI runs in SSR mode, it might want a more "direct" way to access the REST API. As an extreme example, if the REST API is running on localhost, then when the UI is running in SSR mode, it really could just make calls to http://localhost:8080/server/. There's no need for the UI to access the REST API via a public URL until it switches to CSR mode.

But, because our REST API sends all the _links back as absolute URIs, even if you initially access the REST API at localhost:8080, the HATEOAS links will send you to the public URL on the next request.

I'm not yet sure of the best solution, but it seems like there's two obvious options:

  1. When running in SSR mode, the UI replaces the public URL with the local URL (this seems a bit messy/hacky, but it'd be only happening on SSR mode)
  2. Or, we modify the REST API to send _links back as absolute paths instead of absolute URIs. So, instead of https://api7.dspace.org/server/api/authn it'd send back /server/api/authn. But, I know that may or may not be controversial, see this StackOverflow for some discussion: https://stackoverflow.com/a/18505331

Overall, I'm not sure of the best approach here, so we may need to consider this more for 7.3 & find time to discuss in a future meeting.

tdonohue avatar Jan 06 '22 21:01 tdonohue

Just a wee note here about the "affects local instances" aspect: I've got local (docker, though this isn't required) DSpace 7 SSR working nicely by editing /etc/hosts so that the hostname used for the backend server can be resolved both within the docker swarm and by my host machine.

This doesn't solve the problem of a true production instance where you want to route browser vs frontend traffic differently on the way to the backend (though some similar host resolution / network routing hacks on the angular machine could probably achieve the same thing without any DSpace code modification)

kshepherd avatar Nov 15 '22 02:11 kshepherd

Just a wee note here about the "affects local instances" aspect: I've got local (docker, though this isn't required) DSpace 7 SSR working nicely by editing /etc/hosts so that the hostname used for the backend server can be resolved both within the docker swarm and by my host machine.

This doesn't solve the problem of a true production instance where you want to route browser vs frontend traffic differently on the way to the backend (though some similar host resolution / network routing hacks on the angular machine could probably achieve the same thing without any DSpace code modification)

@kshepherd is that through https on the backend as well? A case we have is the SSL certificates are all managed on the gateway by the organization. What would help out, in that case of overriding the DNS is to then not have the backend calls be over https while the front end is over https. I was hoping there was a workaround to moving the certs over to internal machine. In one case, I was able to get an organization's private Root CA to be trusted by Node internally by adding it to the environment using NODE_EXTRA_CA_CERTS

As @tdonohue points out, with that StackOverflow link, that it's a good idea to have an absolute URI, but the population of the scheme, host, and port should probably be dynamic based on the incoming requests protocol, port and hostname, this would allow the application to work better behind Gateways and VirtualHosts and reduce some of the integration pain points.

(Note, there's another place where there is "hard binding" of services to absolute URI, and that is in SWORD and SWORDv2, that has always been a bit of a pain when you have gateways your deploying behind and want to make backend calls to those services, removing/improving that would also be a "nice to have")

mdiggory avatar Jun 27 '23 15:06 mdiggory

This ticket came back up in our DevMtg on June 27, 2024 related to performance improvements for Angular SSR. I'm bumping up the priority to "high" as I think this may require more investigation again to see if we can solve the problem of public vs private REST URL requests (so that SSR doesn't need to use public URLs for requests, which can slow down the SSR process).

tdonohue avatar Jul 03 '24 21:07 tdonohue