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));
+}