GraphqlServer.scala 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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 repository.{DataRepository, UserRepository}
  19. import play.api.libs.json.{JsObject, JsString, JsValue, Json}
  20. import play.api.mvc.Results._
  21. import play.api.mvc._
  22. import sangria.execution.{ErrorWithResolver, Executor, QueryAnalysisError}
  23. import sangria.parser.QueryParser
  24. import scala.concurrent.{ExecutionContext, Future}
  25. import scala.util.{Failure, Success}
  26. import sangria.marshalling.playJson._
  27. import sangria.schema.Schema
  28. import sangria.execution.ExceptionHandler
  29. case class GraphqlServer(dataRepo: DataRepository,
  30. userRepo: UserRepository) {
  31. import scala.concurrent.ExecutionContext.Implicits.global
  32. val errorHandler = ABagOfGoodies.errorHandler
  33. def fetchQueryResult(userToken: Option[String],
  34. requestJson: JsValue)(implicit ec: ExecutionContext): Future[Result] = {
  35. val JsObject(fields) = requestJson
  36. val JsString(query) = fields("query")
  37. QueryParser.parse(query) match {
  38. case Success(queryAst) =>
  39. val operation = fields.get("operationName") collect {
  40. case JsString(op) => op
  41. }
  42. val variables = fields.get("variables") match {
  43. case Some(obj: JsObject) => obj
  44. case _ => JsObject.empty
  45. }
  46. val vars = (requestJson \ "variables").toOption.flatMap {
  47. case JsString(xs) => Some(parseVariables(xs))
  48. case obj: JsObject => Some(obj)
  49. case _ => None //Json.obj()
  50. }
  51. executeGraphQLQuery(query = queryAst,
  52. userToken = userToken,
  53. errorHandler = errorHandler,
  54. op = operation,
  55. vars = {vars getOrElse Json.obj()})
  56. case Failure(error) =>
  57. Future.successful(BadRequest(Json.obj("error" -> error.getMessage)))
  58. }
  59. }
  60. def parseVariables(vars: String) =
  61. if (vars.trim == "" || vars.trim == "null") Json.obj() else Json.parse(vars).as[JsObject]
  62. def executeGraphQLQuery(query: sangria.ast.Document,
  63. userToken: Option[String],
  64. errorHandler: ExceptionHandler,
  65. op: Option[String],
  66. vars: JsObject): Future[Result] =
  67. Executor.execute(
  68. schema = SchemaDefinition.schema,
  69. query,
  70. userContext =
  71. new SecureGraphqlContext(userToken, userRepo, dataRepo),
  72. exceptionHandler = errorHandler,
  73. operationName = op,
  74. variables = vars)
  75. .map(Ok(_))
  76. .recover {
  77. case error: QueryAnalysisError => BadRequest(error.resolveError)
  78. case error: ErrorWithResolver => InternalServerError(error.resolveError)
  79. }
  80. }