Initial work on Rocket integration
This commit is contained in:
parent
a7a6778b18
commit
e82534aced
5 changed files with 129 additions and 2 deletions
11
Cargo.toml
11
Cargo.toml
|
@ -22,19 +22,28 @@ path = "benches/bench.rs"
|
|||
name = "server"
|
||||
required-features = ["iron-handlers", "expose-test-schema"]
|
||||
|
||||
[[example]]
|
||||
name = "rocket-server"
|
||||
required-features = ["rocket-handlers", "expose-test-schema"]
|
||||
|
||||
[features]
|
||||
nightly = []
|
||||
iron-handlers = ["iron", "serde_json", "urlencoded"]
|
||||
rocket-handlers = ["rocket", "rocket_codegen", "serde_json"]
|
||||
expose-test-schema = []
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "^1.0.8" }
|
||||
serde_derive = {version="^1.0.8" }
|
||||
|
||||
iron = { version = "^0.5.1", optional = true }
|
||||
serde_json = { version = "^1.0.2", optional = true }
|
||||
|
||||
iron = { version = "^0.5.1", optional = true }
|
||||
urlencoded = { version = "^0.5.0", optional = true }
|
||||
|
||||
rocket = { version = "^0.2.8", optional = true }
|
||||
rocket_codegen = { version = "^0.2.8", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
iron = "^0.5.1"
|
||||
router = "^0.5.0"
|
||||
|
|
37
examples/rocket-server.rs
Normal file
37
examples/rocket-server.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
#![feature(plugin)]
|
||||
#![plugin(rocket_codegen)]
|
||||
|
||||
extern crate rocket;
|
||||
extern crate juniper;
|
||||
|
||||
use rocket::response::content;
|
||||
use rocket::State;
|
||||
|
||||
use juniper::tests::model::Database;
|
||||
use juniper::{EmptyMutation, RootNode};
|
||||
|
||||
use juniper::rocket_handlers;
|
||||
|
||||
type Schema = RootNode<'static, Database, EmptyMutation<Database>>;
|
||||
|
||||
#[get("/")]
|
||||
fn graphiql() -> content::HTML<String> {
|
||||
rocket_handlers::graphiql_source("/graphql")
|
||||
}
|
||||
|
||||
#[post("/graphql", data="<request>")]
|
||||
fn post_graphql_handler(
|
||||
context: State<Database>,
|
||||
request: rocket_handlers::GraphQLRequest,
|
||||
schema: State<Schema>
|
||||
) -> rocket_handlers::GraphQLResponse {
|
||||
request.execute(&schema, &context)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
rocket::ignite()
|
||||
.manage(Database::new())
|
||||
.manage(Schema::new(Database::new(), EmptyMutation::<Database>::new()))
|
||||
.mount("/", routes![graphiql, post_graphql_handler])
|
||||
.launch();
|
||||
}
|
|
@ -1,2 +1,3 @@
|
|||
#[cfg(feature="iron-handlers")] pub mod iron_handlers;
|
||||
#[cfg(feature="rocket-handlers")] pub mod rocket_handlers;
|
||||
pub mod serde;
|
||||
|
|
74
src/integrations/rocket_handlers.rs
Normal file
74
src/integrations/rocket_handlers.rs
Normal file
|
@ -0,0 +1,74 @@
|
|||
use std::io::{Cursor, Read};
|
||||
|
||||
use serde_json;
|
||||
|
||||
use rocket::Request;
|
||||
use rocket::data::{FromData, Outcome};
|
||||
use rocket::response::{Responder, Response, content};
|
||||
use rocket::http::{ContentType, Status};
|
||||
use rocket::Data;
|
||||
use rocket::Outcome::{Forward, Failure, Success};
|
||||
|
||||
use ::http;
|
||||
|
||||
use types::base::GraphQLType;
|
||||
use schema::model::RootNode;
|
||||
|
||||
pub struct GraphQLResponse(Status, String);
|
||||
pub struct GraphQLRequest(http::GraphQLRequest);
|
||||
|
||||
pub fn graphiql_source(graphql_endpoint_url: &str) -> content::HTML<String> {
|
||||
content::HTML(::graphiql::graphiql_source(graphql_endpoint_url))
|
||||
}
|
||||
|
||||
impl GraphQLRequest {
|
||||
pub fn execute<CtxT, QueryT, MutationT>(
|
||||
&self,
|
||||
root_node: &RootNode<QueryT, MutationT>,
|
||||
context: &CtxT,
|
||||
)
|
||||
-> GraphQLResponse
|
||||
where QueryT: GraphQLType<Context=CtxT>,
|
||||
MutationT: GraphQLType<Context=CtxT>,
|
||||
{
|
||||
let response = self.0.execute(root_node, context);
|
||||
let status = if response.is_ok() { Status::Ok } else { Status::BadRequest };
|
||||
let json = serde_json::to_string_pretty(&response).unwrap();
|
||||
|
||||
GraphQLResponse(status, json)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromData for GraphQLRequest {
|
||||
type Error = String;
|
||||
|
||||
fn from_data(request: &Request, data: Data) -> Outcome<Self, String> {
|
||||
if !request.content_type().map_or(false, |ct| ct.is_json()) {
|
||||
return Forward(data);
|
||||
}
|
||||
|
||||
let mut body = String::new();
|
||||
if let Err(e) = data.open().read_to_string(&mut body) {
|
||||
return Failure((Status::InternalServerError, format!("{:?}", e)));
|
||||
}
|
||||
|
||||
match serde_json::from_str(&body) {
|
||||
Ok(value) => Success(GraphQLRequest(value)),
|
||||
Err(failure) => return Failure(
|
||||
(Status::BadRequest, format!("{}", failure)),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Responder<'r> for GraphQLResponse {
|
||||
fn respond(self) -> Result<Response<'r>, Status> {
|
||||
let GraphQLResponse(status, body) = self;
|
||||
|
||||
Ok(Response::build()
|
||||
.header(ContentType::new("application", "json"))
|
||||
.status(status)
|
||||
.sized_body(Cursor::new(body))
|
||||
.finalize())
|
||||
}
|
||||
}
|
|
@ -185,6 +185,11 @@ built-in [GraphiQL][6] handler included.
|
|||
|
||||
#![cfg_attr(feature="nightly", feature(test))]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
#![cfg_attr(feature="rocket-handlers", feature(plugin))]
|
||||
#![cfg_attr(feature="rocket-handlers", plugin(rocket_codegen))]
|
||||
#[cfg(feature="rocket-handlers")] extern crate rocket;
|
||||
|
||||
#[cfg(feature="nightly")] extern crate test;
|
||||
#[cfg(feature="iron-handlers")] #[macro_use(itry)] extern crate iron;
|
||||
#[cfg(feature="iron-handlers")] extern crate urlencoded;
|
||||
|
@ -192,7 +197,7 @@ built-in [GraphiQL][6] handler included.
|
|||
extern crate serde;
|
||||
#[macro_use] extern crate serde_derive;
|
||||
|
||||
#[cfg(feature="iron-handlers")] extern crate serde_json;
|
||||
#[cfg(any(feature="iron-handlers", feature="rocket-handlers"))] extern crate serde_json;
|
||||
|
||||
#[macro_use] mod macros;
|
||||
mod ast;
|
||||
|
@ -232,6 +237,7 @@ pub use result_ext::ResultExt;
|
|||
pub use schema::meta;
|
||||
|
||||
#[cfg(feature="iron-handlers")] pub use integrations::iron_handlers;
|
||||
#[cfg(feature="rocket-handlers")] pub use integrations::rocket_handlers;
|
||||
|
||||
/// An error that prevented query execution
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
|
Loading…
Reference in a new issue