Skip to content

Commit e82534a

Browse files
committed
Initial work on Rocket integration
1 parent a7a6778 commit e82534a

File tree

5 files changed

+129
-2
lines changed

5 files changed

+129
-2
lines changed

Cargo.toml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,28 @@ path = "benches/bench.rs"
2222
name = "server"
2323
required-features = ["iron-handlers", "expose-test-schema"]
2424

25+
[[example]]
26+
name = "rocket-server"
27+
required-features = ["rocket-handlers", "expose-test-schema"]
28+
2529
[features]
2630
nightly = []
2731
iron-handlers = ["iron", "serde_json", "urlencoded"]
32+
rocket-handlers = ["rocket", "rocket_codegen", "serde_json"]
2833
expose-test-schema = []
2934

3035
[dependencies]
3136
serde = { version = "^1.0.8" }
3237
serde_derive = {version="^1.0.8" }
3338

34-
iron = { version = "^0.5.1", optional = true }
3539
serde_json = { version = "^1.0.2", optional = true }
40+
41+
iron = { version = "^0.5.1", optional = true }
3642
urlencoded = { version = "^0.5.0", optional = true }
3743

44+
rocket = { version = "^0.2.8", optional = true }
45+
rocket_codegen = { version = "^0.2.8", optional = true }
46+
3847
[dev-dependencies]
3948
iron = "^0.5.1"
4049
router = "^0.5.0"

examples/rocket-server.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#![feature(plugin)]
2+
#![plugin(rocket_codegen)]
3+
4+
extern crate rocket;
5+
extern crate juniper;
6+
7+
use rocket::response::content;
8+
use rocket::State;
9+
10+
use juniper::tests::model::Database;
11+
use juniper::{EmptyMutation, RootNode};
12+
13+
use juniper::rocket_handlers;
14+
15+
type Schema = RootNode<'static, Database, EmptyMutation<Database>>;
16+
17+
#[get("/")]
18+
fn graphiql() -> content::HTML<String> {
19+
rocket_handlers::graphiql_source("/graphql")
20+
}
21+
22+
#[post("/graphql", data="<request>")]
23+
fn post_graphql_handler(
24+
context: State<Database>,
25+
request: rocket_handlers::GraphQLRequest,
26+
schema: State<Schema>
27+
) -> rocket_handlers::GraphQLResponse {
28+
request.execute(&schema, &context)
29+
}
30+
31+
fn main() {
32+
rocket::ignite()
33+
.manage(Database::new())
34+
.manage(Schema::new(Database::new(), EmptyMutation::<Database>::new()))
35+
.mount("/", routes![graphiql, post_graphql_handler])
36+
.launch();
37+
}

src/integrations/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
#[cfg(feature="iron-handlers")] pub mod iron_handlers;
2+
#[cfg(feature="rocket-handlers")] pub mod rocket_handlers;
23
pub mod serde;

src/integrations/rocket_handlers.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
use std::io::{Cursor, Read};
2+
3+
use serde_json;
4+
5+
use rocket::Request;
6+
use rocket::data::{FromData, Outcome};
7+
use rocket::response::{Responder, Response, content};
8+
use rocket::http::{ContentType, Status};
9+
use rocket::Data;
10+
use rocket::Outcome::{Forward, Failure, Success};
11+
12+
use ::http;
13+
14+
use types::base::GraphQLType;
15+
use schema::model::RootNode;
16+
17+
pub struct GraphQLResponse(Status, String);
18+
pub struct GraphQLRequest(http::GraphQLRequest);
19+
20+
pub fn graphiql_source(graphql_endpoint_url: &str) -> content::HTML<String> {
21+
content::HTML(::graphiql::graphiql_source(graphql_endpoint_url))
22+
}
23+
24+
impl GraphQLRequest {
25+
pub fn execute<CtxT, QueryT, MutationT>(
26+
&self,
27+
root_node: &RootNode<QueryT, MutationT>,
28+
context: &CtxT,
29+
)
30+
-> GraphQLResponse
31+
where QueryT: GraphQLType<Context=CtxT>,
32+
MutationT: GraphQLType<Context=CtxT>,
33+
{
34+
let response = self.0.execute(root_node, context);
35+
let status = if response.is_ok() { Status::Ok } else { Status::BadRequest };
36+
let json = serde_json::to_string_pretty(&response).unwrap();
37+
38+
GraphQLResponse(status, json)
39+
}
40+
}
41+
42+
impl FromData for GraphQLRequest {
43+
type Error = String;
44+
45+
fn from_data(request: &Request, data: Data) -> Outcome<Self, String> {
46+
if !request.content_type().map_or(false, |ct| ct.is_json()) {
47+
return Forward(data);
48+
}
49+
50+
let mut body = String::new();
51+
if let Err(e) = data.open().read_to_string(&mut body) {
52+
return Failure((Status::InternalServerError, format!("{:?}", e)));
53+
}
54+
55+
match serde_json::from_str(&body) {
56+
Ok(value) => Success(GraphQLRequest(value)),
57+
Err(failure) => return Failure(
58+
(Status::BadRequest, format!("{}", failure)),
59+
),
60+
}
61+
}
62+
}
63+
64+
impl<'r> Responder<'r> for GraphQLResponse {
65+
fn respond(self) -> Result<Response<'r>, Status> {
66+
let GraphQLResponse(status, body) = self;
67+
68+
Ok(Response::build()
69+
.header(ContentType::new("application", "json"))
70+
.status(status)
71+
.sized_body(Cursor::new(body))
72+
.finalize())
73+
}
74+
}

src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,14 +185,19 @@ built-in [GraphiQL][6] handler included.
185185

186186
#![cfg_attr(feature="nightly", feature(test))]
187187
#![warn(missing_docs)]
188+
189+
#![cfg_attr(feature="rocket-handlers", feature(plugin))]
190+
#![cfg_attr(feature="rocket-handlers", plugin(rocket_codegen))]
191+
#[cfg(feature="rocket-handlers")] extern crate rocket;
192+
188193
#[cfg(feature="nightly")] extern crate test;
189194
#[cfg(feature="iron-handlers")] #[macro_use(itry)] extern crate iron;
190195
#[cfg(feature="iron-handlers")] extern crate urlencoded;
191196
#[cfg(test)] extern crate iron_test;
192197
extern crate serde;
193198
#[macro_use] extern crate serde_derive;
194199

195-
#[cfg(feature="iron-handlers")] extern crate serde_json;
200+
#[cfg(any(feature="iron-handlers", feature="rocket-handlers"))] extern crate serde_json;
196201

197202
#[macro_use] mod macros;
198203
mod ast;
@@ -232,6 +237,7 @@ pub use result_ext::ResultExt;
232237
pub use schema::meta;
233238

234239
#[cfg(feature="iron-handlers")] pub use integrations::iron_handlers;
240+
#[cfg(feature="rocket-handlers")] pub use integrations::rocket_handlers;
235241

236242
/// An error that prevented query execution
237243
#[derive(Debug, PartialEq)]

0 commit comments

Comments
 (0)