-
Notifications
You must be signed in to change notification settings - Fork 0
/
RestAPIClient.scala
57 lines (50 loc) · 2.53 KB
/
RestAPIClient.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.github.opengrabeso.github
import com.avsystem.commons.misc.Opt
import com.avsystem.commons.rpc.AsReal
import com.avsystem.commons.serialization.GenCodec
import com.github.opengrabeso.github.rest._
import sttp.client3._
import io.udash.rest.raw._
import io.udash.rest.{RestException, SttpRestClient}
import sttp.model.{Header, Method}
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
class RestAPIClient[TAPI: RawRest.AsRealRpc : RestMetadata](sttpBackend: SttpBackend[Future, Any], uri: String) {
private implicit val backend: SttpBackend[Future, Any] = sttpBackend
val api: TAPI = SttpRestClient.future[TAPI](uri)
def apply(): TAPI = api
// adapted from io.udash.rest.SttpRestClient#fromSttpResponse
// we cannot use it directly, as it is private there
private def fromSttpResponse(sttpResp: Response[String]): RestResponse = RestResponse(
sttpResp.code.code,
IMapping(sttpResp.headers.map { case Header(n, v) => (n, PlainValue(v)) }.toList),
sttpResp.contentType.fold(HttpBody.empty) { contentType =>
val mediaType = HttpBody.mediaTypeOf(contentType)
HttpBody.charsetOf(contentType) match {
case Opt(charset) =>
// TODO: uncool that we have to go through byte array for textual body
val text = sttpResp.body
HttpBody.textual(text, mediaType, charset)
case _ =>
HttpBody.textual(sttpResp.body, contentType)
}
}
)
// many APIs return URLs which should be used to obtain more information - this can be used to have the result decoded
def request[T](uri: String, token: String, method: Method = Method.GET, headers: Seq[(String, String)] = Seq.empty)(implicit asReal: AsReal[RestResponse, T]): Future[T] = {
val request = quickRequest.method(method, uri"$uri").auth.bearer(token).headers(headers.map((Header.apply _).tupled):_*)
sttpBackend.send(request).map { r =>
val raw = fromSttpResponse(r)
implicitly[AsReal[RestResponse, T]].asReal(raw)
}
}
// used for issue paging - use the provided URL and process the result headers
def requestWithHeaders[T: GenCodec](uri: String, token: String, headers: Seq[(String, String)] = Seq.empty): Future[DataWithHeaders[T]] = {
val request = quickRequest.method(Method.GET, uri"$uri").auth.bearer(token).headers(headers.map((Header.apply _).tupled):_*)
sttpBackend.send(request).map { r =>
val raw = fromSttpResponse(r)
import io.udash.rest.GenCodecRestImplicits._
EnhancedRestImplicits.fromResponse[T].asReal(raw)
}
}
}