/** * Generated by API Builder - https://www.apibuilder.io * Service version: 0.0.1-dev * User agent: apibuilder app.apibuilder.io/shopr/clickouts-api/0.0.1-dev/play_2_4_client */ package com.shopr.api.clickouts.api.v0.models { /** * Represents an Offer click-out. It contains all the information needed to * properly identify the offer, trace it ot the user navigating from search page, * and relevant information about the offer at the click-out moment (e.g.: price, * lowest price among other offers, etc.) * * @param productId Product identifier * @param seller Seller/Retailer unique identifier * @param sellerProductId Product as identifier given by the seller/retailer * @param price Offer price at the moment of the click-out * @param deepUrl Full product URL at the retailer side * @param lowestPrice Lowest price among all offers * @param highestPrice Seller/Retailer unique identifier * @param offerCount Number of offers * @param offerPosition Offer position among other offers (e.g.: first, second, etc.) * @param categoryId Category where the product was put into * @param tracking Tracking information * @param creationTime When this click-out happened */ final case class Clickout( productId: String, seller: String, sellerProductId: String, price: BigDecimal, deepUrl: String, lowestPrice: BigDecimal, highestPrice: BigDecimal, offerCount: Int = 1, offerPosition: Int, categoryId: String, tracking: com.shopr.api.clickouts.api.v0.models.Tracking, creationTime: _root_.org.joda.time.DateTime ) /** * @param code Machine readable code for this specific error message * @param localizedStringCode A localized description of the error code */ final case class ErrorCode( code: String, localizedStringCode: String ) /** * @param message User-friendly message. * @param errorCodes List of errors that may happened all together. * @param fingerprint The request fingerprint associated with this error. */ final case class ErrorResponse( message: _root_.scala.Option[String] = None, errorCodes: Seq[com.shopr.api.clickouts.api.v0.models.ErrorCode], fingerprint: _root_.scala.Option[String] = None ) /** * Response for ping, health check and version */ final case class Status( response: String ) /** * Series of attributes for tracking purposes * * @param origin Client originating the order request essentially any of the values of the * client_origin enum. * @param referrer Optional page referrer. */ final case class Tracking( ipAddress: String, origin: com.shopr.api.clickouts.api.v0.models.ClientOrigin, userAgent: _root_.scala.Option[String] = None, referrer: _root_.scala.Option[String] = None ) /** * Describes the client where the request for a clickout has originated. */ sealed trait ClientOrigin extends _root_.scala.Product with _root_.scala.Serializable object ClientOrigin { /** * The Shopr website */ case object ShoprWebsite extends ClientOrigin { override def toString = "shopr_website" } /** * The Shopr website, but from a mobile. */ case object ShoprMobileWeb extends ClientOrigin { override def toString = "shopr_mobile_web" } /** * IPhone native application. */ case object ShoprIphone extends ClientOrigin { override def toString = "shopr_iphone" } /** * Native application running on an IPad. */ case object ShoprIpad extends ClientOrigin { override def toString = "shopr_ipad" } /** * Android native application. */ case object ShoprAndroid extends ClientOrigin { override def toString = "shopr_android" } /** * 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 to 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 ClientOrigin /** * 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[ClientOrigin] = scala.List(ShoprWebsite, ShoprMobileWeb, ShoprIphone, ShoprIpad, ShoprAndroid) private val byName: Map[String, ClientOrigin] = all.map(x => x.toString.toLowerCase -> x).toMap def apply(value: String): ClientOrigin = fromString(value).getOrElse(UNDEFINED(value)) def fromString(value: String): _root_.scala.Option[ClientOrigin] = byName.get(value.toLowerCase) } } package com.shopr.api.clickouts.api.v0.models { package object json { import play.api.libs.json.__ import play.api.libs.json.JsString import play.api.libs.json.Writes import play.api.libs.functional.syntax._ import com.shopr.api.clickouts.api.v0.models.json._ private[v0] implicit val jsonReadsUUID: play.api.libs.json.Reads[_root_.java.util.UUID] = __.read[String].map { str => _root_.java.util.UUID.fromString(str) } private[v0] implicit val jsonWritesUUID: play.api.libs.json.Writes[_root_.java.util.UUID] = (x: _root_.java.util.UUID) => play.api.libs.json.JsString(x.toString) private[v0] implicit val jsonReadsJodaDateTime: play.api.libs.json.Reads[_root_.org.joda.time.DateTime] = __.read[String].map { str => _root_.org.joda.time.format.ISODateTimeFormat.dateTimeParser.parseDateTime(str) } private[v0] implicit val jsonWritesJodaDateTime: play.api.libs.json.Writes[_root_.org.joda.time.DateTime] = (x: _root_.org.joda.time.DateTime) => { play.api.libs.json.JsString(_root_.org.joda.time.format.ISODateTimeFormat.dateTime.print(x)) } private[v0] implicit val jsonReadsJodaLocalDate: play.api.libs.json.Reads[_root_.org.joda.time.LocalDate] = __.read[String].map { str => _root_.org.joda.time.format.ISODateTimeFormat.dateTimeParser.parseLocalDate(str) } private[v0] implicit val jsonWritesJodaLocalDate: play.api.libs.json.Writes[_root_.org.joda.time.LocalDate] = (x: _root_.org.joda.time.LocalDate) => { play.api.libs.json.JsString(_root_.org.joda.time.format.ISODateTimeFormat.date.print(x)) } implicit val jsonReadsClickoutsApiClientOrigin: play.api.libs.json.Reads[com.shopr.api.clickouts.api.v0.models.ClientOrigin] = new play.api.libs.json.Reads[com.shopr.api.clickouts.api.v0.models.ClientOrigin] { def reads(js: play.api.libs.json.JsValue): play.api.libs.json.JsResult[com.shopr.api.clickouts.api.v0.models.ClientOrigin] = { js match { case v: play.api.libs.json.JsString => play.api.libs.json.JsSuccess(com.shopr.api.clickouts.api.v0.models.ClientOrigin(v.value)) case _ => { (js \ "value").validate[String] match { case play.api.libs.json.JsSuccess(v, _) => play.api.libs.json.JsSuccess(com.shopr.api.clickouts.api.v0.models.ClientOrigin(v)) case _: play.api.libs.json.JsError => (js \ "client_origin").validate[String] match { case play.api.libs.json.JsSuccess(v, _) => play.api.libs.json.JsSuccess(com.shopr.api.clickouts.api.v0.models.ClientOrigin(v)) case err: play.api.libs.json.JsError => err } } } } } } def jsonWritesClickoutsApiClientOrigin(obj: com.shopr.api.clickouts.api.v0.models.ClientOrigin) = { play.api.libs.json.JsString(obj.toString) } def jsObjectClientOrigin(obj: com.shopr.api.clickouts.api.v0.models.ClientOrigin) = { play.api.libs.json.Json.obj("value" -> play.api.libs.json.JsString(obj.toString)) } implicit def jsonWritesClickoutsApiClientOrigin: play.api.libs.json.Writes[ClientOrigin] = { (obj: com.shopr.api.clickouts.api.v0.models.ClientOrigin) => { com.shopr.api.clickouts.api.v0.models.json.jsonWritesClickoutsApiClientOrigin(obj) } } implicit def jsonReadsClickoutsApiClickout: play.api.libs.json.Reads[com.shopr.api.clickouts.api.v0.models.Clickout] = { for { productId <- (__ \ "productId").read[String] seller <- (__ \ "seller").read[String] sellerProductId <- (__ \ "sellerProductId").read[String] price <- (__ \ "price").read[BigDecimal] deepUrl <- (__ \ "deepUrl").read[String] lowestPrice <- (__ \ "lowestPrice").read[BigDecimal] highestPrice <- (__ \ "highestPrice").read[BigDecimal] offerCount <- (__ \ "offerCount").read[Int] offerPosition <- (__ \ "offerPosition").read[Int] categoryId <- (__ \ "categoryId").read[String] tracking <- (__ \ "tracking").read[com.shopr.api.clickouts.api.v0.models.Tracking] creationTime <- (__ \ "creationTime").read[_root_.org.joda.time.DateTime] } yield Clickout(productId, seller, sellerProductId, price, deepUrl, lowestPrice, highestPrice, offerCount, offerPosition, categoryId, tracking, creationTime) } def jsObjectClickout(obj: com.shopr.api.clickouts.api.v0.models.Clickout): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "productId" -> play.api.libs.json.JsString(obj.productId), "seller" -> play.api.libs.json.JsString(obj.seller), "sellerProductId" -> play.api.libs.json.JsString(obj.sellerProductId), "price" -> play.api.libs.json.JsNumber(obj.price), "deepUrl" -> play.api.libs.json.JsString(obj.deepUrl), "lowestPrice" -> play.api.libs.json.JsNumber(obj.lowestPrice), "highestPrice" -> play.api.libs.json.JsNumber(obj.highestPrice), "offerCount" -> play.api.libs.json.JsNumber(obj.offerCount), "offerPosition" -> play.api.libs.json.JsNumber(obj.offerPosition), "categoryId" -> play.api.libs.json.JsString(obj.categoryId), "tracking" -> com.shopr.api.clickouts.api.v0.models.json.jsObjectTracking(obj.tracking), "creationTime" -> play.api.libs.json.JsString(_root_.org.joda.time.format.ISODateTimeFormat.dateTime.print(obj.creationTime)) ) } implicit def jsonWritesClickoutsApiClickout: play.api.libs.json.Writes[Clickout] = { (obj: com.shopr.api.clickouts.api.v0.models.Clickout) => { com.shopr.api.clickouts.api.v0.models.json.jsObjectClickout(obj) } } implicit def jsonReadsClickoutsApiErrorCode: play.api.libs.json.Reads[com.shopr.api.clickouts.api.v0.models.ErrorCode] = { for { code <- (__ \ "code").read[String] localizedStringCode <- (__ \ "localized_string_code").read[String] } yield ErrorCode(code, localizedStringCode) } def jsObjectErrorCode(obj: com.shopr.api.clickouts.api.v0.models.ErrorCode): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "code" -> play.api.libs.json.JsString(obj.code), "localized_string_code" -> play.api.libs.json.JsString(obj.localizedStringCode) ) } implicit def jsonWritesClickoutsApiErrorCode: play.api.libs.json.Writes[ErrorCode] = { (obj: com.shopr.api.clickouts.api.v0.models.ErrorCode) => { com.shopr.api.clickouts.api.v0.models.json.jsObjectErrorCode(obj) } } implicit def jsonReadsClickoutsApiErrorResponse: play.api.libs.json.Reads[com.shopr.api.clickouts.api.v0.models.ErrorResponse] = { for { message <- (__ \ "message").readNullable[String] errorCodes <- (__ \ "error_codes").read[Seq[com.shopr.api.clickouts.api.v0.models.ErrorCode]] fingerprint <- (__ \ "fingerprint").readNullable[String] } yield ErrorResponse(message, errorCodes, fingerprint) } def jsObjectErrorResponse(obj: com.shopr.api.clickouts.api.v0.models.ErrorResponse): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "error_codes" -> play.api.libs.json.Json.toJson(obj.errorCodes) ) ++ (obj.message match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("message" -> play.api.libs.json.JsString(x)) }) ++ (obj.fingerprint match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("fingerprint" -> play.api.libs.json.JsString(x)) }) } implicit def jsonWritesClickoutsApiErrorResponse: play.api.libs.json.Writes[ErrorResponse] = { (obj: com.shopr.api.clickouts.api.v0.models.ErrorResponse) => { com.shopr.api.clickouts.api.v0.models.json.jsObjectErrorResponse(obj) } } implicit def jsonReadsClickoutsApiStatus: play.api.libs.json.Reads[com.shopr.api.clickouts.api.v0.models.Status] = { (__ \ "response").read[String].map { x => Status(response = x) } } def jsObjectStatus(obj: com.shopr.api.clickouts.api.v0.models.Status): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "response" -> play.api.libs.json.JsString(obj.response) ) } implicit def jsonWritesClickoutsApiStatus: play.api.libs.json.Writes[Status] = { (obj: com.shopr.api.clickouts.api.v0.models.Status) => { com.shopr.api.clickouts.api.v0.models.json.jsObjectStatus(obj) } } implicit def jsonReadsClickoutsApiTracking: play.api.libs.json.Reads[com.shopr.api.clickouts.api.v0.models.Tracking] = { for { ipAddress <- (__ \ "ipAddress").read[String] origin <- (__ \ "origin").read[com.shopr.api.clickouts.api.v0.models.ClientOrigin] userAgent <- (__ \ "userAgent").readNullable[String] referrer <- (__ \ "referrer").readNullable[String] } yield Tracking(ipAddress, origin, userAgent, referrer) } def jsObjectTracking(obj: com.shopr.api.clickouts.api.v0.models.Tracking): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "ipAddress" -> play.api.libs.json.JsString(obj.ipAddress), "origin" -> play.api.libs.json.JsString(obj.origin.toString) ) ++ (obj.userAgent match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("userAgent" -> play.api.libs.json.JsString(x)) }) ++ (obj.referrer match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("referrer" -> play.api.libs.json.JsString(x)) }) } implicit def jsonWritesClickoutsApiTracking: play.api.libs.json.Writes[Tracking] = { (obj: com.shopr.api.clickouts.api.v0.models.Tracking) => { com.shopr.api.clickouts.api.v0.models.json.jsObjectTracking(obj) } } } } package com.shopr.api.clickouts.api.v0 { object Bindables { import play.api.mvc.{PathBindable, QueryStringBindable} // import models directly for backwards compatibility with prior versions of the generator import Core._ import Models._ object Core { implicit def pathBindableDateTimeIso8601(implicit stringBinder: QueryStringBindable[String]): PathBindable[_root_.org.joda.time.DateTime] = ApibuilderPathBindable(ApibuilderTypes.dateTimeIso8601) implicit def queryStringBindableDateTimeIso8601(implicit stringBinder: QueryStringBindable[String]): QueryStringBindable[_root_.org.joda.time.DateTime] = ApibuilderQueryStringBindable(ApibuilderTypes.dateTimeIso8601) implicit def pathBindableDateIso8601(implicit stringBinder: QueryStringBindable[String]): PathBindable[_root_.org.joda.time.LocalDate] = ApibuilderPathBindable(ApibuilderTypes.dateIso8601) implicit def queryStringBindableDateIso8601(implicit stringBinder: QueryStringBindable[String]): QueryStringBindable[_root_.org.joda.time.LocalDate] = ApibuilderQueryStringBindable(ApibuilderTypes.dateIso8601) } object Models { import com.shopr.api.clickouts.api.v0.models._ val clientOriginConverter: ApibuilderTypeConverter[com.shopr.api.clickouts.api.v0.models.ClientOrigin] = new ApibuilderTypeConverter[com.shopr.api.clickouts.api.v0.models.ClientOrigin] { override def convert(value: String): com.shopr.api.clickouts.api.v0.models.ClientOrigin = com.shopr.api.clickouts.api.v0.models.ClientOrigin(value) override def convert(value: com.shopr.api.clickouts.api.v0.models.ClientOrigin): String = value.toString override def example: com.shopr.api.clickouts.api.v0.models.ClientOrigin = com.shopr.api.clickouts.api.v0.models.ClientOrigin.ShoprWebsite override def validValues: Seq[com.shopr.api.clickouts.api.v0.models.ClientOrigin] = com.shopr.api.clickouts.api.v0.models.ClientOrigin.all } implicit def pathBindableClientOrigin(implicit stringBinder: QueryStringBindable[String]): PathBindable[com.shopr.api.clickouts.api.v0.models.ClientOrigin] = ApibuilderPathBindable(clientOriginConverter) implicit def queryStringBindableClientOrigin(implicit stringBinder: QueryStringBindable[String]): QueryStringBindable[com.shopr.api.clickouts.api.v0.models.ClientOrigin] = ApibuilderQueryStringBindable(clientOriginConverter) } trait ApibuilderTypeConverter[T] { def convert(value: String): T def convert(value: T): String def example: T def validValues: Seq[T] = Nil def errorMessage(key: String, value: String, ex: java.lang.Exception): String = { val base = s"Invalid value '$value' for parameter '$key'. " validValues.toList match { case Nil => base + "Ex: " + convert(example) case values => base + ". Valid values are: " + values.mkString("'", "', '", "'") } } } object ApibuilderTypes { val dateTimeIso8601: ApibuilderTypeConverter[_root_.org.joda.time.DateTime] = new ApibuilderTypeConverter[_root_.org.joda.time.DateTime] { override def convert(value: String): _root_.org.joda.time.DateTime = _root_.org.joda.time.format.ISODateTimeFormat.dateTimeParser.parseDateTime(value) override def convert(value: _root_.org.joda.time.DateTime): String = _root_.org.joda.time.format.ISODateTimeFormat.dateTime.print(value) override def example: _root_.org.joda.time.DateTime = _root_.org.joda.time.DateTime.now } val dateIso8601: ApibuilderTypeConverter[_root_.org.joda.time.LocalDate] = new ApibuilderTypeConverter[_root_.org.joda.time.LocalDate] { override def convert(value: String): _root_.org.joda.time.LocalDate = _root_.org.joda.time.format.ISODateTimeFormat.dateTimeParser.parseLocalDate(value) override def convert(value: _root_.org.joda.time.LocalDate): String = _root_.org.joda.time.format.ISODateTimeFormat.date.print(value) override def example: _root_.org.joda.time.LocalDate = _root_.org.joda.time.LocalDate.now } } final case class ApibuilderQueryStringBindable[T]( converters: ApibuilderTypeConverter[T] ) extends QueryStringBindable[T] { override def bind(key: String, params: Map[String, Seq[String]]): _root_.scala.Option[_root_.scala.Either[String, T]] = { params.getOrElse(key, Nil).headOption.map { v => try { Right( converters.convert(v) ) } catch { case ex: java.lang.Exception => Left( converters.errorMessage(key, v, ex) ) } } } override def unbind(key: String, value: T): String = { s"$key=${converters.convert(value)}" } } final case class ApibuilderPathBindable[T]( converters: ApibuilderTypeConverter[T] ) extends PathBindable[T] { override def bind(key: String, value: String): _root_.scala.Either[String, T] = { try { Right( converters.convert(value) ) } catch { case ex: java.lang.Exception => Left( converters.errorMessage(key, value, ex) ) } } override def unbind(key: String, value: T): String = { converters.convert(value) } } } } package com.shopr.api.clickouts.api.v0 { object Constants { val BaseUrl = "http://api.shopr.nl/stats" val Namespace = "com.shopr.api.clickouts.api.v0" val UserAgent = "apibuilder app.apibuilder.io/shopr/clickouts-api/0.0.1-dev/play_2_4_client" val Version = "0.0.1-dev" val VersionMajor = 0 } class Client( val baseUrl: String = "http://api.shopr.nl/stats", auth: scala.Option[com.shopr.api.clickouts.api.v0.Authorization] = None, defaultHeaders: Seq[(String, String)] = Nil ) extends interfaces.Client { import com.shopr.api.clickouts.api.v0.models.json._ private val logger = play.api.Logger("com.shopr.api.clickouts.api.v0.Client") logger.info(s"Initializing com.shopr.api.clickouts.api.v0.Client for url $baseUrl") def clickouts: Clickouts = Clickouts def statuses: Statuses = Statuses object Clickouts extends Clickouts { override def post( fingerprint: String, clickout: com.shopr.api.clickouts.api.v0.models.Clickout, requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[String] = { val payload = play.api.libs.json.Json.toJson(clickout) _executeRequest("POST", s"/${play.utils.UriEncoding.encodePathSegment(fingerprint, "UTF-8")}/clickouts", body = Some(payload), requestHeaders = requestHeaders).map { case r if r.status == 202 => _root_.com.shopr.api.clickouts.api.v0.Client.parseJson("String", r, _.validate[String]) case r if r.status == 422 => throw com.shopr.api.clickouts.api.v0.errors.ErrorResponsesResponse(r) case r => throw com.shopr.api.clickouts.api.v0.errors.FailedRequest(r.status, s"Unsupported response code[${r.status}]. Expected: 202, 422") } } } object Statuses extends Statuses { override def getPing( requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[com.shopr.api.clickouts.api.v0.models.Status] = { _executeRequest("GET", s"/_internal_/ping", requestHeaders = requestHeaders).map { case r if r.status == 200 => _root_.com.shopr.api.clickouts.api.v0.Client.parseJson("com.shopr.api.clickouts.api.v0.models.Status", r, _.validate[com.shopr.api.clickouts.api.v0.models.Status]) case r => throw com.shopr.api.clickouts.api.v0.errors.FailedRequest(r.status, s"Unsupported response code[${r.status}]. Expected: 200") } } override def getStatus( requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[com.shopr.api.clickouts.api.v0.models.Status] = { _executeRequest("GET", s"/_internal_/status", requestHeaders = requestHeaders).map { case r if r.status == 200 => _root_.com.shopr.api.clickouts.api.v0.Client.parseJson("com.shopr.api.clickouts.api.v0.models.Status", r, _.validate[com.shopr.api.clickouts.api.v0.models.Status]) case r => throw com.shopr.api.clickouts.api.v0.errors.FailedRequest(r.status, s"Unsupported response code[${r.status}]. Expected: 200") } } override def getVersion( requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[String] = { _executeRequest("GET", s"/_internal_/version", requestHeaders = requestHeaders).map { case r if r.status == 200 => _root_.com.shopr.api.clickouts.api.v0.Client.parseJson("String", r, _.validate[String]) case r => throw com.shopr.api.clickouts.api.v0.errors.FailedRequest(r.status, s"Unsupported response code[${r.status}]. Expected: 200") } } } def _requestHolder(path: String): play.api.libs.ws.WSRequest = { import play.api.Play.current val holder = play.api.libs.ws.WS.url(baseUrl + path).withHeaders( "User-Agent" -> Constants.UserAgent, "X-Apidoc-Version" -> Constants.Version, "X-Apidoc-Version-Major" -> Constants.VersionMajor.toString ).withHeaders(defaultHeaders: _*) auth.fold(holder) { case Authorization.Basic(username, password) => { holder.withAuth(username, password.getOrElse(""), play.api.libs.ws.WSAuthScheme.BASIC) } } } def _logRequest(method: String, req: play.api.libs.ws.WSRequest): play.api.libs.ws.WSRequest = { val queryComponents = for { (name, values) <- req.queryString value <- values } yield s"$name=$value" val url = s"${req.url}${queryComponents.mkString("?", "&", "")}" auth.fold(logger.info(s"curl -X $method '$url'")) { _ => logger.info(s"curl -X $method -u '[REDACTED]:' '$url'") } req } def _executeRequest( method: String, path: String, queryParameters: Seq[(String, String)] = Nil, requestHeaders: Seq[(String, String)] = Nil, body: Option[play.api.libs.json.JsValue] = None ): scala.concurrent.Future[play.api.libs.ws.WSResponse] = { method.toUpperCase match { case "GET" => { _logRequest("GET", _requestHolder(path).withHeaders(requestHeaders: _*).withQueryString(queryParameters: _*)).get() } case "POST" => { _logRequest("POST", _requestHolder(path).withHeaders(_withJsonContentType(requestHeaders): _*).withQueryString(queryParameters: _*)).post(body.getOrElse(play.api.libs.json.Json.obj())) } case "PUT" => { _logRequest("PUT", _requestHolder(path).withHeaders(_withJsonContentType(requestHeaders): _*).withQueryString(queryParameters: _*)).put(body.getOrElse(play.api.libs.json.Json.obj())) } case "PATCH" => { _logRequest("PATCH", _requestHolder(path).withHeaders(requestHeaders: _*).withQueryString(queryParameters: _*)).patch(body.getOrElse(play.api.libs.json.Json.obj())) } case "DELETE" => { _logRequest("DELETE", _requestHolder(path).withHeaders(requestHeaders: _*).withQueryString(queryParameters: _*)).delete() } case "HEAD" => { _logRequest("HEAD", _requestHolder(path).withHeaders(requestHeaders: _*).withQueryString(queryParameters: _*)).head() } case "OPTIONS" => { _logRequest("OPTIONS", _requestHolder(path).withHeaders(requestHeaders: _*).withQueryString(queryParameters: _*)).options() } case _ => { _logRequest(method, _requestHolder(path).withHeaders(requestHeaders: _*).withQueryString(queryParameters: _*)) sys.error("Unsupported method[%s]".format(method)) } } } /** * Adds a Content-Type: application/json header unless the specified requestHeaders * already contain a Content-Type header */ def _withJsonContentType(headers: Seq[(String, String)]): Seq[(String, String)] = { headers.find { _._1.toUpperCase == "CONTENT-TYPE" } match { case None => headers ++ Seq("Content-Type" -> "application/json; charset=UTF-8") case Some(_) => headers } } } object Client { def parseJson[T]( className: String, r: play.api.libs.ws.WSResponse, f: (play.api.libs.json.JsValue => play.api.libs.json.JsResult[T]) ): T = { f(play.api.libs.json.Json.parse(r.body)) match { case play.api.libs.json.JsSuccess(x, _) => x case play.api.libs.json.JsError(errors) => { throw com.shopr.api.clickouts.api.v0.errors.FailedRequest(r.status, s"Invalid json for class[" + className + "]: " + errors.mkString(" ")) } } } } 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 { def baseUrl: String def clickouts: com.shopr.api.clickouts.api.v0.Clickouts def statuses: com.shopr.api.clickouts.api.v0.Statuses } } trait Clickouts { /** * Create a new click-out. Requests are accepted for eventual processing. * * @param fingerprint User fingerprint used for correlation purposes. */ def post( fingerprint: String, clickout: com.shopr.api.clickouts.api.v0.models.Clickout, requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[String] } trait Statuses { /** * Ping in milliseconds. */ def getPing( requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[com.shopr.api.clickouts.api.v0.models.Status] /** * Current health check status. */ def getStatus( requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[com.shopr.api.clickouts.api.v0.models.Status] /** * API version. */ def getVersion( requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[String] } package errors { import com.shopr.api.clickouts.api.v0.models.json._ final case class ErrorResponsesResponse( response: play.api.libs.ws.WSResponse, message: Option[String] = None ) extends Exception(message.getOrElse(s"${response.status}: ${response.body}")) { lazy val errorResponses = _root_.com.shopr.api.clickouts.api.v0.Client.parseJson("Seq[com.shopr.api.clickouts.api.v0.models.ErrorResponse]", response, _.validate[Seq[com.shopr.api.clickouts.api.v0.models.ErrorResponse]]) } final case class FailedRequest(responseCode: Int, message: String, requestUri: Option[_root_.java.net.URI] = None) extends _root_.java.lang.Exception(s"HTTP $responseCode: $message") } }