Repository navigation
Closed
Description
With propagation: HEADERS (the default), the CD resolver copied almost every client header onto every include call. That broke includes and leaked credentials:
Accept-Encodingwas forwarded. A downstream service with compression on returned a gzipped body, the JDK client doesn't decompress it, and the fetch failed.- Conditional and range headers (
If-None-Match,If-Modified-Since,If-Match,If-Unmodified-Since,If-Range,Range) were forwarded. A downstream service could answer304or206, which the resolver treats as a failure. - Credentials (
Authorization,Cookie, theX-Authenticated-*principal headers) went to every mapped service, partner and third-party APIs included. - Repeated headers were reduced to their first value. Under HTTP/2, cookies are often split across several lines, so the session cookie could be lost.
- Hop-by-hop headers (
TE,Trailer,Transfer-Encoding,Keep-Alive,Proxy-Connection) and the client'sAcceptwere forwarded. - The
X-Disable-Compound-Docslookup was case-sensitive, soX-Disable-Compound-Docs: truefrom a client could be ignored.
Per-type settings were also spread over three maps: mapping, batchSizeMapping and the new trust list.
Header propagation
- Never forwarded: headers that change the response (
Accept,Accept-Encoding,Content-Type, the conditional and range headers,X-Disable-Compound-Docs), hop-by-hop headers, and the client-address headers as before. Include calls ask forapplication/vnd.api+jsonthemselves. - Every value is sent:
CompoundDocsRequest.headersis now a case-insensitiveMap<String, List<String>>. Cookies are joined into oneCookieheader, as HTTP/1.1 requires. - Credentials only where trusted:
jsonapi4j.cd.credentialHeaders(default:Authorization,Cookie,Proxy-Authorization,X-Authenticated-User-Id,X-Authenticated-User-Granted-Scopes,X-Authenticated-Client-Entitlements) go to:- resource types served by this app itself (loopback or
mapping.default), always; - a type mapped to another service only with
propagateCredentials: true.
- resource types served by this app itself (loopback or
DomainSettingsgetspropagateCredentials. The two-argument constructor andof()mean "not trusted", and a customDomainSettingsResolverdecides per route.
One mapping entry per resource type
jsonapi4j:
cd:
mapping:
orders:
url: https://orders.internal/jsonapi # served by another service
maxBatchSize: 50
propagateCredentials: true
rates:
url: https://partner.example.com/jsonapi # no credentials by default
countries:
maxBatchSize: 20 # same-app type: no url, batch size only
default:
url: https://api.internal:8443/jsonapi # this app, when loopback isn't reachable- Validation points at the exact key:
- an entry needs
urlormaxBatchSize; urlmust be an absolute http(s) URL;maxBatchSizemust be positive;propagateCredentialswithout aurlis rejected;- the reserved
defaultentry takes onlyurl.
- an entry needs
- The standalone
DefaultDomainSettingsResolvernow wraps aMap<String, DomainSettings>. - The sample apps' illustrative
localhostmappings become batch-size-only entries, with a commented-out example of a remote service.
Breaking changes
- Keys renamed:
mapping.<type>becomesmapping.<type>.url;batchSizeMapping.<type>becomesmapping.<type>.maxBatchSize;mapping.defaultbecomesmapping.default.url(env varJSONAPI4J_CD_MAPPING_DEFAULT_URL).
- Credentials: remote mapped services no longer receive the client's credentials unless
propagateCredentials: true. - No longer forwarded downstream: the client's
Accept,Accept-Encoding, conditional andRangeheaders. - Standalone API:
DefaultDomainSettingsResolver.from(...)is removed;CompoundDocsRequestheaders becomeMap<String, List<String>>;CompoundDocsResolverConfiggains acredentialHeadersargument.
Tests
- The HTTP client tested against a local server: headers that change the response are replaced, credentials are left out for an untrusted destination and sent (with cookies joined) to a trusted one, and repeated headers arrive with every value.
- Case-insensitive header lookup.
- Trust for the app's own routes in fallback routing.
mappingvalidation and thedomainSettings()/maxBatchSize()derivation.
Docs: the CD plugin page (property rows, a full mapping example, a new "Header propagation" section, updated base-URL and limitations sections), the standalone resolver docs, configuration.md, and the Claude Code plugin references.
Not verified: Quarkus environment-variable binding for a nested mapping entry.
Metadata
Metadata
Assignees
Labels
No labels
Activity
#217: CD: forward only safe headers, send credentials only to trusted…