GraphQLServer.scala 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /*
  2. * Copyright (C) 2020 Prasoon Joshi
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. */
  17. package graphql
  18. import play.api.libs.json.{JsObject, JsString, JsValue, Json}
  19. import play.api.mvc.Results._
  20. import play.api.mvc._
  21. import sangria.execution.{ErrorWithResolver, Executor, QueryAnalysisError}
  22. import sangria.parser.QueryParser
  23. import scala.concurrent.{ExecutionContext, Future}
  24. import scala.util.{Failure, Success}
  25. import sangria.marshalling.playJson._
  26. case class GraphQLServer(context: GraphQLContext) extends QueryServer {
  27. import scala.concurrent.ExecutionContext.Implicits.global
  28. def fetchQueryResult(requestJson: JsValue)(implicit ec: ExecutionContext): Future[Result] = {
  29. val JsObject(fields) = requestJson
  30. val JsString(query) = fields("query")
  31. QueryParser.parse(query) match {
  32. case Success(queryAst) =>
  33. val operation = fields.get("operationName") collect {
  34. case JsString(op) => op
  35. }
  36. val variables = fields.get("variables") match {
  37. case Some(obj: JsObject) => obj
  38. case _ => JsObject.empty
  39. }
  40. val vars = (requestJson \ "variables").toOption.flatMap {
  41. case JsString(xs) => Some(parseVariables(xs))
  42. case obj: JsObject => Some(obj)
  43. case _ => None //Json.obj()
  44. }
  45. executeGraphQLQuery(queryAst, operation, {vars getOrElse Json.obj()})
  46. case Failure(error) =>
  47. Future.successful(BadRequest(Json.obj("error" → error.getMessage)))
  48. }
  49. }
  50. def parseVariables(vars: String) =
  51. if (vars.trim == "" || vars.trim == "null") Json.obj() else Json.parse(vars).as[JsObject]
  52. def executeGraphQLQuery(query: sangria.ast.Document, op: Option[String], vars: JsObject): Future[Result] =
  53. Executor.execute(schema, query, context, operationName = op, variables = vars)
  54. .map(Ok(_))
  55. .recover {
  56. case error: QueryAnalysisError ⇒ BadRequest(error.resolveError)
  57. case error: ErrorWithResolver ⇒ InternalServerError(error.resolveError)
  58. }
  59. }