io.github.dexclaimation.ahql.AhqlClient.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ahql_2.13 Show documentation
Show all versions of ahql_2.13 Show documentation
Akka Http Query Library, a minimal GraphQL client and server exposing as a set of akka-http utilities
The newest version!
//
// AhqlClient.scala
// ahql
//
// Created by d-exclaimation on 10:14 PM.
//
package io.github.dexclaimation.ahql
import akka.actor.ClassicActorSystemProvider
import akka.http.scaladsl.Http
import akka.http.scaladsl.client.RequestBuilding.{Get, Post}
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.model.{ContentTypes, HttpHeader, HttpMethod, HttpMethods, HttpRequest, headers => h}
import akka.http.scaladsl.unmarshalling.Unmarshal
import io.github.dexclaimation.ahql.graphql.GqlRequest
import spray.json.{DefaultJsonProtocol, JsObject, JsValue, JsonParser}
import scala.concurrent.{ExecutionContext, Future}
/**
* Minimal GraphQL HTTP-based Client
*
* @param endpoint GraphQL API Endpoint.
* @param defaultHeaders Default HTTP Headers.
*/
class AhqlClient(
endpoint: String,
defaultHeaders: Seq[HttpHeader] = Nil
)(implicit system: ClassicActorSystemProvider) extends SprayJsonSupport with DefaultJsonProtocol {
/**
* Make a fetch request to a GraphQL API.
*
* @param query Query AST Document.
* @param operationName Operation name being executed from the AST.
* @param variables Variables used in the query.
* @param headers Additional header for this request.
* @return Future of an JsObject
*/
def fetch(
query: sangria.ast.Document,
operationName: Option[String] = None,
variables: JsObject = JsObject.empty,
method: HttpMethod = HttpMethods.POST,
headers: Seq[HttpHeader] = Nil
)(implicit ex: ExecutionContext): Future[JsObject] = method match {
case HttpMethods.POST =>
val payload = operationName
.map(GqlRequest(query, _, variables))
.getOrElse(GqlRequest(query, variables))
post(payload, headers)
case HttpMethods.GET =>
val queryParams = GqlRequest.queryString(query, operationName, variables)
get(queryParams, headers)
case _ => Future.failed(new Error("Cannot perform GraphQL Request other than in POST and GET"))
}
/**
* Make a fetch request to a GraphQL API, but not
* hard bound to [[spray.json.JsObject]].
*
* @param query Query AST Document.
* @param operationName Operation name being executed from the AST.
* @param variables Variables used in the query.
* @param headers Additional header for this request.
* @return Future of an JsObject
*/
def _fetch(
query: sangria.ast.Document,
operationName: Option[String] = None,
variables: String = JsObject.empty.compactPrint,
method: HttpMethod = HttpMethods.POST,
headers: Seq[HttpHeader] = Nil
)(implicit ex: ExecutionContext): Future[JsObject] = JsonParser(variables) match {
case obj: JsObject => fetch(query, operationName, obj, method, headers)
case _ => Future.failed(new Error("Cannot parse variables"))
}
/**
* Make HTTP GET Request
*
* @param headers Additional headers.
*/
private def get(
queryParams: String,
headers: Seq[HttpHeader]
)(implicit ex: ExecutionContext): Future[JsObject] = {
val req = Get(s"$endpoint?$queryParams")
.withHeaders(
headers ++ defaultHeaders
)
httpRequest(req)
}
/**
* Make HTTP POST Request
*
* @param headers Additional headers.
*/
private def post(
js: JsValue,
headers: Seq[HttpHeader]
)(implicit ex: ExecutionContext): Future[JsObject] = {
val req = Post(endpoint, js)
.withHeaders(
headers ++ defaultHeaders :+ h.`Content-Type`(ContentTypes.`application/json`)
)
httpRequest(req)
}
/**
* Make HTTP Request
*
* @param req HttpRequest
*/
private def httpRequest(req: HttpRequest)
(implicit ex: ExecutionContext): Future[JsObject] =
Http()
.singleRequest(req)
.map(Unmarshal(_))
.flatMap(_.to[JsObject])
private[ahql] def test(
query: sangria.ast.Document,
operationName: Option[String] = None,
variables: JsObject = JsObject.empty,
method: HttpMethod = HttpMethods.POST,
headers: Seq[HttpHeader] = Nil
)(implicit ex: ExecutionContext): HttpRequest = method match {
case HttpMethods.POST =>
val payload = operationName
.map(GqlRequest(query, _, variables))
.getOrElse(GqlRequest(query, variables))
Post(endpoint, payload)
.withHeaders(
headers ++ defaultHeaders :+ h.`Content-Type`(ContentTypes.`application/json`)
)
case HttpMethods.GET =>
val queryParams = GqlRequest.queryString(query, operationName, variables)
Get(s"$endpoint?$queryParams")
.withHeaders(
headers ++ defaultHeaders
)
case _ => throw new Error("Cannot perform GraphQL Request other than in POST and GET")
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy