shaperail_runtime/graphql/
handler.rs1use std::sync::Arc;
4
5use actix_web::{web, HttpRequest, HttpResponse};
6use async_graphql_actix_web::{GraphQLRequest, GraphQLResponse};
7
8use super::dataloader::RelationLoader;
9use super::schema::{GqlContext, GraphQLSchema};
10use crate::auth::extractor::try_extract_auth;
11use crate::handlers::crud::AppState;
12
13pub async fn graphql_handler(
16 req: HttpRequest,
17 schema: web::Data<GraphQLSchema>,
18 state: web::Data<Arc<AppState>>,
19 request: GraphQLRequest,
20) -> GraphQLResponse {
21 let user = try_extract_auth(&req);
22 let loader = RelationLoader::new(state.get_ref().clone(), state.resources.clone());
23 let context = GqlContext {
24 state: state.get_ref().clone(),
25 resources: state.resources.clone(),
26 user,
27 loader,
28 };
29 let mut gql_req = request.into_inner();
30 gql_req = gql_req.data(context);
31 let response = schema.execute(gql_req).await;
32 response.into()
33}
34
35pub async fn playground_handler() -> HttpResponse {
37 let html = r#"<!DOCTYPE html>
38<html>
39<head><title>GraphQL Playground</title></head>
40<body>
41 <h1>GraphQL Playground</h1>
42 <p>Endpoint: <code>POST /graphql</code></p>
43 <textarea id="query" rows="8" style="width:90%;display:block;margin:1em 0;">query { __typename }</textarea>
44 <button onclick="run()">Run</button>
45 <pre id="result"></pre>
46 <script>
47 async function run() {
48 const query = document.getElementById('query').value;
49 const res = await fetch('/graphql', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query }) });
50 const data = await res.json();
51 document.getElementById('result').textContent = JSON.stringify(data, null, 2);
52 }
53 </script>
54</body>
55</html>"#;
56 HttpResponse::Ok()
57 .content_type("text/html; charset=utf-8")
58 .body(html)
59}