Skip to content

Commit cf7e498

Browse files
committed
fix: keep HTTP error bodies readable and forward the value slot
ThrowOnHttpErrorStep built the exception from the live response, but the pipeline closes that response (and its body) as soon as the step throws, so the error body was unreadable on the resulting Failure — contradicting the bodySnapshot and stream-on-demand contract. Buffer the error body into a bounded, replayable in-memory body before constructing the exception, capped at HttpException.DEFAULT_SNAPSHOT_BYTES so a large 5xx body cannot exhaust memory. Add a test that the failure's body and bodySnapshot are still readable after the pipeline closes the original. Forward the value slot through the concrete HttpException subclasses so a codegen subclass derived from a concrete type (as the base KDoc describes) can stamp a typed payload; previously only the abstract base accepted it. Single-source the 400..599 error boundary by adding isErrorStatus and fromResponseOrNull to HttpExceptionFactory and having the step use them, instead of redeclaring the range. Tighten the value round-trip test to assertSame, reword a test comment off tracker IDs, and soften the docs so they describe ThrowOnHttpErrorStep as a building block rather than implying a default pipeline wires it. Regenerate the API snapshot.
1 parent ff44640 commit cf7e498

7 files changed

Lines changed: 251 additions & 45 deletions

File tree

docs/http.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -387,11 +387,13 @@ if (!response.status.isSuccess) {
387387
The factory throws `IllegalArgumentException` if called with a status outside 400..599 —
388388
1xx/2xx/3xx outcomes are not exceptions and should not be funneled through this path.
389389

390-
In the recovery-aware pipeline this is wired through `ThrowOnHttpErrorStep`, a
391-
`ResponsePipelineStep` that calls `fromResponse` on a 4xx/5xx response and throws the result.
392-
`ResponsePipeline` converts that throw into a `ResponseOutcome.Failure`, which then flows
393-
through the recovery chain (e.g. `RetryStep`) exactly like a transport failure — and because
394-
the thrown `HttpException` is `Retryable`, retry classification keys off it uniformly.
390+
For the recovery-aware pipeline, `ThrowOnHttpErrorStep` packages this mapping as a
391+
`ResponsePipelineStep`: drop it into a `ResponsePipeline.responseSteps` list and it calls
392+
`fromResponse` on a 4xx/5xx response and throws the result. `ResponsePipeline` converts that
393+
throw into a `ResponseOutcome.Failure`, which then flows through the recovery chain (e.g.
394+
`RetryStep`) exactly like a transport failure — and because the thrown `HttpException` is
395+
`Retryable`, retry classification keys off it uniformly. The step is a building block; no
396+
default pipeline in `sdk-core` assembles it for you.
395397

396398
---
397399

sdk-core/api/sdk-core.api

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,49 +1264,56 @@ public class org/dexpace/sdk/core/http/response/exception/BadGatewayException :
12641264
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
12651265
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
12661266
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1267-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1267+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1268+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
12681269
}
12691270

12701271
public class org/dexpace/sdk/core/http/response/exception/BadRequestException : org/dexpace/sdk/core/http/response/exception/HttpException {
12711272
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
12721273
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
12731274
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1274-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1275+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1276+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
12751277
}
12761278

12771279
public class org/dexpace/sdk/core/http/response/exception/ClientErrorException : org/dexpace/sdk/core/http/response/exception/HttpException {
12781280
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
12791281
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
12801282
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1281-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1283+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1284+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
12821285
}
12831286

12841287
public class org/dexpace/sdk/core/http/response/exception/ConflictException : org/dexpace/sdk/core/http/response/exception/HttpException {
12851288
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
12861289
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
12871290
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1288-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1291+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1292+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
12891293
}
12901294

12911295
public class org/dexpace/sdk/core/http/response/exception/ForbiddenException : org/dexpace/sdk/core/http/response/exception/HttpException {
12921296
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
12931297
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
12941298
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1295-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1299+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1300+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
12961301
}
12971302

12981303
public class org/dexpace/sdk/core/http/response/exception/GatewayTimeoutException : org/dexpace/sdk/core/http/response/exception/HttpException {
12991304
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
13001305
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
13011306
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1302-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1307+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1308+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
13031309
}
13041310

13051311
public class org/dexpace/sdk/core/http/response/exception/GoneException : org/dexpace/sdk/core/http/response/exception/HttpException {
13061312
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
13071313
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
13081314
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1309-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1315+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1316+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
13101317
}
13111318

13121319
public abstract class org/dexpace/sdk/core/http/response/exception/HttpException : java/lang/RuntimeException, org/dexpace/sdk/core/http/response/exception/Retryable {
@@ -1333,20 +1340,24 @@ public final class org/dexpace/sdk/core/http/response/exception/HttpException$Co
13331340
public final class org/dexpace/sdk/core/http/response/exception/HttpExceptionFactory {
13341341
public static final field INSTANCE Lorg/dexpace/sdk/core/http/response/exception/HttpExceptionFactory;
13351342
public static final fun fromResponse (Lorg/dexpace/sdk/core/http/response/Response;)Lorg/dexpace/sdk/core/http/response/exception/HttpException;
1343+
public static final fun fromResponseOrNull (Lorg/dexpace/sdk/core/http/response/Response;)Lorg/dexpace/sdk/core/http/response/exception/HttpException;
1344+
public static final fun isErrorStatus (I)Z
13361345
}
13371346

13381347
public class org/dexpace/sdk/core/http/response/exception/InternalServerErrorException : org/dexpace/sdk/core/http/response/exception/HttpException {
13391348
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
13401349
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
13411350
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1342-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1351+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1352+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
13431353
}
13441354

13451355
public class org/dexpace/sdk/core/http/response/exception/MethodNotAllowedException : org/dexpace/sdk/core/http/response/exception/HttpException {
13461356
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
13471357
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
13481358
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1349-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1359+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1360+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
13501361
}
13511362

13521363
public class org/dexpace/sdk/core/http/response/exception/NetworkException : java/io/IOException, org/dexpace/sdk/core/http/response/exception/Retryable {
@@ -1361,21 +1372,24 @@ public class org/dexpace/sdk/core/http/response/exception/NotFoundException : or
13611372
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
13621373
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
13631374
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1364-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1375+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1376+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
13651377
}
13661378

13671379
public class org/dexpace/sdk/core/http/response/exception/PayloadTooLargeException : org/dexpace/sdk/core/http/response/exception/HttpException {
13681380
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
13691381
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
13701382
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1371-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1383+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1384+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
13721385
}
13731386

13741387
public class org/dexpace/sdk/core/http/response/exception/RequestTimeoutException : org/dexpace/sdk/core/http/response/exception/HttpException {
13751388
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
13761389
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
13771390
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1378-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1391+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1392+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
13791393
}
13801394

13811395
public abstract interface class org/dexpace/sdk/core/http/response/exception/Retryable {
@@ -1386,42 +1400,48 @@ public class org/dexpace/sdk/core/http/response/exception/ServerErrorException :
13861400
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
13871401
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
13881402
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1389-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1403+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1404+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
13901405
}
13911406

13921407
public class org/dexpace/sdk/core/http/response/exception/ServiceUnavailableException : org/dexpace/sdk/core/http/response/exception/HttpException {
13931408
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
13941409
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
13951410
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1396-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1411+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1412+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
13971413
}
13981414

13991415
public class org/dexpace/sdk/core/http/response/exception/TooManyRequestsException : org/dexpace/sdk/core/http/response/exception/HttpException {
14001416
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
14011417
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
14021418
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1403-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1419+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1420+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
14041421
}
14051422

14061423
public class org/dexpace/sdk/core/http/response/exception/UnauthorizedException : org/dexpace/sdk/core/http/response/exception/HttpException {
14071424
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
14081425
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
14091426
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1410-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1427+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1428+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
14111429
}
14121430

14131431
public class org/dexpace/sdk/core/http/response/exception/UnprocessableEntityException : org/dexpace/sdk/core/http/response/exception/HttpException {
14141432
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
14151433
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
14161434
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1417-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1435+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1436+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
14181437
}
14191438

14201439
public class org/dexpace/sdk/core/http/response/exception/UnsupportedMediaTypeException : org/dexpace/sdk/core/http/response/exception/HttpException {
14211440
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;)V
14221441
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;)V
14231442
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;)V
1424-
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1443+
public fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;)V
1444+
public synthetic fun <init> (Lorg/dexpace/sdk/core/http/response/Response;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/Object;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
14251445
}
14261446

14271447
public final class org/dexpace/sdk/core/http/sse/ServerSentEvent {

sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/response/exception/HttpExceptionFactory.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,26 @@ public object HttpExceptionFactory {
6565
private const val SC_SERVER_ERROR_MIN = 500
6666
private const val SC_SERVER_ERROR_MAX = 599
6767

68+
/**
69+
* Whether [code] is in the 400..599 error range this factory maps to an [HttpException].
70+
*
71+
* This is the single source of truth for the error-status boundary; callers that want to
72+
* pre-check before mapping (e.g. a pipeline step that only acts on error responses) should
73+
* use this rather than re-declaring the range.
74+
*/
75+
@JvmStatic
76+
public fun isErrorStatus(code: Int): Boolean = code in SC_CLIENT_ERROR_MIN..SC_SERVER_ERROR_MAX
77+
78+
/**
79+
* Maps [response] to its [HttpException] subclass, or returns `null` when the status is not
80+
* an error (1xx / 2xx / 3xx). Unlike [fromResponse], a non-error status is a no-op rather
81+
* than an [IllegalArgumentException], so this is the convenient form for "map it if it is
82+
* an error" call sites.
83+
*/
84+
@JvmStatic
85+
public fun fromResponseOrNull(response: Response): HttpException? =
86+
if (isErrorStatus(response.status.code)) fromResponse(response) else null
87+
6888
/**
6989
* Returns the [HttpException] subclass that corresponds to [response]'s status code.
7090
*

0 commit comments

Comments
 (0)