From 57ecd4b4716275262a58a663cb2c1e9b7caffddd Mon Sep 17 00:00:00 2001 From: Christoph Herzog <chris@theduke.at> Date: Mon, 19 Aug 2019 22:40:22 +0200 Subject: [PATCH] Add warp_async example --- Cargo.toml | 1 + examples/warp_async/.gitignore | 1 + examples/warp_async/Cargo.toml | 17 ++++++ examples/warp_async/src/main.rs | 99 +++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 examples/warp_async/.gitignore create mode 100644 examples/warp_async/Cargo.toml create mode 100644 examples/warp_async/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 35fbad11..6f61e9f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,4 +12,5 @@ members = [ ] exclude = [ "docs/book/tests", + "examples/warp_async", ] diff --git a/examples/warp_async/.gitignore b/examples/warp_async/.gitignore new file mode 100644 index 00000000..eb5a316c --- /dev/null +++ b/examples/warp_async/.gitignore @@ -0,0 +1 @@ +target diff --git a/examples/warp_async/Cargo.toml b/examples/warp_async/Cargo.toml new file mode 100644 index 00000000..1891ad97 --- /dev/null +++ b/examples/warp_async/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "warp_async" +version = "0.1.0" +authors = ["Christoph Herzog <chris@theduke.at>"] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +juniper = { git = "https://github.com/graphql-rust/juniper", branch = "async-await", features = ["async"] } +juniper_warp = { git = "https://github.com/graphql-rust/juniper", branch = "async-await", features = ["async"] } +log = "0.4.8" +env_logger = "0.6.2" +warp = "0.1.19" +futures-preview = { version = "0.3.0-alpha.18", features = ["nightly", "async-await", "compat"] } +reqwest = "0.9.19" + diff --git a/examples/warp_async/src/main.rs b/examples/warp_async/src/main.rs new file mode 100644 index 00000000..70112bae --- /dev/null +++ b/examples/warp_async/src/main.rs @@ -0,0 +1,99 @@ +//! +//! This example demonstrates async/await usage with warp. +//! NOTE: this uses tokio 0.1 , not the alpha tokio 0.2. + +#![feature(async_await, async_closure)] + +use juniper::{EmptyMutation, RootNode, FieldError}; +use warp::{http::Response, Filter}; + +#[derive(Clone)] +struct Context { + +} +impl juniper::Context for Context {} + +struct User { + id: i32, + name: String, +} + +#[juniper::object(Context = Context)] +impl User { + fn id(&self) -> i32 { + self.id + } + + fn name(&self) -> &str { + &self.name + } + + async fn friends(&self) -> Vec<User> { + vec![] + } +} + +struct Query; + +#[juniper::object(Context = Context)] +impl Query { + async fn users() -> Vec<User> { + vec![ + User{ + id: 1, + name: "user1".into(), + }, + ] + } + + /// Fetch a URL and return the response body text. + async fn request(url: String) -> Result<String, FieldError> { + use futures::{ compat::{Stream01CompatExt, Future01CompatExt}, stream::TryStreamExt}; + + let res = reqwest::r#async::Client::new() + .get(&url) + .send() + .compat() + .await?; + + let body_raw = res.into_body().compat().try_concat().await?; + let body = std::str::from_utf8(&body_raw).unwrap_or("invalid utf8"); + Ok(body.to_string()) + } +} + +type Schema = RootNode<'static, Query, EmptyMutation<Context>>; + +fn schema() -> Schema { + Schema::new(Query, EmptyMutation::<Context>::new()) +} + +fn main() { + ::std::env::set_var("RUST_LOG", "warp_async"); + env_logger::init(); + + let log = warp::log("warp_server"); + + let homepage = warp::path::end().map(|| { + Response::builder() + .header("content-type", "text/html") + .body(format!( + "<html><h1>juniper_warp</h1><div>visit <a href=\"/graphiql\">/graphiql</a></html>" + )) + }); + + log::info!("Listening on 127.0.0.1:8080"); + + let state = warp::any().map(move || Context{} ); + let graphql_filter = juniper_warp::make_graphql_filter_async(schema(), state.boxed()); + + warp::serve( + warp::get2() + .and(warp::path("graphiql")) + .and(juniper_warp::graphiql_filter("/graphql")) + .or(homepage) + .or(warp::path("graphql").and(graphql_filter)) + .with(log), + ) + .run(([127, 0, 0, 1], 8080)); +}