Skip to content

feat: add iiif-image and public-fetch packages - #986

Merged
ddeboer merged 3 commits into
mainfrom
feat/iiif-image
Nov 4, 2026
Merged

ddeboer merged 3 commits into
mainfrom
feat/iiif-image

Conversation

@ddeboer

@ddeboer ddeboer commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

Moves the protocol-generic half of netwerk-digitaal-erfgoed/stack#55 into LDE, so that @ndes/iiif-images keeps only its SCHEMA-AP-NDE binding.

@lde/iiif-image

  • imageServices(manifest): the image service URL of each painted image, in Presentation 2 or 3, in painting order. Destructure the first for a cover image. It walks the plain JSON, so a manifest with "annotations": [null] – which Deventit Atlantis writes and normalising parsers reject – still yields its services. It throws for a document without canvases, such as an error page served as JSON, because a caller that stores results must not record that as “no image”.
  • readImageService(url, info): an info.json as { url, width, height, sizes }, where each size carries the URL of its JPEG rendition in the canonical form of the service’s Image API version.

Tested against four real manifests: Gouda Tijdmachine, Limb, LDmaX and FEHAC.

@lde/public-fetch

fetchPublic(url, options) is fetch for URLs from someone else’s data, run from inside a private network:

  • it refuses non-http(s) URLs, every address that is not public unicast (including the IPv6 forms that carry an IPv4 address), single-label hosts and .localhost, .local, .internal and .svc names, with or without a trailing dot;
  • it follows redirects one hop at a time and checks each target, dropping credentials on a cross-origin hop as fetch does;
  • it returns an ordinary Response whose body fails past 20 MiB, whatever Content-Length says, and is not read until the caller reads it.

It does not limit request rates: that stays with @lde/host-limiter and @lde/resolver.

@lde/iiif-validator (breaking)

It now fetches through @lde/public-fetch, so ManifestValidationReason gains refused-url and too-large.

Not in this PR

  • distribution-probe has its own byte-limited body reader. Moving it onto fetchPublic is a separate change.
  • Sizes derived from tile scale factors are rounded to the nearest pixel. The live Cantaloupe server at ndeiiif.adlibhosting.com lists 83 for 1335 ÷ 16, which rounding gives and rounding up would not.

After merging

@lde/iiif-image and @lde/public-fetch are new on npm, so each needs the manual first publish before the release workflow can take over.

- Add @lde/iiif-image: find a manifest’s first painted image service in Presentation 2 or 3,
  and read info.json into version, level, limits and sizes
- Add @lde/public-fetch: fetch URLs from other people’s data without reaching internal
  addresses, checking every redirect and bounding the body read
- Document both on the docs site and list them in the package tables
- Refuse manifest URLs and redirect targets that are not public addresses
- Read at most 20 MiB of a manifest body

BREAKING CHANGE: ManifestValidationReason gains refused-url and too-large, so code that
handles every reason must handle these two.
- iiif-image: replace firstImageService and hasCanvases with an imageServices iterator that throws for a document it cannot read as a manifest
- iiif-image: give each size the URL of its JPEG rendition, replacing imageUrl, and drop version, level, server limits and size sources from ImageService
- public-fetch: bound the body of the Response fetchPublic returns, replacing readJson, and read nothing until the caller does
- public-fetch: stop exporting isPublicWebUrl, the option and limit constants, and the fields on its errors
- iiif-validator: read manifests with response.json()
@ddeboer
ddeboer merged commit 5c651ea into main Nov 4, 2026
4 checks passed
@ddeboer
ddeboer deleted the feat/iiif-image branch November 4, 2026 08:17
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