-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Various things in LabThings need to contain URLs, for example the serialisation of a Blob includes a download URL, and the representation of an Invocation includes a URL for polling. Currently, these are generated in a somewhat ad-hoc manner using Request.url_for - but the Request object isn't always available when it's needed.
Additionally, some objects (for example Action outputs) may be downloaded in a different request from the one where they were created. This could lead to errors if url_for is called in the request that starts the action, but the URL is returned in the request that polls it. It's an edge case, but it would be nice to know we're following best practice.
Finally, it's a general rule that we should avoid manipulating URLs in the web app as strings: particularly if LabThings is combined with another server (e.g. to add authentication), we should minimise our assumptions about URLs.
I propose we can fix all these issues by implementing a nice way to generate URLs.
- Introduce a new class,
UrlFor, which ispydantic-compatible (i.e. can be serialised). This would accept the same arguments asRequest.url_for, i.e. an endpoint name and keyword arguments. When aUrlForobject is serialised, it would callRequest.url_forto generate the URL in the request where the object gets returned so it's always correct. - Add a piece of middleware that sets a context variable, to make
url_foravailable to the deserialiser ofUrlForon every HTTP request. This avoids the need to use a specific dependency/context manager and should ensure we can always serialise aUrlForobject whenever one is returned.
This way, our application code need only ever handle endpoint names and not URLs, and we needn't worry about providing context explicitly.
After implementing this, we probably need to improve the endpoint names to make them predictable, so it's easy to use UrlFor instead of hard-coding URLs.