diff options
author | Jakob Odersky <jakob@driver.xyz> | 2017-07-12 22:26:07 -0700 |
---|---|---|
committer | Jakob Odersky <jakob@driver.xyz> | 2017-07-12 22:30:35 -0700 |
commit | 3e700be0b7df8022627b1f46890f3e3dad3fa54b (patch) | |
tree | 0066df95d2a2f033faf9e3e0f9eca92c9c1aad31 /src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala | |
parent | f9ac0adf5c3bcfcde03bd3ea2bc2471b0d0f99fe (diff) | |
download | rest-query-3e700be0b7df8022627b1f46890f3e3dad3fa54b.tar.gz rest-query-3e700be0b7df8022627b1f46890f3e3dad3fa54b.tar.bz2 rest-query-3e700be0b7df8022627b1f46890f3e3dad3fa54b.zip |
Handle errors by failing futures in REST services
Diffstat (limited to 'src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala')
-rw-r--r-- | src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala | 47 |
1 files changed, 20 insertions, 27 deletions
diff --git a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala index 7d2838b..bd9580a 100644 --- a/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala +++ b/src/main/scala/xyz/driver/pdsuidomain/services/rest/RestHelper.scala @@ -1,10 +1,8 @@ package xyz.driver.pdsuidomain.services.rest -import java.lang.RuntimeException - import scala.concurrent.{ExecutionContext, Future} -import akka.http.scaladsl.model.{HttpMethods, HttpRequest, HttpResponse, ResponseEntity, StatusCode, StatusCodes, Uri} +import akka.http.scaladsl.model.{HttpResponse, ResponseEntity, StatusCodes, Uri} import akka.http.scaladsl.unmarshalling.{Unmarshal, Unmarshaller} import akka.stream.Materializer import xyz.driver.core.rest.ServiceRequestContext @@ -17,7 +15,8 @@ import xyz.driver.pdsuicommon.db.{ Sorting, SortingOrder } -import xyz.driver.pdsuicommon.error.DomainError +import xyz.driver.pdsuicommon.serialization.PlayJsonSupport +import xyz.driver.pdsuicommon.error._ trait RestHelper { @@ -30,9 +29,6 @@ trait RestHelper { protected def endpointUri(baseUri: Uri, path: String, query: Seq[(String, String)]) = baseUri.withPath(Uri.Path(path)).withQuery(Uri.Query(query: _*)) - def get(baseUri: Uri, path: String, query: Seq[(String, String)] = Seq.empty): HttpRequest = - HttpRequest(HttpMethods.GET, endpointUri(baseUri, path, query)) - def sortingQuery(sorting: Option[Sorting]): Seq[(String, String)] = { def dimensionQuery(dimension: Sorting.Dimension) = { val ord = dimension.order match { @@ -97,33 +93,30 @@ trait RestHelper { * @param unmarshaller An unmarshaller that converts a successful response to an api reply. */ def apiResponse[ApiReply, DomainReply](response: HttpResponse)(successMapper: ApiReply => DomainReply)( - errorMapper: PartialFunction[DomainError, DomainReply] = PartialFunction.empty)( implicit unmarshaller: Unmarshaller[ResponseEntity, ApiReply]): Future[DomainReply] = { - val domainErrors: Map[StatusCode, DomainError] = Map( - StatusCodes.Unauthorized -> new DomainError.AuthenticationError { - override protected def userMessage: String = "unauthorized" - }, // 401 - StatusCodes.Forbidden -> new DomainError.AuthorizationError { - override protected def userMessage: String = "forbidden" - }, // 403 - StatusCodes.NotFound -> new DomainError.NotFoundError { - override protected def userMessage: String = "not found" - } // 404 - ) + def extractErrorMessage(response: HttpResponse): Future[String] = { + import PlayJsonSupport._ + Unmarshal(response.entity) + .to[ErrorsResponse.ResponseError] + .transform( + _.message, + ex => new DomainException(ex.getMessage) + ) + } if (response.status.isSuccess) { val reply = Unmarshal(response.entity).to[ApiReply] reply.map(successMapper) } else { - val domainError = domainErrors.get(response.status) - domainError.flatMap(errorMapper.lift) match { - case Some(error) => Future.successful(error) - case None => - Future.failed( - new RuntimeException( - s"Unhandled domain error for HTTP status ${response.status}. Message ${response.entity}") - ) + extractErrorMessage(response).flatMap { message => + Future.failed(response.status match { + case StatusCodes.Unauthorized => new AuthenticationException(message) + case StatusCodes.Forbidden => new AuthorizationException(message) + case StatusCodes.NotFound => new NotFoundException(message) + case other => + new DomainException(s"Unhandled domain error for HTTP status ${other.value}. Message ${message}") + }) } } } |