You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+35-21Lines changed: 35 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -117,15 +117,25 @@ For queries that return a list, the complexity can be determined by providing a
117
117
118
118
1. Slicing arguments: lists must be bounded by one integer slicing argument in order to calculate the complexity for the field. Thispackage supports the slicing arguments`first`, `last` and `limit`. The complexity of the list will be the value passed as the argument to the field.
119
119
120
-
2. Directives: To use directives, `@listCost` must be defined in your schema with`directive @listCost(cost: Int!) on FIELD_DEFINITION`. Then, on any unbounded list field, add `@listCost(cost: <Int>)` where `<Int>` is the complexity you want applied to the list when queried.
120
+
2. Directives: To use directives, `@listCost` must be defined in your schema with`directive @listCost(cost: Int!) on FIELD_DEFINITION`. Then, on any field which resolves to an unbounded list, add `@listCost(cost: [Int])` where `[Int]` is the complexity forthis field.
121
121
122
-
(Note: Slicing arguments are preferred!`@listCost` is in place for any reason slicing arguments cannot be used.)
122
+
(Note: Slicing arguments are preferred and will override the the `@listCost` directive!`@listCost` is in place as a fall back.)
123
+
124
+
```graphql
125
+
directive @listCost(cost: Int!) on FIELD_DEFINITION
126
+
type Human {
127
+
id: ID!
128
+
}
129
+
type Query {
130
+
humans: [Human] @listCost(cost: 10)
131
+
}
132
+
```
123
133
124
134
## <a name="how-it-works"></a> How It Works
125
135
126
136
Requests are rate-limited based on the IP address associated with the request.
127
137
128
-
On server start, the GraphQL (GQL) schema is parsed to build an object that maps GQL types/fields to their corresponding weights. Type weights can be provided during <a href="typeWeights">initial configuration</a>. When a request is received, this object is used to cross reference the fields queried by the user and compute the complexity of each field. The total complexity of the request is the sum of these values.
138
+
On startup, the GraphQL (GQL) schema is parsed to build an object that maps GQL types/fields to their corresponding weights. Type weights can be provided during <a href="typeWeights">initial configuration</a>. When a request is received, this object is used to cross reference the fields queried by the user and compute the complexity of each field. The total complexity of the request is the sum of these values.
129
139
130
140
Complexity is determined, statically (before any resolvers are called) to estimate the upper bound of the response size - a proxy for the work done by the server to build the response. The total complexity is then used to allow/block the request based on popular rate-limiting algorithms.
131
141
@@ -134,19 +144,23 @@ Requests for each user are processed sequentially by the rate limiter.
134
144
Example (with default weights):
135
145
136
146
```graphql
137
-
query { # 1 query
138
-
hero (episode: EMPIRE) { # 1 object
139
-
name # 0 scalar
140
-
id # 0 scalar
141
-
friends (first: 3) { # 3 objects
142
-
name # 0 scalar
143
-
id # 0 scalar
144
-
}
145
-
}
146
-
reviews (episode: EMPIRE, limit: 5) { # 5 objects
147
-
stars # 0 scalar
148
-
commentary # 0 scalar
149
-
}
147
+
query {
148
+
# 1 query
149
+
hero(episode: EMPIRE) {
150
+
# 1 object
151
+
name # 0 scalar
152
+
id # 0 scalar
153
+
friends(first: 3) {
154
+
# 3 objects
155
+
name # 0 scalar
156
+
id # 0 scalar
157
+
}
158
+
}
159
+
reviews(episode: EMPIRE, limit: 5) {
160
+
# 5 objects
161
+
stars # 0 scalar
162
+
commentary # 0 scalar
163
+
}
150
164
} # total complexity of 10
151
165
```
152
166
@@ -155,10 +169,10 @@ query { # 1 query
155
169
1.<b>Blocked Requests</b>: blocked requests recieve a response with,
156
170
157
171
- status of`429`for`Too Many Requests`
158
-
-`Retry-After` header with a value ofthe time to wait in seconds before the request would be approved (`Infinity`if the complexity is greater than rate-limiting capacity).
159
-
-AJSON response with the `tokens` available, `complexity`of the query, `depth`of the query, `success`of the query set to `false`, and the UNIX`timestamp`of the request
172
+
-`Retry-After` header indicating the time to wait in seconds before the request could be approved (`Infinity`if the complexity is greater than rate-limiting capacity).
173
+
-AJSON response with the remaining `tokens` available, `complexity`of the query, `depth`of the query, `success`of the query set to `false`, and the UNIX`timestamp`of the request
160
174
161
-
2.<b>Successful Requests</b>: successful requests are passed onto the next function in the middleware chain with the following properties saved to `res.locals`
175
+
2.<b>Successful Requests</b>: successful requests are passed on to the next function in the middleware chain with the following properties saved to `res.locals`
162
176
163
177
```javascript
164
178
{
@@ -167,15 +181,15 @@ query { # 1 query
167
181
tokens: number, // tokens available after request
168
182
compexity: number, // complexity of the query
169
183
depth: number, // depth of the query
170
-
timestamp: number, //ms
184
+
timestamp: number, //UNIX timestamp
171
185
}
172
186
}
173
187
```
174
188
175
189
## <a name="error-handling"></a> Error Handling
176
190
177
191
- Incoming queries are validated against the GraphQL schema. If the query is invalid, a response with status code `400` is returned along with an array of GraphQL Errors that were found.
178
-
- To avoid disrupting server activity, errors thrown during the analysis and rate-limiting of the query are logged and the request is passed onto the next middleware function in the chain.
192
+
- To avoid disrupting server activity, errors thrown during the analysis and rate-limiting of the query are logged and the request is passed onto the next piece of middleware in the chain.
179
193
180
194
## <a name="future-development"></a> Future Development
0 commit comments