mod cors;
mod multipart;
mod router;
pub use cors::{cors_headers, cors_preflight};
pub use multipart::parse_multipart;
pub use router::{extract_tenant, extract_playground_tenant};
use async_graphql::{
http::GraphQLPlaygroundConfig, http::playground_source, Error as GqlError, Pos,
Request as GraphQlRequest, Response as GraphQlResponse,
};
use http::StatusCode;
use lambda_http::{Body, Error, Request, RequestExt, Response};
use crate::errors::ServerError;
pub fn graphql_error(message: impl std::fmt::Display) -> String {
let msg = format!("{}", message);
let gql_err: GqlError = crate::errors::gql_from_message(msg);
let server_err = gql_err.into_server_error(Pos::default());
let response = GraphQlResponse::from_errors(vec![server_err]);
serde_json::to_string(&response).unwrap_or_else(|_| {
r#"{"errors":[{"message":"Internal serialization error"}]}"#.to_string()
})
}
pub fn error_response(status: StatusCode, body: String) -> Result<Response<Body>, Error> {
Ok(Response::builder()
.status(status)
.header("Access-Control-Allow-Origin", "*")
.body(Body::Text(body))?)
}
pub fn playground_response(api_endpoint: &str) -> Result<Response<Body>, Error> {
let playground_config = GraphQLPlaygroundConfig::new(api_endpoint);
let html = playground_source(playground_config);
Response::builder()
.status(StatusCode::OK)
.header("Content-Type", "text/html")
.header("Access-Control-Allow-Origin", "*")
.body(Body::Text(html))
.map_err(|e| Error::from(format!("Playground response error: {}", e)))
}
pub async fn graphql_request_from_post(request: Request) -> anyhow::Result<GraphQlRequest> {
let content_type = request
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("");
if content_type.starts_with("multipart/form-data") {
parse_multipart(request).await
} else {
let body = request.body();
let body_str = std::str::from_utf8(body).map_err(|e| anyhow::anyhow!("{}", e))?;
serde_json::from_str(body_str).map_err(|e| anyhow::anyhow!("{}", e))
}
}
pub async fn graphql_request_from_get(request: Request) -> anyhow::Result<GraphQlRequest> {
let query_params = request.query_string_parameters();
let query = query_params
.first("query")
.ok_or_else(|| anyhow::anyhow!("Missing query parameter"))?;
let variables = query_params
.first("variables")
.and_then(|v| serde_json::from_str(v).ok());
let operation_name = query_params.first("operationName").map(|s| s.to_string());
Ok(GraphQlRequest::new(query.to_string())
.variables(variables.unwrap_or_default())
.operation_name(operation_name.unwrap_or_default()))
}
pub fn graphql_response(response: GraphQlResponse) -> Result<Response<Body>, Error> {
let response_body = serde_json::to_string(&response).map_err(ServerError::from)?;
Response::builder()
.status(StatusCode::OK)
.header("Access-Control-Allow-Origin", "*")
.body(Body::Text(response_body))
.map_err(ServerError::from)
.map_err(Error::from)
}