-
Notifications
You must be signed in to change notification settings - Fork 312
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
56 changed files
with
571 additions
and
462 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +1,56 @@ | ||
package sttp.client4 | ||
|
||
import sttp.model.StatusCode | ||
|
||
import scala.annotation.tailrec | ||
import sttp.model.ResponseMetadata | ||
|
||
/** Used to represent errors, that might occur when handling the response body. Typically, this type is used as the | ||
* left-side of a top-level either (where the right-side represents a successfull request and deserialization). | ||
/** Used to represent errors, that might occur when handling the response body, that was otherwise received | ||
* successfully. | ||
* | ||
* A response exception can itself be one of two cases: | ||
* - [[ResponseException.UnexpectedStatusCode]], when the response code is other than 2xx (or whatever is considered | ||
* "success" by the response handling description); the body is deserialized to `HE` | ||
* - [[ResponseException.DeserializationException]], when there's an error during deserialization (this includes | ||
* deserialization exceptions of both the success and error branches) | ||
* | ||
* A response exception can itself either be one of two cases: | ||
* - a [[HttpError]], when the response code is other than 2xx (or whatever is considered "success" by the response | ||
* handling description); the body is deserialized to `HE` | ||
* - a [[DeserializationException]], when there's an error during deserialization (this might include both | ||
* deserialization exceptions of the success and error branches) | ||
* This type is often used as the left-side of a top-level either (where the right-side represents a successful request | ||
* and deserialization). When thrown/returned when sending a request (e.g. in `...OrFailed` response handling | ||
* descriptions), will be additionally wrapped with a [[SttpClientException.ResponseHandlingException]]. | ||
* | ||
* @tparam HE | ||
* The type of the body to which the response is deserialized, when the response code is different than success | ||
* (typically 2xx status code). | ||
* @tparam DE | ||
* A deserialization-library-specific error type, describing the deserialization error in more detail. | ||
*/ | ||
sealed abstract class ResponseException[+HE, +DE](error: String, cause: Option[Throwable]) | ||
extends Exception(error, cause.orNull) | ||
|
||
/** Represents an http error, where the response was received successfully, but the status code is other than the | ||
* expected one (typically other than 2xx). | ||
* | ||
* @tparam HE | ||
* The type of the body to which the error response is deserialized. | ||
*/ | ||
case class HttpError[+HE](body: HE, statusCode: StatusCode) | ||
extends ResponseException[HE, Nothing](s"statusCode: $statusCode, response: $body", None) | ||
|
||
/** Represents an error that occured during deserialization of `body`. | ||
* | ||
* @tparam DE | ||
* A deserialization-library-specific error type, describing the deserialization error in more detail. | ||
*/ | ||
case class DeserializationException[+DE: ShowError](body: String, error: DE) | ||
extends ResponseException[Nothing, DE]( | ||
implicitly[ShowError[DE]].show(error), | ||
if (error.isInstanceOf[Throwable]) Some(error.asInstanceOf[Throwable]) else None | ||
) | ||
|
||
object HttpError { | ||
@tailrec def find(exception: Throwable): Option[HttpError[_]] = | ||
sealed abstract class ResponseException[+HE]( | ||
error: String, | ||
cause: Option[Throwable], | ||
val response: ResponseMetadata | ||
) extends Exception(error, cause.orNull) | ||
|
||
object ResponseException { | ||
|
||
/** Represents an error, where the response was received successfully, but the status code is other than the expected | ||
* one (typically other than 2xx). | ||
* | ||
* @tparam HE | ||
* The type of the body to which the error response is deserialized. | ||
*/ | ||
case class UnexpectedStatusCode[+HE](body: HE, override val response: ResponseMetadata) | ||
extends ResponseException[HE](s"statusCode: ${response.code}, response: $body", None, response) | ||
|
||
/** Represents an error that occurred during deserialization of `body`. */ | ||
case class DeserializationException(body: String, cause: Exception, override val response: ResponseMetadata) | ||
extends ResponseException[Nothing]( | ||
cause.getMessage(), | ||
Some(cause), | ||
response | ||
) | ||
|
||
// | ||
|
||
@tailrec def find(exception: Throwable): Option[ResponseException[_]] = | ||
Option(exception) match { | ||
case Some(error: HttpError[_]) => Some(error) | ||
case Some(_) => find(exception.getCause) | ||
case None => Option.empty | ||
case Some(e: ResponseException[_]) => Some(e) | ||
case Some(_) => find(exception.getCause) | ||
case None => None | ||
} | ||
} | ||
|
||
trait ShowError[-T] { | ||
def show(t: T): String | ||
} | ||
|
||
object ShowError { | ||
implicit val showErrorMessageFromException: ShowError[Exception] = new ShowError[Exception] { | ||
override def show(t: Exception): String = t.getMessage | ||
} | ||
} |
Oops, something went wrong.