|
|
|
@ -2,11 +2,15 @@ extern crate juniper; |
|
|
|
|
|
|
|
|
|
use crate::database::{DBLog, DBMessage}; |
|
|
|
|
use chrono::prelude::*; |
|
|
|
|
use juniper::http::GraphQLRequest; |
|
|
|
|
use juniper::Value::Null; |
|
|
|
|
use juniper::{FieldError, FieldResult}; |
|
|
|
|
use std::collections::HashSet; |
|
|
|
|
use std::convert::TryInto; |
|
|
|
|
use warp::Filter; |
|
|
|
|
use std::sync::Arc; |
|
|
|
|
|
|
|
|
|
use actix_cors::Cors; |
|
|
|
|
use actix_web::{http, middleware, web, App, Error, HttpResponse, HttpServer}; |
|
|
|
|
|
|
|
|
|
#[derive(Debug, juniper::GraphQLObject)] |
|
|
|
|
#[graphql(description = "Paginated list of messages")] |
|
|
|
@ -248,20 +252,52 @@ impl Mutation {} |
|
|
|
|
|
|
|
|
|
type Schema = juniper::RootNode<'static, Query, Mutation>; |
|
|
|
|
|
|
|
|
|
pub fn server(bind: &str, port: u16, databases: Vec<DBLog>) { |
|
|
|
|
async fn graphql( |
|
|
|
|
st: web::Data<Arc<GQLData>>, |
|
|
|
|
data: web::Json<GraphQLRequest>, |
|
|
|
|
) -> Result<HttpResponse, Error> { |
|
|
|
|
let user = web::block(move || { |
|
|
|
|
let res = data.execute(&st.schema, &st.context); |
|
|
|
|
Ok::<_, serde_json::error::Error>(serde_json::to_string(&res)?) |
|
|
|
|
}) |
|
|
|
|
.await?; |
|
|
|
|
Ok(HttpResponse::Ok() |
|
|
|
|
.content_type("application/json") |
|
|
|
|
.body(user)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct GQLData { |
|
|
|
|
schema: Schema, |
|
|
|
|
context: Context, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub async fn server(bind: &str, databases: Vec<DBLog>) -> std::io::Result<()> { |
|
|
|
|
// Create Juniper schema
|
|
|
|
|
let schema = Schema::new(Query, Mutation); |
|
|
|
|
let state = warp::any().map(move || Context { |
|
|
|
|
databases: databases.clone().into_iter().map(from_db).collect(), |
|
|
|
|
}); |
|
|
|
|
let graphql_filter = juniper_warp::make_graphql_filter(schema, state.boxed()); |
|
|
|
|
|
|
|
|
|
println!("Starting server at {}:{}\n\nEndpoints:\n graphql: http://{}:{}/graphql\n graphiql: http://{}:{}/graphiql", bind, port, bind, port, bind, port); |
|
|
|
|
|
|
|
|
|
warp::serve( |
|
|
|
|
warp::get2() |
|
|
|
|
.and(warp::path("graphiql")) |
|
|
|
|
.and(juniper_warp::graphiql_filter("/graphql")) |
|
|
|
|
.or(warp::path("graphql").and(graphql_filter)), |
|
|
|
|
) |
|
|
|
|
.run(std::net::SocketAddr::new(bind.parse().unwrap(), port)); |
|
|
|
|
let context = Context { |
|
|
|
|
databases: databases.into_iter().map(from_db).collect(), |
|
|
|
|
}; |
|
|
|
|
let data = std::sync::Arc::new(GQLData { schema, context }); |
|
|
|
|
|
|
|
|
|
// Start http server
|
|
|
|
|
HttpServer::new(move || { |
|
|
|
|
App::new() |
|
|
|
|
.data(data.clone()) |
|
|
|
|
.wrap(middleware::Logger::default()) |
|
|
|
|
.wrap( |
|
|
|
|
Cors::new() |
|
|
|
|
.allowed_methods(vec!["GET", "POST", "OPTIONS"]) |
|
|
|
|
.allowed_headers(vec![ |
|
|
|
|
http::header::AUTHORIZATION, |
|
|
|
|
http::header::ACCEPT, |
|
|
|
|
http::header::CONTENT_TYPE, |
|
|
|
|
]) |
|
|
|
|
.max_age(3600) |
|
|
|
|
.finish(), |
|
|
|
|
) |
|
|
|
|
.service(web::resource("/graphql").route(web::post().to(graphql))) |
|
|
|
|
}) |
|
|
|
|
.bind(bind)? |
|
|
|
|
.run() |
|
|
|
|
.await |
|
|
|
|
} |
|
|
|
|