#![deny(warnings)] use std::{collections::HashMap, env}; use actix_cors::Cors; use actix_web::{ http::header, middleware, web::{self, Data}, App, Error, HttpResponse, HttpServer, }; use juniper::{graphql_object, EmptyMutation, EmptySubscription, GraphQLObject, RootNode}; use juniper_actix::{graphiql_handler, graphql_handler, playground_handler}; #[derive(Clone, GraphQLObject)] ///a user pub struct User { ///the id id: i32, ///the name name: String, } #[derive(Clone, Default)] pub struct Database { ///this could be a database connection users: HashMap, } impl Database { pub fn new() -> Database { let mut users = HashMap::new(); users.insert( 1, User { id: 1, name: "Aron".into(), }, ); users.insert( 2, User { id: 2, name: "Bea".into(), }, ); users.insert( 3, User { id: 3, name: "Carl".into(), }, ); users.insert( 4, User { id: 4, name: "Dora".into(), }, ); Database { users } } pub fn get_user(&self, id: &i32) -> Option<&User> { self.users.get(id) } } // To make our Database usable by Juniper, we have to implement a marker trait. impl juniper::Context for Database {} // Queries represent the callable funcitons struct Query; #[graphql_object(context = Database)] impl Query { fn api_version() -> &'static str { "1.0" } fn user( context: &Database, #[graphql(description = "id of the user")] id: i32, ) -> Option<&User> { context.get_user(&id) } } type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>; fn schema() -> Schema { Schema::new( Query, EmptyMutation::::new(), EmptySubscription::::new(), ) } async fn graphiql_route() -> Result { graphiql_handler("/graphql", None).await } async fn playground_route() -> Result { playground_handler("/graphql", None).await } async fn graphql_route( req: actix_web::HttpRequest, payload: actix_web::web::Payload, schema: web::Data, ) -> Result { let context = Database::new(); graphql_handler(&schema, &context, req, payload).await } #[actix_web::main] async fn main() -> std::io::Result<()> { env::set_var("RUST_LOG", "info"); env_logger::init(); let server = HttpServer::new(move || { App::new() .app_data(Data::new(schema())) .wrap( Cors::default() .allow_any_origin() .allowed_methods(vec!["POST", "GET"]) .allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT]) .allowed_header(header::CONTENT_TYPE) .supports_credentials() .max_age(3600), ) .wrap(middleware::Compress::default()) .wrap(middleware::Logger::default()) .service( web::resource("/graphql") .route(web::post().to(graphql_route)) .route(web::get().to(graphql_route)), ) .service(web::resource("/playground").route(web::get().to(playground_route))) .service(web::resource("/graphiql").route(web::get().to(graphiql_route))) }); server.bind("127.0.0.1:8080").unwrap().run().await } // now go to http://127.0.0.1:8080/playground or graphiql and execute //{ apiVersion, user(id: 2){id, name}}