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
use human_size::Size;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
pub struct LimitsConfig {
/// Configuration of limiting the depth of the incoming GraphQL operations.
/// If not specified, depth limiting is disabled.
///
/// It is used to prevent too large queries that could lead to overfetching or DOS attacks.
#[serde(skip_serializing_if = "Option::is_none")]
pub max_depth: Option<MaxDepthRuleConfig>,
/// Configuration of limiting the number of directives in the incoming GraphQL operations.
/// If not specified, directive limiting is disabled.
///
/// It is used to prevent too many directives that could lead to overfetching or DOS attacks.
#[serde(skip_serializing_if = "Option::is_none")]
pub max_directives: Option<MaxDirectivesRuleConfig>,
/// Configuration of limiting the number of tokens in the incoming GraphQL operations.
/// If not specified, token limiting is disabled.
///
/// It is used to prevent too large queries that could lead to overfetching or DOS attacks.
#[serde(skip_serializing_if = "Option::is_none")]
pub max_tokens: Option<MaxTokensRuleConfig>,
/// Configuration of limiting the number of aliases in the incoming GraphQL operations.
/// If not specified, alias limiting is disabled.
///
/// It is used to prevent too many aliases that could lead to overfetching or DOS attacks.
#[serde(skip_serializing_if = "Option::is_none")]
pub max_aliases: Option<MaxAliasesRuleConfig>,
#[serde(default = "default_max_request_body_size")]
#[schemars(with = "String")]
pub max_request_body_size: Size,
/// The maximum total size of the incoming HTTP request headers.
/// Requests exceeding this limit are rejected with `431 Request Header Fields Too Large`
/// before being processed, so oversized headers (e.g. large cookies) never reach the subgraphs.
///
/// Defaults to `64KiB`.
#[serde(default = "default_max_request_header_size")]
#[schemars(with = "String")]
pub max_request_header_size: Size,
}
impl Default for LimitsConfig {
fn default() -> Self {
Self {
max_depth: None,
max_directives: None,
max_tokens: None,
max_aliases: None,
max_request_body_size: default_max_request_body_size(),
max_request_header_size: default_max_request_header_size(),
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
pub struct MaxDepthRuleConfig {
/// Depth threshold
pub n: usize,
#[serde(default = "default_ignore_introspection")]
/// Ignore the depth of introspection queries.
pub ignore_introspection: bool,
#[serde(default = "default_flatten_fragments")]
/// Flatten fragment spreads and inline fragments when calculating depth.
pub flatten_fragments: bool,
}
fn default_ignore_introspection() -> bool {
true
}
fn default_flatten_fragments() -> bool {
false
}
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
pub struct MaxDirectivesRuleConfig {
/// Directives threshold
pub n: usize,
}
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
pub struct MaxTokensRuleConfig {
/// Tokens threshold
pub n: usize,
}
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
pub struct MaxAliasesRuleConfig {
/// Aliases threshold
pub n: usize,
}
fn default_max_request_body_size() -> Size {
"2MB".parse().expect(
"Default value for 'limits.max_request_body_size' should be a valid human-readable size",
)
}
fn default_max_request_header_size() -> Size {
// Matches ntex's default HTTP message buffer size (64 * 1024 bytes).
"64KiB".parse().expect(
"Default value for 'limits.max_request_header_size' should be a valid human-readable size",
)
}