Skip to content

fix: the image_scales original download points at the original again - #37

Merged
jensens merged 1 commit into
mainfrom
fix/15-original-download
Aug 27, 2026
Merged

fix: the image_scales original download points at the original again#37
jensens merged 1 commit into
mainfrom
fix/15-original-download

Conversation

@jensens

@jensens jensens commented Aug 27, 2026

Copy link
Copy Markdown
Member

Half of #15 — the half where "should this go through Thumbor at all?" answers itself.

ImageFieldScales.get_original_image_url builds the metadata's top-level download by asking for a scale at the original's own dimensions. Under Thumbor that came back as a Thumbor URL, and that is wrong twice over.

It is not the original. A 1:1 request through an image processor is at best a re-encode — and since 0.7.0 a Thumbor URL names the source derivative, so a "download original" link handed over a capped, colour-converted rendition rather than the uploaded bytes. On the press site this package was built for, that is precisely the asset the link exists to serve.

It is not context-relative, which the metadata contract requires. _scale_view_from_url strips the context URL off and the renderer puts it back. With PGTHUMBOR_SERVER_URL=/thumbor there is no context prefix to strip, so the stored value was thumbor/<signed> and the renderer emitted {image_url}/thumbor/<signed> — broken for every consumer of the column, including plone.namedfile's own tag().

The route already existed

@@images/{fieldname} returns the original under pgthumbor today. The field branch of ImageScaling.publishTraverse builds the scale view with only data= and fieldname=, without a uid, and ThumborImageScale.__init__ only produces a Thumbor URL when one is present — so _thumbor_url stays None, index_html() falls through to the parent, and Plone streams the stored bytes.

_skip_type_fallback_url already builds exactly that URL for SVG (#17), so this shares it rather than spelling "the original's own URL" a second time. A test pins that.

Registration

For IPlonePgthumborLayer, which is strictly more specific than plone.namedfile's (field, content, Interface), so it wins the lookup without an overrides.zcml entry — and sites without the add-on keep the stock adapter.

Deliberately not in scope

Per-scale download entries are untouched, and a test pins that only the one method is overridden. Those should be Thumbor URLs. Their own version of the host-root problem is the rest of #15 and wants answering together with #7: absolute URLs would fix the rendering, but bake in the host that the relative setting exists to avoid.

So #15 stays open after this.

595 tests green, adapters.py at 100%.

🤖 Generated with Claude Code

Half of #15, and the half where "should this go through Thumbor at all?"
answers itself.

ImageFieldScales.get_original_image_url builds the metadata's top-level
download by asking for a scale at the original's *own* dimensions. Under
Thumbor that came back as a Thumbor URL, which is wrong twice over.

It is not the original. A 1:1 request through an image processor is at
best a re-encode, and since 0.7.0 a Thumbor URL names the source
derivative — so a "download original" link handed over a capped,
colour-converted rendition rather than the uploaded bytes. On the press
site this package was built for, that is precisely the asset the link
exists to serve.

And it is not context-relative, which the metadata contract requires.
_scale_view_from_url strips the context URL off and the renderer puts it
back; with PGTHUMBOR_SERVER_URL=/thumbor there is no context prefix to
strip, so the stored value was "thumbor/<signed>" and the renderer emitted
"{image_url}/thumbor/<signed>". Broken for every consumer of the column,
including plone.namedfile's own tag().

The route to serve it properly already existed. @@images/{fieldname}
returns the original under pgthumbor today: the field branch of
ImageScaling.publishTraverse builds the scale view without a uid, and
ThumborImageScale.__init__ only produces a Thumbor URL when one is
present, so index_html() falls through and Plone streams the stored bytes.
_skip_type_fallback_url already builds exactly that URL for SVG, so this
shares it rather than spelling it a second time.

Registered for IPlonePgthumborLayer, which is strictly more specific than
plone.namedfile's (field, content, Interface), so it wins the lookup
without an overrides.zcml entry and sites without the add-on keep the
stock adapter.

Per-scale downloads are untouched, and a test pins that only the one
method is overridden. Those *should* be Thumbor URLs; their own version of
the host-root problem is the rest of #15 and needs answering together with
#7, since absolute URLs would fix the rendering but bake in the host that
the relative setting exists to avoid.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jensens
jensens merged commit db9a46b into main Aug 27, 2026
6 checks passed
@jensens
jensens deleted the fix/15-original-download branch August 27, 2026 00:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant