For image files, it would be nice to have the image styles URLs available to client applications. These URLs can't be simply calculated on the client-side due to the anti-DoS tokens added to the end of the URLs.
Proposed resolution
For file entities that have image styles, list their URLs in the response. Exactly what is the best way to implement this is debatable. Adding them as extra "links" might make the most sense, perhaps labelled by their image style. It would probably be a good idea to prefix the image style name to reduce the likelihood of naming collisions (in case someone makes an image style with the name "self", for example):
{
"data": [
{
"type": "file--file",
"id": "aeb7262d-5d1c-4252-a7f7-7c32e7f9c20c",
"attributes": { ... },
"links": {
"self": "http://drupal.dd:8080/jsonapi/file/file/aeb7262d-5d1c-4252-a7f7-7c32e7f9c20c",
"image_thumbnail": "http://drupal.dd:8080/sites/default/files/styles/thumbnail/image.gif?itok=AbCdEfGh",
...
"image_large": "http://drupal.dd:8080/sites/default/files/styles/large/image.gif?itok=aBcDeFgH"
}
Alternately, I could see using "meta" members to pass the URLs. Perhaps something like:
{
"data": [
{
"type": "file--file",
"id": "aeb7262d-5d1c-4252-a7f7-7c32e7f9c20c",
"attributes": { ... },
"meta": {
"image_styles": {
"thumbnail": "http://drupal.dd:8080/sites/default/files/styles/thumbnail/image.gif?itok=AbCdEfGh",
...
"large": "http://drupal.dd:8080/sites/default/files/styles/large/image.gif?itok=aBcDeFgH"
}
}
Comments
Comment #2
e0ipsoI like this idea, but I don't like it at the same time.
I go in a loop over these:
PRO: It is very useful for consumers, and that's what an API is for. It's not for winning a cleanliness gold medal.
CON: In certain setups it can increase the payload size significantly.
PRO: The payload size will matter less with gzip compression.
CON: Using image styles defined in the server breaks the no presentation in the back-end rule and that is bad for many, many reasons.
Thoughts?
Comment #3
e0ipsoI think this feature may be a good candidate for the separate contrib being planned in #2846488: Explore abstracting away "Drupalisms".
Comment #4
hampercm CreditAttribution: hampercm at Acquia commentedI can see this as being a part of an "extras" module, as some people won't need this, and as @e0ipso mentioned, it can increase payload size significantly.
As for image styles being presentation on the back-end, this feels like a gray area to me, though in the end this may just be arguing semantics. Many frontend projects focus on optimizing image sizes and delivery to the client; this is often done manually by pre-processing the images, and giving the filenames appropriate suffixes or putting them in different directories. Drupal just happens to have this functionality available out-of-the-box. In the end, image styles greatly reduces the total data transfer, as images are frequently the largest portion of data transferred for a website/application.
Either way, this feels like a very important feature to have somewhere. It even come up as a question during a presentation I've given regarding JSON API.
Comment #5
justinlevi CreditAttribution: justinlevi commentedIs there a way currently to get to the image style urls with JSON API? I'm having a hard time wrapping my brain around the request syntax for a simple request to a media reference entity on a basic page content type.
Comment #6
SpleshkaWe ran into the same issue and I feel that this issue will become a hot topic soon :) Developers certainly should be able to fetch images including their image styles. As mentioned in #4, there is no way to generate image style url from the frontend due to the tokenization of this url, and this is the key of the issue.
My proposed solution would be to let frontend to include list of required image styles into the json api request. Something like this (very, very rough and dirty example!):
I'm not yet (!) familiar with json api source code so can't judge if this direction if sufficient or not, so maintainers' opinion is needed && appreciated.
Yet another question here is if maintainers would like to see this 'image_style' feature in the json_api module OR if it should go to the new module json_api_extras (json_api submodule or standalone)?
I'm willing to help in getting this feature done, as we urgently need it. So fast responses here might save the world!
Comment #7
SpleshkaComment #8
SpleshkaThere's probably another solution which is outside of Json API scope. Things like Sharp ,Image Resizer or Imaginary might be better from architectual point of view:
1. Frontend becomes independant of Drupal's image styles
2. Images aren't linked to the backend (file storage can be moved to S3 or similar, no links to the backend, etc)
However, it brings additional complexity like configuration + support of image resizing software (and most likely standalone server as well, because it's not supported by most of the hosting providers).
So even though enterprise level solutions have a way around this issue, simple projects still need "a simple solution to get a resized image".
Comment #9
Wim LeersWe're working on this in core too: #2825812: ImageItem should have an "derivatives" computed property, to expose all image style URLs. Over there, we're considering adding a
image_style_urls
property to theImageItem
field type.That'd then make it automatically available. For core REST, for JSON API, for GraphQL … and for auto-generated documentation such as https://www.drupal.org/project/openapi or https://www.drupal.org/project/docson.
Comment #10
dannyjohnson1 CreditAttribution: dannyjohnson1 commentedSubscribe...
Comment #11
e0ipsoMoving to the JSON API Extras project.
Comment #12
e0ipsoThis deserves some attention. Moving to the latest module version.
Comment #13
GoldI have just hit this issue myself.
Looking at the "no presentation in the back-end" and the payload size concerns, could it be possible to just deliver the anti-DoS token with the current payload? The image style URLs are easily derived from the source image URI and the frontend devs would be working in tandem with the backend devs.
This we end up with something like this;
Given this would only be adding one extra attribute it could also be moved back to the JSON:API module.
Thoughts?
Comment #14
GoldAh... Never mind. Just saw that
buildUrl()
would be creating a unique token for each derivative. Not sure how useful the suggestion at #13 is now.