/** * Generated by API Builder - https://www.apibuilder.io * Service version: 0.0.1-dev * User agent: apibuilder app.apibuilder.io/chenggit/flowerate/0.0.1-dev/http4s_0_20 */ package io.cheng.flowerate.v0.models { /** * Models rates response from fixer io */ sealed trait FixerRateResponse extends _root_.scala.Product with _root_.scala.Serializable /** * fixer.io error detail inside a failure response * * @param code error code * @param `type` fixer.io error type */ final case class FixerErrorDetail( code: Long, `type`: String ) /** * fixer.io failure response for exchange rate between two currencies * * @param success response status, should be false in this case * @param error error from fixer.io */ final case class FixerRatesFailureResponse( success: Boolean, error: io.cheng.flowerate.v0.models.FixerErrorDetail ) extends FixerRateResponse /** * fixer.io response for exchange rate between two currencies * * @param success response status, should be true in this case * @param base base currency * @param rates target currencies * @param timestamp epoch timestamp of returned exchange rate */ final case class FixerRatesSuccessResponse( success: Boolean, base: io.cheng.flowerate.v0.models.Currency, rates: Map[String, Double], timestamp: Long ) extends FixerRateResponse /** * flowerate response for exchange rate between two currencies * * @param base base currency * @param target targey currency * @param rate exchange rate, target currency to base currency * @param timestamp epoch timestamp of returned exchange rate */ final case class RateBetweenResponse( base: io.cheng.flowerate.v0.models.Currency, target: io.cheng.flowerate.v0.models.Currency, rate: Double, timestamp: Long ) /** * flowerate response for exchange rate for base currency to all currencies * * @param base base currency * @param rates target currencies * @param timestamp epoch timestamp of returned exchange rate */ final case class RateToAllResponse( base: io.cheng.flowerate.v0.models.Currency, rates: Map[String, Double], timestamp: Long ) /** * describe subscribed action and corresponding url of a webhook * * @param currencyRateEvent enum value, currency rate event that this webhook subscribe to * @param url where POST request to when subscribed event happens */ final case class WebhookDetail( currencyRateEvent: io.cheng.flowerate.v0.models.CurrencyRateEvent, url: String ) /** * payload of POST request to register a webhook * * @param clientId user id * @param webhooks a sequence of webhook details */ final case class WebhookRegisterRequest( clientId: String, webhooks: Seq[io.cheng.flowerate.v0.models.WebhookDetail] ) /** * Provides future compatibility in clients - in the future, when a type is added * to the union FixerRateResponse, it will need to be handled in the client code. * This implementation will deserialize these future types as an instance of this * class. * * @param description Information about the type that we received that is undefined in this version of * the client. */ final case class FixerRateResponseUndefinedType( description: String ) extends FixerRateResponse sealed trait Currency extends _root_.scala.Product with _root_.scala.Serializable object Currency { case object Aed extends Currency { override def toString = "AED" } case object Afn extends Currency { override def toString = "AFN" } case object All extends Currency { override def toString = "ALL" } case object Amd extends Currency { override def toString = "AMD" } case object Ang extends Currency { override def toString = "ANG" } case object Aoa extends Currency { override def toString = "AOA" } case object Ars extends Currency { override def toString = "ARS" } case object Aud extends Currency { override def toString = "AUD" } case object Awg extends Currency { override def toString = "AWG" } case object Azn extends Currency { override def toString = "AZN" } case object Bam extends Currency { override def toString = "BAM" } case object Bbd extends Currency { override def toString = "BBD" } case object Bdt extends Currency { override def toString = "BDT" } case object Bgn extends Currency { override def toString = "BGN" } case object Bhd extends Currency { override def toString = "BHD" } case object Bif extends Currency { override def toString = "BIF" } case object Bmd extends Currency { override def toString = "BMD" } case object Bnd extends Currency { override def toString = "BND" } case object Bob extends Currency { override def toString = "BOB" } case object Brl extends Currency { override def toString = "BRL" } case object Bsd extends Currency { override def toString = "BSD" } case object Btc extends Currency { override def toString = "BTC" } case object Btn extends Currency { override def toString = "BTN" } case object Bwp extends Currency { override def toString = "BWP" } case object Byn extends Currency { override def toString = "BYN" } case object Byr extends Currency { override def toString = "BYR" } case object Bzd extends Currency { override def toString = "BZD" } case object Cad extends Currency { override def toString = "CAD" } case object Cdf extends Currency { override def toString = "CDF" } case object Chf extends Currency { override def toString = "CHF" } case object Clf extends Currency { override def toString = "CLF" } case object Clp extends Currency { override def toString = "CLP" } case object Cny extends Currency { override def toString = "CNY" } case object Cop extends Currency { override def toString = "COP" } case object Crc extends Currency { override def toString = "CRC" } case object Cuc extends Currency { override def toString = "CUC" } case object Cup extends Currency { override def toString = "CUP" } case object Cve extends Currency { override def toString = "CVE" } case object Czk extends Currency { override def toString = "CZK" } case object Djf extends Currency { override def toString = "DJF" } case object Dkk extends Currency { override def toString = "DKK" } case object Dop extends Currency { override def toString = "DOP" } case object Dzd extends Currency { override def toString = "DZD" } case object Egp extends Currency { override def toString = "EGP" } case object Ern extends Currency { override def toString = "ERN" } case object Etb extends Currency { override def toString = "ETB" } case object Eur extends Currency { override def toString = "EUR" } case object Fjd extends Currency { override def toString = "FJD" } case object Fkp extends Currency { override def toString = "FKP" } case object Gbp extends Currency { override def toString = "GBP" } case object Gel extends Currency { override def toString = "GEL" } case object Ggp extends Currency { override def toString = "GGP" } case object Ghs extends Currency { override def toString = "GHS" } case object Gip extends Currency { override def toString = "GIP" } case object Gmd extends Currency { override def toString = "GMD" } case object Gnf extends Currency { override def toString = "GNF" } case object Gtq extends Currency { override def toString = "GTQ" } case object Gyd extends Currency { override def toString = "GYD" } case object Hkd extends Currency { override def toString = "HKD" } case object Hnl extends Currency { override def toString = "HNL" } case object Hrk extends Currency { override def toString = "HRK" } case object Htg extends Currency { override def toString = "HTG" } case object Huf extends Currency { override def toString = "HUF" } case object Idr extends Currency { override def toString = "IDR" } case object Ils extends Currency { override def toString = "ILS" } case object Imp extends Currency { override def toString = "IMP" } case object Inr extends Currency { override def toString = "INR" } case object Iqd extends Currency { override def toString = "IQD" } case object Irr extends Currency { override def toString = "IRR" } case object Isk extends Currency { override def toString = "ISK" } case object Jep extends Currency { override def toString = "JEP" } case object Jmd extends Currency { override def toString = "JMD" } case object Jod extends Currency { override def toString = "JOD" } case object Jpy extends Currency { override def toString = "JPY" } case object Kes extends Currency { override def toString = "KES" } case object Kgs extends Currency { override def toString = "KGS" } case object Khr extends Currency { override def toString = "KHR" } case object Kmf extends Currency { override def toString = "KMF" } case object Kpw extends Currency { override def toString = "KPW" } case object Krw extends Currency { override def toString = "KRW" } case object Kwd extends Currency { override def toString = "KWD" } case object Kyd extends Currency { override def toString = "KYD" } case object Kzt extends Currency { override def toString = "KZT" } case object Lak extends Currency { override def toString = "LAK" } case object Lbp extends Currency { override def toString = "LBP" } case object Lkr extends Currency { override def toString = "LKR" } case object Lrd extends Currency { override def toString = "LRD" } case object Lsl extends Currency { override def toString = "LSL" } case object Ltl extends Currency { override def toString = "LTL" } case object Lvl extends Currency { override def toString = "LVL" } case object Lyd extends Currency { override def toString = "LYD" } case object Mad extends Currency { override def toString = "MAD" } case object Mdl extends Currency { override def toString = "MDL" } case object Mga extends Currency { override def toString = "MGA" } case object Mkd extends Currency { override def toString = "MKD" } case object Mmk extends Currency { override def toString = "MMK" } case object Mnt extends Currency { override def toString = "MNT" } case object Mop extends Currency { override def toString = "MOP" } case object Mro extends Currency { override def toString = "MRO" } case object Mur extends Currency { override def toString = "MUR" } case object Mvr extends Currency { override def toString = "MVR" } case object Mwk extends Currency { override def toString = "MWK" } case object Mxn extends Currency { override def toString = "MXN" } case object Myr extends Currency { override def toString = "MYR" } case object Mzn extends Currency { override def toString = "MZN" } case object Nad extends Currency { override def toString = "NAD" } case object Ngn extends Currency { override def toString = "NGN" } case object Nio extends Currency { override def toString = "NIO" } case object Nok extends Currency { override def toString = "NOK" } case object Npr extends Currency { override def toString = "NPR" } case object Nzd extends Currency { override def toString = "NZD" } case object Omr extends Currency { override def toString = "OMR" } case object Pab extends Currency { override def toString = "PAB" } case object Pen extends Currency { override def toString = "PEN" } case object Pgk extends Currency { override def toString = "PGK" } case object Php extends Currency { override def toString = "PHP" } case object Pkr extends Currency { override def toString = "PKR" } case object Pln extends Currency { override def toString = "PLN" } case object Pyg extends Currency { override def toString = "PYG" } case object Qar extends Currency { override def toString = "QAR" } case object Ron extends Currency { override def toString = "RON" } case object Rsd extends Currency { override def toString = "RSD" } case object Rub extends Currency { override def toString = "RUB" } case object Rwf extends Currency { override def toString = "RWF" } case object Sar extends Currency { override def toString = "SAR" } case object Sbd extends Currency { override def toString = "SBD" } case object Scr extends Currency { override def toString = "SCR" } case object Sdg extends Currency { override def toString = "SDG" } case object Sek extends Currency { override def toString = "SEK" } case object Sgd extends Currency { override def toString = "SGD" } case object Shp extends Currency { override def toString = "SHP" } case object Sll extends Currency { override def toString = "SLL" } case object Sos extends Currency { override def toString = "SOS" } case object Srd extends Currency { override def toString = "SRD" } case object Std extends Currency { override def toString = "STD" } case object Svc extends Currency { override def toString = "SVC" } case object Syp extends Currency { override def toString = "SYP" } case object Szl extends Currency { override def toString = "SZL" } case object Thb extends Currency { override def toString = "THB" } case object Tjs extends Currency { override def toString = "TJS" } case object Tmt extends Currency { override def toString = "TMT" } case object Tnd extends Currency { override def toString = "TND" } case object Top extends Currency { override def toString = "TOP" } case object Try extends Currency { override def toString = "TRY" } case object Ttd extends Currency { override def toString = "TTD" } case object Twd extends Currency { override def toString = "TWD" } case object Tzs extends Currency { override def toString = "TZS" } case object Uah extends Currency { override def toString = "UAH" } case object Ugx extends Currency { override def toString = "UGX" } case object Usd extends Currency { override def toString = "USD" } case object Uyu extends Currency { override def toString = "UYU" } case object Uzs extends Currency { override def toString = "UZS" } case object Vef extends Currency { override def toString = "VEF" } case object Vnd extends Currency { override def toString = "VND" } case object Vuv extends Currency { override def toString = "VUV" } case object Wst extends Currency { override def toString = "WST" } case object Xaf extends Currency { override def toString = "XAF" } case object Xag extends Currency { override def toString = "XAG" } case object Xau extends Currency { override def toString = "XAU" } case object Xcd extends Currency { override def toString = "XCD" } case object Xdr extends Currency { override def toString = "XDR" } case object Xof extends Currency { override def toString = "XOF" } case object Xpf extends Currency { override def toString = "XPF" } case object Yer extends Currency { override def toString = "YER" } case object Zar extends Currency { override def toString = "ZAR" } case object Zmk extends Currency { override def toString = "ZMK" } case object Zmw extends Currency { override def toString = "ZMW" } case object Zwl extends Currency { override def toString = "ZWL" } /** * UNDEFINED captures values that are sent either in error or * that were added by the server after this library was * generated. We want to make it easy and obvious for users of * this library to handle this case gracefully. * * We use all CAPS for the variable name to avoid collisions * with the camel cased values above. */ final case class UNDEFINED(override val toString: String) extends Currency /** * all returns a list of all the valid, known values. We use * lower case to avoid collisions with the camel cased values * above. */ val all: scala.List[Currency] = scala.List(Aed, Afn, All, Amd, Ang, Aoa, Ars, Aud, Awg, Azn, Bam, Bbd, Bdt, Bgn, Bhd, Bif, Bmd, Bnd, Bob, Brl, Bsd, Btc, Btn, Bwp, Byn, Byr, Bzd, Cad, Cdf, Chf, Clf, Clp, Cny, Cop, Crc, Cuc, Cup, Cve, Czk, Djf, Dkk, Dop, Dzd, Egp, Ern, Etb, Eur, Fjd, Fkp, Gbp, Gel, Ggp, Ghs, Gip, Gmd, Gnf, Gtq, Gyd, Hkd, Hnl, Hrk, Htg, Huf, Idr, Ils, Imp, Inr, Iqd, Irr, Isk, Jep, Jmd, Jod, Jpy, Kes, Kgs, Khr, Kmf, Kpw, Krw, Kwd, Kyd, Kzt, Lak, Lbp, Lkr, Lrd, Lsl, Ltl, Lvl, Lyd, Mad, Mdl, Mga, Mkd, Mmk, Mnt, Mop, Mro, Mur, Mvr, Mwk, Mxn, Myr, Mzn, Nad, Ngn, Nio, Nok, Npr, Nzd, Omr, Pab, Pen, Pgk, Php, Pkr, Pln, Pyg, Qar, Ron, Rsd, Rub, Rwf, Sar, Sbd, Scr, Sdg, Sek, Sgd, Shp, Sll, Sos, Srd, Std, Svc, Syp, Szl, Thb, Tjs, Tmt, Tnd, Top, Try, Ttd, Twd, Tzs, Uah, Ugx, Usd, Uyu, Uzs, Vef, Vnd, Vuv, Wst, Xaf, Xag, Xau, Xcd, Xdr, Xof, Xpf, Yer, Zar, Zmk, Zmw, Zwl) private val byName: Map[String, Currency] = all.map(x => x.toString.toLowerCase -> x).toMap def apply(value: String): Currency = fromString(value).getOrElse(UNDEFINED(value)) def fromString(value: String): _root_.scala.Option[Currency] = byName.get(value.toLowerCase) } sealed trait CurrencyRateEvent extends _root_.scala.Product with _root_.scala.Serializable object CurrencyRateEvent { case object CurrencyRateChange extends CurrencyRateEvent { override def toString = "CurrencyRateChange" } /** * UNDEFINED captures values that are sent either in error or * that were added by the server after this library was * generated. We want to make it easy and obvious for users of * this library to handle this case gracefully. * * We use all CAPS for the variable name to avoid collisions * with the camel cased values above. */ final case class UNDEFINED(override val toString: String) extends CurrencyRateEvent /** * all returns a list of all the valid, known values. We use * lower case to avoid collisions with the camel cased values * above. */ val all: scala.List[CurrencyRateEvent] = scala.List(CurrencyRateChange) private val byName: Map[String, CurrencyRateEvent] = all.map(x => x.toString.toLowerCase -> x).toMap def apply(value: String): CurrencyRateEvent = fromString(value).getOrElse(UNDEFINED(value)) def fromString(value: String): _root_.scala.Option[CurrencyRateEvent] = byName.get(value.toLowerCase) } } package io.cheng.flowerate.v0.models { package object json { import io.circe.Decoder._ import io.circe.Encoder._ import scala.language.implicitConversions // See below - Make Scala 2.11 Either monadic import scala.util.Try import io.circe.{Json, JsonObject, Encoder, Decoder, DecodingFailure} import io.circe.syntax._ import io.cheng.flowerate.v0.models.json._ // Make Scala 2.11 Either monadic private[v0] implicit def eitherOps[A,B](e: Either[A,B]) = cats.implicits.catsSyntaxEither(e) private[v0] implicit val decodeUUID: Decoder[_root_.java.util.UUID] = Decoder.decodeString.emapTry(str => Try(_root_.java.util.UUID.fromString(str))) private[v0] implicit val encodeUUID: Encoder[_root_.java.util.UUID] = Encoder.encodeString.contramap[_root_.java.util.UUID](uuid => uuid.toString) private[v0] implicit val decodeInstant: Decoder[_root_.java.time.Instant] = Decoder.decodeString.emapTry(str => Try(_root_.java.time.OffsetDateTime.parse(str).toInstant)) private[v0] implicit val encodeInstant: Encoder[_root_.java.time.Instant] = Encoder.encodeString.contramap[_root_.java.time.Instant](_.toString) private[v0] implicit val decodeLocalDate: Decoder[_root_.java.time.LocalDate] = Decoder.decodeString.emapTry(str => Try(_root_.java.time.LocalDate.parse(str))) private[v0] implicit val encodeLocalDate: Encoder[_root_.java.time.LocalDate] = Encoder.encodeString.contramap[_root_.java.time.LocalDate](_.toString) implicit val jsonDecoderFlowerateCurrency: Decoder[io.cheng.flowerate.v0.models.Currency] = Decoder.decodeString.map(io.cheng.flowerate.v0.models.Currency(_)) implicit val jsonEncoderFlowerateCurrency: Encoder[io.cheng.flowerate.v0.models.Currency] = Encoder.encodeString.contramap[io.cheng.flowerate.v0.models.Currency](_.toString) implicit val jsonDecoderFlowerateCurrencyRateEvent: Decoder[io.cheng.flowerate.v0.models.CurrencyRateEvent] = Decoder.decodeString.map(io.cheng.flowerate.v0.models.CurrencyRateEvent(_)) implicit val jsonEncoderFlowerateCurrencyRateEvent: Encoder[io.cheng.flowerate.v0.models.CurrencyRateEvent] = Encoder.encodeString.contramap[io.cheng.flowerate.v0.models.CurrencyRateEvent](_.toString) implicit def decodeFlowerateFixerErrorDetail: Decoder[FixerErrorDetail] = Decoder.instance { c => for { code <- c.downField("code").as[Long] __type__ <- c.downField("type").as[String] } yield { FixerErrorDetail( code = code, `type` = __type__ ) } } implicit def encodeFlowerateFixerErrorDetail: Encoder[FixerErrorDetail] = Encoder.instance { t => Json.fromFields(Seq( Some("code" -> t.code.asJson), Some("type" -> t.`type`.asJson) ).flatten) } implicit def decodeFlowerateFixerRatesFailureResponse: Decoder[FixerRatesFailureResponse] = Decoder.instance { c => for { success <- c.downField("success").as[Boolean] error <- c.downField("error").as[io.cheng.flowerate.v0.models.FixerErrorDetail] } yield { FixerRatesFailureResponse( success = success, error = error ) } } implicit def encodeFlowerateFixerRatesFailureResponse: Encoder[FixerRatesFailureResponse] = Encoder.instance { t => Json.fromFields(Seq( Some("success" -> t.success.asJson), Some("error" -> t.error.asJson) ).flatten) } implicit def decodeFlowerateFixerRatesSuccessResponse: Decoder[FixerRatesSuccessResponse] = Decoder.instance { c => for { success <- c.downField("success").as[Boolean] base <- c.downField("base").as[io.cheng.flowerate.v0.models.Currency] rates <- c.downField("rates").as[Map[String, Double]] timestamp <- c.downField("timestamp").as[Long] } yield { FixerRatesSuccessResponse( success = success, base = base, rates = rates, timestamp = timestamp ) } } implicit def encodeFlowerateFixerRatesSuccessResponse: Encoder[FixerRatesSuccessResponse] = Encoder.instance { t => Json.fromFields(Seq( Some("success" -> t.success.asJson), Some("base" -> t.base.asJson), Some("rates" -> t.rates.asJson), Some("timestamp" -> t.timestamp.asJson) ).flatten) } implicit def decodeFlowerateRateBetweenResponse: Decoder[RateBetweenResponse] = Decoder.instance { c => for { base <- c.downField("base").as[io.cheng.flowerate.v0.models.Currency] target <- c.downField("target").as[io.cheng.flowerate.v0.models.Currency] rate <- c.downField("rate").as[Double] timestamp <- c.downField("timestamp").as[Long] } yield { RateBetweenResponse( base = base, target = target, rate = rate, timestamp = timestamp ) } } implicit def encodeFlowerateRateBetweenResponse: Encoder[RateBetweenResponse] = Encoder.instance { t => Json.fromFields(Seq( Some("base" -> t.base.asJson), Some("target" -> t.target.asJson), Some("rate" -> t.rate.asJson), Some("timestamp" -> t.timestamp.asJson) ).flatten) } implicit def decodeFlowerateRateToAllResponse: Decoder[RateToAllResponse] = Decoder.instance { c => for { base <- c.downField("base").as[io.cheng.flowerate.v0.models.Currency] rates <- c.downField("rates").as[Map[String, Double]] timestamp <- c.downField("timestamp").as[Long] } yield { RateToAllResponse( base = base, rates = rates, timestamp = timestamp ) } } implicit def encodeFlowerateRateToAllResponse: Encoder[RateToAllResponse] = Encoder.instance { t => Json.fromFields(Seq( Some("base" -> t.base.asJson), Some("rates" -> t.rates.asJson), Some("timestamp" -> t.timestamp.asJson) ).flatten) } implicit def decodeFlowerateWebhookDetail: Decoder[WebhookDetail] = Decoder.instance { c => for { currencyRateEvent <- c.downField("currencyRateEvent").as[io.cheng.flowerate.v0.models.CurrencyRateEvent] url <- c.downField("url").as[String] } yield { WebhookDetail( currencyRateEvent = currencyRateEvent, url = url ) } } implicit def encodeFlowerateWebhookDetail: Encoder[WebhookDetail] = Encoder.instance { t => Json.fromFields(Seq( Some("currencyRateEvent" -> t.currencyRateEvent.asJson), Some("url" -> t.url.asJson) ).flatten) } implicit def decodeFlowerateWebhookRegisterRequest: Decoder[WebhookRegisterRequest] = Decoder.instance { c => for { clientId <- c.downField("clientId").as[String] webhooks <- c.downField("webhooks").as[Seq[io.cheng.flowerate.v0.models.WebhookDetail]] } yield { WebhookRegisterRequest( clientId = clientId, webhooks = webhooks ) } } implicit def encodeFlowerateWebhookRegisterRequest: Encoder[WebhookRegisterRequest] = Encoder.instance { t => Json.fromFields(Seq( Some("clientId" -> t.clientId.asJson), Some("webhooks" -> t.webhooks.asJson) ).flatten) } implicit def decodeFlowerateFixerRateResponse: Decoder[FixerRateResponse] = Decoder.instance { c => c.get[io.cheng.flowerate.v0.models.FixerRatesSuccessResponse]("FixerRatesSuccessResponse") orElse c.get[io.cheng.flowerate.v0.models.FixerRatesFailureResponse]("FixerRatesFailureResponse") orElse Right(io.cheng.flowerate.v0.models.FixerRateResponseUndefinedType(c.value.toString)) } implicit def encodeFlowerateFixerRateResponse: Encoder[FixerRateResponse] = Encoder.instance { case t: io.cheng.flowerate.v0.models.FixerRatesSuccessResponse => Json.fromJsonObject(JsonObject.singleton("FixerRatesSuccessResponse", t.asJson)) case t: io.cheng.flowerate.v0.models.FixerRatesFailureResponse => Json.fromJsonObject(JsonObject.singleton("FixerRatesFailureResponse", t.asJson)) case other => sys.error(s"The type[${other.getClass.getName}] has no JSON encoder") } } } package io.cheng.flowerate.v0 { import cats.effect._ import cats.implicits._ import io.circe.syntax._ object Constants { val Namespace = "io.cheng.flowerate.v0" val UserAgent = "apibuilder app.apibuilder.io/chenggit/flowerate/0.0.1-dev/http4s_0_20" val Version = "0.0.1-dev" val VersionMajor = 0 } class Client[F[_]: Sync]( val baseUrl: org.http4s.Uri, auth: scala.Option[io.cheng.flowerate.v0.Authorization] = None, defaultHeaders: Seq[(String, String)] = Nil, httpClient: org.http4s.client.Client[F] ) extends interfaces.Client[F] { import org.http4s.Response import io.cheng.flowerate.v0.models.json._ private lazy val defaultApiHeaders = Seq( ("User-Agent", Constants.UserAgent), ("X-Apidoc-Version", Constants.Version), ("X-Apidoc-Version-Major", Constants.VersionMajor.toString) ) def apiHeaders: Seq[(String, String)] = defaultApiHeaders def modifyRequest(request: org.http4s.Request[F]): org.http4s.Request[F] = request implicit def circeJsonEncoder[F[_]: Sync, A](implicit encoder: io.circe.Encoder[A]) = org.http4s.circe.jsonEncoderOf[F, A] def _executeRequest[T, U]( method: String, path: Seq[String], queryParameters: Seq[(String, String)] = Nil, requestHeaders: Seq[(String, String)] = Nil, body: Option[T] = None, formBody : Option[org.http4s.UrlForm] = None )(handler: org.http4s.Response[F] => F[U] )(implicit encoder: io.circe.Encoder[T]): F[U] = { import org.http4s.QueryParamEncoder._ val m = org.http4s.Method.fromString(method) match { case Right(m) => m case Left(e) => sys.error(e.toString) } val headers = org.http4s.Headers(( apiHeaders ++ defaultHeaders ++ requestHeaders ).groupBy(_._1).map { case (k, l) => org.http4s.Header(k, l.last._2) }.toList) val queryMap = queryParameters.groupBy(_._1).map { case (k, v) => k -> v.map(_._2) } val uri = path.foldLeft(baseUrl){ case (uri, segment) => uri / segment }.setQueryParams(queryMap) val request = org.http4s.Request[F](method = m, uri = uri, headers = headers) val reqAndMaybeAuth = auth.fold(request) { case Authorization.Basic(username, passwordOpt) => { val userpass = s"$username:${passwordOpt.getOrElse("")}" val token = java.util.Base64.getEncoder.encodeToString(userpass.getBytes(java.nio.charset.StandardCharsets.ISO_8859_1)) request.putHeaders(org.http4s.Header("Authorization", s"Basic $token")) } case a => sys.error("Invalid authorization scheme[" + a.getClass + "]") } val reqAndMaybeAuthAndBody = if (formBody.nonEmpty) formBody.fold(reqAndMaybeAuth)(reqAndMaybeAuth.withEntity) else body.fold(reqAndMaybeAuth)(reqAndMaybeAuth.withEntity) httpClient.fetch(modifyRequest(reqAndMaybeAuthAndBody))(handler) } } object Client { import cats.effect._ implicit def circeJsonDecoder[F[_]: Sync, A](implicit decoder: io.circe.Decoder[A]) = org.http4s.circe.jsonOf[F, A] def parseJson[F[_]: Sync, T]( className: String, r: org.http4s.Response[F] )(implicit decoder: io.circe.Decoder[T]): F[T] = r.attemptAs[T].value.flatMap { case Right(value) => Sync[F].pure(value) case Left(error) => Sync[F].raiseError(new io.cheng.flowerate.v0.errors.FailedRequest(r.status.code, s"Invalid json for class[" + className + "]", None, error)) } } sealed trait Authorization extends _root_.scala.Product with _root_.scala.Serializable object Authorization { final case class Basic(username: String, password: Option[String] = None) extends Authorization } package interfaces { trait Client[F[_]] { def baseUrl: org.http4s.Uri } } package errors { final case class FailedRequest(responseCode: Int, message: String, requestUri: Option[_root_.java.net.URI] = None, parent: Exception = null) extends _root_.java.lang.Exception(s"HTTP $responseCode: $message", parent) } }