1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use async_graphql::{ObjectType, SubscriptionType};
use aws_lambda_events::encodings::Body;
use netlify_lambda_http::{Request, Response};
use std::any::Any;
use diana::{DianaHandler, DianaResponse, Options};
pub type AwsError = Box<dyn std::error::Error + Send + Sync + 'static>;
enum AwsReqData {
Valid((String, Option<String>)),
Invalid(Response<String>),
}
fn get_data_from_aws_req(req: Request) -> Result<AwsReqData, AwsError> {
let body = req.body();
let body = match body {
Body::Text(body_str) => body_str.to_string(),
Body::Binary(body_binary) => {
let body_str = std::str::from_utf8(&body_binary);
match body_str {
Ok(body_str) => body_str.to_string(),
Err(_) => {
let res = Response::builder()
.status(400)
.body(
"Found binary body that couldn't be serialized to string".to_string(),
)?;
return Ok(AwsReqData::Invalid(res));
}
}
}
Body::Empty => {
let res = Response::builder()
.status(400)
.body("Found empty body, expected string".to_string())?;
return Ok(AwsReqData::Invalid(res));
}
};
let auth_header = req.headers().get("Authorization");
let auth_header = match auth_header {
Some(auth_header) => {
let header_str = auth_header.to_str();
match header_str {
Ok(header_str) => Some(header_str.to_string()),
Err(_) => {
let res = Response::builder()
.status(400)
.body("Couldn't parse authorization header as string".to_string())?;
return Ok(AwsReqData::Invalid(res));
}
}
}
None => None,
};
Ok(AwsReqData::Valid((body, auth_header)))
}
fn parse_aws_res(res: DianaResponse) -> Result<Response<String>, AwsError> {
let res = match res {
DianaResponse::Success(gql_res_str) => Response::builder()
.status(200)
.body(gql_res_str)?,
DianaResponse::Blocked => Response::builder()
.status(403)
.body("Request blocked due to invalid or insufficient authentication".to_string())?,
DianaResponse::Error(_) => Response::builder()
.status(500)
.body("An internal server error occurred".to_string())?,
};
Ok(res)
}
pub async fn run_aws_req<C, Q, M, S>(
req: Request,
opts: Options<C, Q, M, S>,
) -> Result<Response<String>, AwsError>
where
C: Any + Send + Sync + Clone,
Q: Clone + ObjectType + 'static,
M: Clone + ObjectType + 'static,
S: Clone + SubscriptionType + 'static,
{
let diana_handler = DianaHandler::new(opts.clone()).map_err(|err| err.to_string())?;
let req_data = get_data_from_aws_req(req)?;
let (body, auth_header) = match req_data {
AwsReqData::Valid(data) => data,
AwsReqData::Invalid(http_res) => return Ok(http_res),
};
let res = diana_handler
.run_stateless_without_subscriptions(body, auth_header.as_deref(), None)
.await;
let http_res = parse_aws_res(res)?;
Ok(http_res)
}