Skip to content

Support X-Forwarded-Host/Path for IIIF URL generation#49

Merged
donaldgray merged 3 commits into
mainfrom
feature/forwarded_config
May 28, 2026
Merged

Support X-Forwarded-Host/Path for IIIF URL generation#49
donaldgray merged 3 commits into
mainfrom
feature/forwarded_config

Conversation

@donaldgray
Copy link
Copy Markdown
Member

Summary

  • Adds AllowedCustomHosts config - a whitelist of hostnames accepted from X-Forwarded-Host. When a request carries a matching header, the forwarded host (and job ID extracted from X-Forwarded-Path) replace the internal values in all generated IIIF self-referencing URLs.
  • Fixes annotation and context IDs in search responses including the ?q= query string mid-path - child resource IDs now use the path-only URL, while the response id still includes the query string per the IIIF spec.
  • Documents AllowedCustomHosts, AllowFileImageProxy, and the forwarded-header rewriting behaviour in docs/search-api.md.

Test plan

  • Existing unit tests pass (494 tests green)
  • Search v1/v2 annotation id values no longer contain ?q= - confirmed by three new handler tests (Handle_WithQueryInSelfUrl_*)
  • Deploy behind a proxy with X-Forwarded-Host set to a whitelisted host and verify IIIF response id values use the forwarded host
  • Verify X-Forwarded-Host from a non-whitelisted host is ignored

Generated with Claude Code

donaldgray and others added 3 commits May 28, 2026 17:06
Search API can be served via CloudFront custom domains that rewrite the
host and path. EndpointHelpers.Resolve reads both headers once, validates
the host against AllowedCustomHosts, extracts the effective job id from
X-Forwarded-Path (by stripping the route prefix), and returns a
ResolvedRequest(EffectiveId, SelfUrl, BaseUrl). All endpoint call sites
collapse to a single Resolve call.

TextAugmentedRequest gains an optional UrlId so the handler can use the
forwarded id for service descriptor URLs while still loading artefacts
by the canonical storage id.

X-Forwarded-Proto is handled by ForwardedHeadersMiddleware; trust is
restricted via KnownNetworks/KnownProxies config keys so on-prem
deployments can pin trusted proxy IPs/CIDRs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The ?q= param was being embedded mid-path in annotation and context IDs
because SelfUrl (which includes the query) was used as the base for both
the response id and child resource IDs.

Adds ResourceUrl (path only, no query) to ResolvedRequest and threads it
through SearchRequest, SearchV2Request, and SearchHandlerBase so annotation
and context IDs are built from the clean path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds AllowFileImageProxy and AllowedCustomHosts to the configuration
table, plus a new section explaining X-Forwarded-Host / X-Forwarded-Path
behaviour and the allowlist requirement.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@donaldgray donaldgray merged commit 9734030 into main May 28, 2026
4 checks passed
@donaldgray donaldgray deleted the feature/forwarded_config branch May 28, 2026 16:27
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