From 66b293c299210770b5871165d26e479917dbb1a1 Mon Sep 17 00:00:00 2001 From: Anton Parkhomenko Date: Fri, 30 Jul 2021 17:58:06 +0300 Subject: [PATCH] http4s: pass apikey for schema-list method (close #166) --- .../registries/Http4sRegistryLookup.scala | 55 ++++++++++++++----- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/modules/http4s/src/main/scala/com.snowplowanalytics.iglu/client/resolver/registries/Http4sRegistryLookup.scala b/modules/http4s/src/main/scala/com.snowplowanalytics.iglu/client/resolver/registries/Http4sRegistryLookup.scala index d9de66fc..490337e4 100644 --- a/modules/http4s/src/main/scala/com.snowplowanalytics.iglu/client/resolver/registries/Http4sRegistryLookup.scala +++ b/modules/http4s/src/main/scala/com.snowplowanalytics.iglu/client/resolver/registries/Http4sRegistryLookup.scala @@ -18,7 +18,7 @@ import cats.effect.Sync import io.circe.Json import org.http4s.circe._ import org.http4s.client.{Client => HttpClient} -import org.http4s.{EntityDecoder, Header, Headers, Request, Uri} +import org.http4s.{EntityDecoder, Header, Headers, Request, Status, Uri} import com.snowplowanalytics.iglu.core.{SchemaKey, SchemaList} import com.snowplowanalytics.iglu.core.circe.CirceIgluCodecs._ import org.http4s.Method.GET @@ -55,14 +55,10 @@ object Http4sRegistryLookup { ): EitherT[F, RegistryError, Json] = for { uri <- EitherT.fromEither[F](toPath(http, key)) - headers = - http.apikey.fold[Headers](Headers.empty)(apikey => Headers.of(Header("apikey", apikey))) - request = Request[F](method = GET, uri = uri, headers = headers) - json <- EitherT(Sync[F].attempt(client.expect[Json](request))).leftMap[RegistryError] { e => - val error = s"Unexpected exception fetching: $e" - RegistryError.RepoFailure(error) - } - } yield json + headers = http.apikey.fold[Headers](Headers.empty)(apikey => Headers.of(Header("apikey", apikey))) + response = runRequest[F, Json](client, Request[F](method = GET, uri = uri, headers = headers)) + result <- EitherT(response) + } yield result def httpList[F[_]: Sync]( client: HttpClient[F], @@ -73,11 +69,10 @@ object Http4sRegistryLookup { ): EitherT[F, RegistryError, SchemaList] = for { uri <- EitherT.fromEither[F](toSubpath(http, vendor, name, model)) - sl <- EitherT(Sync[F].attempt(client.expect[SchemaList](uri))).leftMap[RegistryError] { e => - val error = s"Unexpected exception listing: $e" - RegistryError.RepoFailure(error) - } - } yield sl + headers = http.apikey.fold[Headers](Headers.empty)(apikey => Headers.of(Header("apikey", apikey))) + response = runRequest[F, SchemaList](client, Request[F](method = GET, uri = uri, headers = headers)) + result <- EitherT(response) + } yield result def toPath(cxn: Registry.HttpConnection, key: SchemaKey): Either[RegistryError, Uri] = Uri @@ -94,5 +89,37 @@ object Http4sRegistryLookup { .fromString(s"${cxn.uri.toString.stripSuffix("/")}/schemas/$vendor/$name/jsonschema/$model") .leftMap(e => RegistryError.ClientFailure(e.message)) + def runRequest[F[_]: Sync, A: EntityDecoder[F, *]](client: HttpClient[F], req: Request[F]): F[Either[RegistryError, A]] = { + val responseResult = client.run(req).use[F, Either[RegistryError, A]] { + case Status.Successful(response) => + response.as[A].map(_.asRight) + case Status.ClientError(response) if response.status.code == 404 => + (RegistryError.NotFound: RegistryError).asLeft[A].pure[F] + case Status.ServerError(response) => + response.bodyText.compile.string.map { body => + val error = s"Unexpected server response: $body" + RegistryError.RepoFailure(error).asLeft + } + case Status.ClientError(response) => + response.bodyText.compile.string.map { body => + val error = s"Unexpected server response: $body" + RegistryError.ClientFailure(error).asLeft + } + case response => + response.bodyText.compile.string.map { body => + val error = s"Unexpected response: $body" + RegistryError.ClientFailure(error).asLeft + } + } + + responseResult.attempt.map { + case Right(result) => + result + case Left(exception) => + val error = Option(exception.getMessage).getOrElse(exception.toString) + RegistryError.ClientFailure(error).asLeft + } + } + implicit def schemaListDecoder[F[_]: Sync]: EntityDecoder[F, SchemaList] = jsonOf[F, SchemaList] }