Skip to content

Added HTTP-client typed Either<T,E> response mapping - #716

Open
GoodforGod wants to merge 3 commits into
masterfrom
feature/http-client-response-code-mapper-range
Open

Added HTTP-client typed Either<T,E> response mapping#716
GoodforGod wants to merge 3 commits into
masterfrom
feature/http-client-response-code-mapper-range

Conversation

@GoodforGod

@GoodforGod GoodforGod commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Added typed Either response mapping for HTTP clients with JSON tag propagation

EN

Added support for declarative HTTP clients to map HttpResponseEntity<Either<T, E>> across all response statuses. This enables hand-written clients to receive typed successful and error bodies without custom response mappers, while keeping the existing default behavior for ordinary return types.


RU

Добавлена поддержка HttpResponseEntity<Either<T, E>> в декларативных HTTP-клиентах: теперь успешные и ошибочные ответы можно получать типизированно без собственного маппера ответа. Для обычных возвращаемых типов старое поведение сохраняется.


  • Added built-in client response mapping for Either<T, E> where 2xx responses are mapped to the left branch and non-2xx responses are mapped to the right branch.
  • Added HttpResponseEntity<Either<T, E>> handling so response status and headers are preserved while the body is mapped into the appropriate Either branch.
  • Added JSON tag propagation for both @Json HttpResponseEntity<Either<T, E>> and HttpResponseEntity<Either<@Json T, @Json E>>.
  • Removed the previously introduced @ResponseCodeMapperRange API since the typed Either flow covers the intended use case without another annotation.

Design

The new mapping path is owned by the HTTP client response mapper layer. HttpClientEitherResponseMapper<T, E> delegates body decoding to two existing HttpClientResponseMapper instances: one for successful statuses and one for error statuses.

HttpResponseEntity<Either<Pet, ErrorResponse>> response = client.createPet(pet);

For status codes in the 200..299 range, the response body is mapped with the success mapper and returned as Either.left(...). For all other status codes, the response body is mapped with the error mapper and returned as Either.right(...). HttpResponseEntity keeps the original status code and headers.

JSON mapping works in two forms. A top-level @Json applies the same tag to both Either branches:

@Json
HttpResponseEntity<Either<Pet, ErrorResponse>> createPet(Pet pet);

Per-branch annotations allow different tagged mappers for each side:

HttpResponseEntity<Either<@Json Pet, @Json ErrorResponse>> createPet(Pet pet);

Java annotation processor and KSP both synthesize the required graph dependencies so users do not need to write a custom mapper for the common JSON case. Existing behavior remains unchanged for non-Either return types: non-2xx responses still throw HttpClientResponseException unless explicit response code mapping is configured.

@GoodforGod GoodforGod added this to the v2.0.0 milestone Jul 12, 2026
@GoodforGod
GoodforGod requested a review from Squiry July 12, 2026 11:49
@GoodforGod GoodforGod added new feature New feature request module: http Related to HTTP module labels Jul 12, 2026
@github-actions

github-actions Bot commented Jul 12, 2026

Copy link
Copy Markdown

Test Results

140 tests   140 ✅  10m 38s ⏱️
  5 suites    0 💤
  5 files      0 ❌

Results for commit d5aabe6.

♻️ This comment has been updated with latest results.

@github-actions

Copy link
Copy Markdown

Dependency Vulnerability Report

Found 2 vulnerabilities across 2 coordinates.

Checked 159 Maven coordinates from gradle/libs.versions.toml via OSV.dev.

com.fasterxml.jackson.core:jackson-databind:2.22.0

Aliases: jackson2-databind

  • GHSA-5jmj-h7xm-6q6v, CVE-2026-54515: jackson-databind has case-insensitive deserialization bypasses per-property @JsonIgnoreProperties

io.undertow:undertow-core:2.4.2.Final

Aliases: undertow-core

  • GHSA-3x3v-w654-m28m, CVE-2026-3260: Undertow: Denial of Service via Multipart/Form-Data Parsing on HTTP GET Requests

@github-actions

Copy link
Copy Markdown

Dependency Update Report

Update level: patch

Found 12 dependency updates.

gradle/libs.versions.toml

  • jackson: 3.2.0 -> 3.2.1
  • jdbc-postgresql (org.postgresql:postgresql, inline:127): 42.7.12 -> 42.7.13
  • grpc-java: 1.82.1 -> 1.82.2
  • byte-buddy: 1.18.10 -> 1.18.11
  • s3client-aws (software.amazon.awssdk:s3, inline:253): 2.46.18 -> 2.46.21
  • ksp: 2.3.9 -> 2.3.10
  • netty: 4.2.15.Final -> 4.2.16.Final
  • zeebe: 8.9.11 -> 8.9.12
  • logback: 1.5.37 -> 1.5.38
  • jackson2-coreline: 2.22.0 -> 2.22.1
  • undertow-servlet: 2.3.25.Final -> 2.3.26.Final

buildSrc/build.gradle

  • line 7: tools.jackson.core:jackson-databind (jackson-databind) 3.2.0 -> 3.2.1

…an inclusive status range.

- Support `HttpResponseEntity<Either<T, E>>` in declarative HTTP clients so non-2xx responses can be mapped into typed error values instead of always throwing. Add built-in `HttpClientEitherResponseMapper` and Kora extension wiring for both Java annotation processor and KSP.
- Also support JSON-tagged Either mapping variants:
- `@Json HttpResponseEntity<Either<T, E>>`
- `HttpResponseEntity<Either<@JSON T, @JSON E>>`
- Cover Java and KSP scenarios with tests for range mapping, all-status Either entity mapping, top-level JSON tags, and per-Either-argument JSON tags.
Added support for mapping `HttpResponseEntity<Either<T, E>>` across all response statuses, keeping successful responses in the left side and error responses in the right side.

- Added built-in client response mapper support for `Either<T, E>` and `HttpResponseEntity<Either<T, E>>`.
- Added JSON tag propagation for both top-level `@Json` response mappings and per-branch `Either<@JSON T, @JSON E>` mappings.
- Removed `@ResponseCodeMapperRange` before release since the explicit range annotation was redundant with the new typed Either response flow.
@GoodforGod
GoodforGod force-pushed the feature/http-client-response-code-mapper-range branch from d5aabe6 to 987a382 Compare July 23, 2026 13:56
@GoodforGod GoodforGod changed the title Added HTTP-client @ResponseCodeMapperRange for mapping default responses in status range Added HTTP-client typed Either<T,E> response mapping Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

module: http Related to HTTP module new feature New feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant