gentics / mesh-incubator

Project which is home for planned enhancements for Gentics Mesh
3 stars 0 forks source link

Asset Management #163

Open Jotschi opened 7 years ago

Jotschi commented 7 years ago

Motivation

It would be good to have a dedicated way to store and manage assets. These assets could in turn be referenced by Nodes via the binary field. Additionally it would be good to be able to apply cropping for assets and thus provide multiple variations of a single image asset.

Suggestion

Add the new element asset. Assets are maintained per project and are stored in flat list. No tree structure will be used to organize assets. Instead the tagging system can be utilized to tag and thus classify an asset. Once an asset has been uploaded it can be referenced by a binary field.

(meshRoot)-[:HAS_ASSET_ROOT]->(assetRoot)-[:HAS_ASSET]->(asset)
(asset)<-[:HAS_ASSET_REF]->(binaryField)
(asset)->[:HAS_ASSET_BINARY]-(assetBinary)

Asset binary vertices contain the sha512sum of the actual binary and the reference to the binary on disk. These vertices are used to handle binary deduplication.

Jotschi commented 7 years ago

Feedback:

philippguertler commented 6 years ago

I think asset management would solve a lot of problems that we are currently having with binary fields.

Regarding the feedback from the comment above

Additional thoughts

There should be a separate webroot for assets. The URL for that would be like this: /api/v1/:project/assetroot/path/to/asset

Assets should also able to be queried via GraphQL.

I will now present the issues that are currently problematic regarding binary fields. I will also explain how asset management (abbreviated as AM in the following text) as Johannes and I proposed it would solve these problems.

Current problems

Binary fields cannot be a required field

This is because you cannot upload a binary with the same request that creates a node. With AM, we could have required binary fields. The workflow would be to first create an asset and then reference the asset in the node create request.

Binary list fields are not allowed

You cannot upload multiple files with a single request to a field. Also we would need a special endpoint to fetch the binary from the list again. With AM, the list would just be a reference to assets, just like a node list.

Binaries must be duplicated when translating a node

When translating a node with a binary field, the binary has to be uploaded again to have it in both versions. This can be devastating if the binary is very large. With AM, the user would just reference the asset in both languages.

Only one binary can be fetched via webroot in a node

When having multiple binary fields, the segment field can only point to one of the binaries. The others cannot be fetched via webroot. In AM there is a separate webroot for assets, which is similar to the path in a filesystem. With that, every asset has a guaranteed webroot path and can be fetched with a better looking URL.

Response Content Type is not predictable

When requesting a node via webroot, you cannot know the response type in advance. Any node could have a segment field pointing to a binary field. In that case the response would be the binary data. In any other case the response is a JSON object. Clients using Mesh must therefore always handle the special case with binaries. With AM, every GET request to assetroot or the asset/:uuid API would be responed with the binary data. The node webroot would always return JSON.

Here is an example for that: A common pattern when using Mesh is to have an HTTP server in front of Mesh that handles requests like this:

  1. A user requests https://mydomain/blog/welcome
  2. The portal calls https://mesh/api/v1/myproject/webroot/blog/welcome
  3. The portal uses a template engine to create HTML out of the JSON response.
  4. The portal returns the HTML to the user. However, Nr 3 fails if the response is a binary. The HTTP server has to handle this special case and pipe the binary to the user. This is not ideal, especially because in some languages (PHP) is not easy to pipe binaries in a fast way.

With AM the solution would be to configure a reverse proxy to rewrite all requests to /assets directly to mesh and all other requests to the HTTP server.

So the request to https://mydomain/blog/welcome would go to the renderer service which responds with the rendered HTML. With AM, this cannot fail anymore because it is guaranteed that Mesh responds with JSON when using webroot.

A request to https://mydomain/assets/images/header.jpg would be caught be the reverse proxy which calls https://mesh/api/v1/myproject/assetroot/images/header.jpg and simply return the binary.

Disadvantages

In my proposal, assets are not specific to a language, release or version. There could be use cases where this is wanted. My solution would be to create a node (which is specific to a language, release and version) with a field that references an asset.

Jotschi commented 4 years ago

It is currently unclear how to handle permissions on /api/v1/:project/assets