2023-11-09 04:57:00 -06:00
|
|
|
//! This example demonstrates simple default integration with [`axum`].
|
|
|
|
|
|
|
|
use std::{net::SocketAddr, sync::Arc, time::Duration};
|
|
|
|
|
|
|
|
use axum::{
|
|
|
|
response::Html,
|
|
|
|
routing::{get, on, MethodFilter},
|
|
|
|
Extension, Router,
|
|
|
|
};
|
|
|
|
use futures::stream::{BoxStream, StreamExt as _};
|
|
|
|
use juniper::{graphql_object, graphql_subscription, EmptyMutation, FieldError, RootNode};
|
|
|
|
use juniper_axum::{graphiql, graphql, playground, ws};
|
|
|
|
use juniper_graphql_ws::ConnectionConfig;
|
2023-11-27 07:14:02 -06:00
|
|
|
use tokio::{net::TcpListener, time::interval};
|
2023-11-09 04:57:00 -06:00
|
|
|
use tokio_stream::wrappers::IntervalStream;
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
|
|
pub struct Query;
|
|
|
|
|
|
|
|
#[graphql_object]
|
|
|
|
impl Query {
|
|
|
|
/// Adds two `a` and `b` numbers.
|
|
|
|
fn add(a: i32, b: i32) -> i32 {
|
|
|
|
a + b
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
|
|
pub struct Subscription;
|
|
|
|
|
|
|
|
type NumberStream = BoxStream<'static, Result<i32, FieldError>>;
|
|
|
|
|
|
|
|
#[graphql_subscription]
|
|
|
|
impl Subscription {
|
|
|
|
/// Counts seconds.
|
|
|
|
async fn count() -> NumberStream {
|
|
|
|
let mut value = 0;
|
|
|
|
let stream = IntervalStream::new(interval(Duration::from_secs(1))).map(move |_| {
|
|
|
|
value += 1;
|
|
|
|
Ok(value)
|
|
|
|
});
|
|
|
|
Box::pin(stream)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type Schema = RootNode<'static, Query, EmptyMutation, Subscription>;
|
|
|
|
|
|
|
|
async fn homepage() -> Html<&'static str> {
|
|
|
|
"<html><h1>juniper_axum/simple example</h1>\
|
|
|
|
<div>visit <a href=\"/graphiql\">GraphiQL</a></div>\
|
|
|
|
<div>visit <a href=\"/playground\">GraphQL Playground</a></div>\
|
|
|
|
</html>"
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
async fn main() {
|
|
|
|
tracing_subscriber::fmt()
|
|
|
|
.with_max_level(tracing::Level::INFO)
|
|
|
|
.init();
|
|
|
|
|
|
|
|
let schema = Schema::new(Query, EmptyMutation::new(), Subscription);
|
|
|
|
|
|
|
|
let app = Router::new()
|
|
|
|
.route(
|
|
|
|
"/graphql",
|
|
|
|
on(
|
2023-11-27 07:14:02 -06:00
|
|
|
MethodFilter::GET.or(MethodFilter::POST),
|
2023-11-09 04:57:00 -06:00
|
|
|
graphql::<Arc<Schema>>,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
.route(
|
|
|
|
"/subscriptions",
|
|
|
|
get(ws::<Arc<Schema>>(ConnectionConfig::new(()))),
|
|
|
|
)
|
|
|
|
.route("/graphiql", get(graphiql("/graphql", "/subscriptions")))
|
|
|
|
.route("/playground", get(playground("/graphql", "/subscriptions")))
|
|
|
|
.route("/", get(homepage))
|
|
|
|
.layer(Extension(Arc::new(schema)));
|
|
|
|
|
|
|
|
let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
|
2023-11-27 07:14:02 -06:00
|
|
|
let listener = TcpListener::bind(addr)
|
|
|
|
.await
|
|
|
|
.unwrap_or_else(|e| panic!("failed to listen on {addr}: {e}"));
|
2023-11-09 04:57:00 -06:00
|
|
|
tracing::info!("listening on {addr}");
|
2023-11-27 07:14:02 -06:00
|
|
|
axum::serve(listener, app)
|
2023-11-09 04:57:00 -06:00
|
|
|
.await
|
2023-11-27 07:14:02 -06:00
|
|
|
.unwrap_or_else(|e| panic!("failed to run `axum::serve`: {e}"));
|
2023-11-09 04:57:00 -06:00
|
|
|
}
|