NCEAS / metacat

Data repository software that helps researchers preserve, share, and discover data
https://knb.ecoinformatics.org/software/metacat
GNU General Public License v2.0
25 stars 12 forks source link

MetacatUI should use CN.resolve() for object downloads if possible #1407

Closed csjx closed 4 years ago

csjx commented 4 years ago

We've discussed the issue where a repository in the down state, or just inaccessible because of network issues, will not be able to deliver objects with MN.get(). For people downloading from search.dataone.org, they can view the metadata (since it's replicated to the CN), but the data objects are unavailable, even when they are replicated to multiple member nodes.

@laurenwalker pointed out that XHR calls to CN.resolve() to get the ObjectLocationList for each object results in a 30x redirect, and the browser automatically follows the redirect to the (at times unavailable) first replica in the list. The ordering of the replicas on the CN side is being addressed in https://redmine.dataone.org/issues/8853 to de-prioritize replicas that are known to be unavailable (INVALID, down node status, etc). But MetacatUI needs to be able to iterate through the ObjectLocationList nonetheless and try/catch failures until success or the list is exhausted.

From this StackOverflow question we see that the browsers are doing what they are supposed to with XHR calls - follow the redirect.

However, we might be able to use the new Fetch API when calling CN.resolve()and set the Request.redirect property to manual so we can obtain the replica list and loop through it. Of course, this depends on browser support. Other ideas welcome!

One other point is that MN installations that aren't part of a CN environment would want to skip the CN.resolve() call, so we should have a configuration that enables or disables object resultion within MetacatUI.

csjx commented 4 years ago

I set the priority high for this mainly so we can put some quick cycles into figuring out if the Fetch API will work for us in managing redirects better. This affects the whole DataONE network, not just ESSDIVE, too.

csjx commented 4 years ago

I did some quick testing in a JSFiddle, and it turns out that fetch(url, { redirect: "manual"}) does not expose the body of the original request in the response (it is set to null), which is the same case with { redirect: "error"}, which just throws a NetworkError if the response code is 3xx.

Ultimately, there's no way to access the CN.resolve() body in the browser. From discussion here and here, the WHATWG Fetch API specifically disallows access for cross-site scripting security reasons. I would imagine this is the same reason that the browser also does the same for XHR requests (specifically disallowing).

The only two ways forward I see are

1) Changing the CN response code from 303 to 200 and require the client to iterate through the ObjectLocationList body (unlikely, given this is a full CI stack change - @datadavev @mbjones can comment)

2) MetacatUI tries to follow the redirect, and catches any errors (404, timeout, etc.) and then creates its own replica list from the SystemMetadata.replica list, which would involve discovering the baseUrl of each replica node from the node list given a nodeId, and tries to fetch the object from each replica in the list until it succeeds. Since the replica list should include status of each replica, we could hit only COMPLETED replicas (skipping those with FAILED|QUEUED|REQUESTED|INVALIDATED).

csjx commented 4 years ago

Dupe of #415. Woops.

mbjones commented 4 years ago

Actually, its a dupe of https://github.com/NCEAS/metacatui/issues/415

csjx commented 4 years ago

Hah! I added this to the wrong repo 😮

csjx commented 4 years ago

Moved comments to https://github.com/NCEAS/metacatui/issues/415, closing this.