use async_graphql::{ObjectType, SubscriptionType, Schema};
use async_graphql::http::GraphiQLSource;
use axum::{
body::Bytes,
extract::Extension,
http::{header, StatusCode},
response::{Html, IntoResponse, Response},
routing::{get, post},
Router,
};
pub async fn graphql_handler<Q, M, S>(
Extension(schema): Extension<Schema<Q, M, S>>,
body: Bytes,
) -> Response
where
Q: ObjectType + 'static,
M: ObjectType + 'static,
S: SubscriptionType + 'static,
{
let request: async_graphql::Request = match serde_json::from_slice(&body) {
Ok(r) => r,
Err(e) => {
return (StatusCode::BAD_REQUEST, e.to_string()).into_response();
}
};
let response = schema.execute(request).await;
match serde_json::to_string(&response) {
Ok(json) => (
StatusCode::OK,
[(header::CONTENT_TYPE, "application/json")],
json,
)
.into_response(),
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
}
}
pub async fn graphiql_handler() -> impl IntoResponse {
Html(GraphiQLSource::build().endpoint("/graphql").finish())
}
pub fn graphql_routes<Q, M, S>(schema: Schema<Q, M, S>) -> Router
where
Q: ObjectType + Clone + 'static,
M: ObjectType + Clone + 'static,
S: SubscriptionType + Clone + 'static,
{
Router::new()
.route("/graphql", post(graphql_handler::<Q, M, S>))
.route("/graphql/playground", get(graphiql_handler))
.layer(Extension(schema))
}