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
+84-1Lines changed: 84 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,9 @@
7
7
</div>
8
8
9
9
10
+
## Summary
11
+
12
+
Developed under tech-accelerator [OSLabs](https://opensourcelabs.io/), GraphQLGate strives for a principled approach to complexity analysis and rate-limiting for GraphQL queries by accurately estimating an upper-bound of the response size of the query. Within a loosely opinionated framework with lots of configuration options, you can reliably throttle GraphQL queries by complexity and depth to protect your GraphQL API. Our solution is inspired by [this paper](https://github.com/Alan-Cha/fse20/blob/master/submissions/functional/FSE-24/graphql-paper.pdf) from IBM research teams.
10
13
11
14
## Table of Contents
12
15
@@ -16,6 +19,7 @@
16
19
-[How It Works](#how-it-works)
17
20
-[Response](#response)
18
21
-[Error Handling](#error-handling)
22
+
-[Internals](#internals)
19
23
-[Future Development](#future-development)
20
24
-[Contributions](#contributions)
21
25
-[Developers](#developers)
@@ -176,7 +180,7 @@ query {
176
180
177
181
```javascript
178
182
{
179
-
graphglGate: {
183
+
graphqlGate: {
180
184
success: boolean, // true when successful
181
185
tokens: number, // tokens available after request
182
186
compexity: number, // complexity of the query
@@ -191,6 +195,85 @@ query {
191
195
- 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.
192
196
- 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.
193
197
198
+
## <a name="internals"></a> Internals
199
+
200
+
This package exposes 3 additional functionalities which comprise the internals of the package. This is a breif documentaion on them.
201
+
202
+
### Complexity Analysis
203
+
204
+
1. #### `typeWeightsFromSchema` | function to create the type weight object from the schema for complexity analysis
205
+
206
+
- `schema: GraphQLSchema` | GraphQL schema object
207
+
- `typeWeightsConfig: TypeWeightConfig = defaultTypeWeightsConfig` | type weight configuration
208
+
- `enforceBoundedLists = false`
209
+
- returns: `TypeWeightObject`
210
+
- usage:
211
+
212
+
```ts
213
+
import { typeWeightsFromSchema } from 'graphql-limiter';
214
+
import { GraphQLSchema } from 'graphql/type/schema';
- returns:`{ success: boolean, tokens: number, retryAfter?: number }`| where `tokens` is tokens available, `retryAfter` is time to wait in seconds before the request would be successful and `success` is falseif the request is blocked
// Fragments can only be defined on the root type.
265
-
// Parse the complexity of this fragment once and store it for use when analyzing other
266
-
// nodes. The complexity of a fragment can be added to the selection cost for the query.
265
+
// Parse the complexity of this fragment once and store it for use when analyzing other nodes
267
266
constnamedType=node.typeCondition.name.value;
268
267
// Duplicate fragment names are not allowed by the GraphQL spec and an error is thrown if used.
269
268
constfragmentName=node.name.value;
@@ -276,10 +275,12 @@ class ASTParser {
276
275
// Don't count fragment complexity in the node's complexity. Only when fragment is used.
277
276
this.fragmentCache[fragmentName]={
278
277
complexity: fragmentComplexity,
279
-
depth: this.maxDepth-1,// subtract one from the calculated depth of the fragment to correct for the additional depth the fragment ads to the query when used
278
+
depth: this.maxDepth-1,// subtract one from the calculated depth of the fragment to correct for the additional depth the fragment adds to the query when used
280
279
};
281
-
}// else {
282
-
// // TODO: Verify that are no other type definition nodes that need to be handled (see ast.d.ts in 'graphql')
280
+
}
281
+
// TODO: Verify that there are no other type definition nodes that need to be handled (see ast.d.ts in 'graphql')
282
+
// else {
283
+
//
283
284
// // Other types include TypeSystemDefinitionNode (Schema, Type, Directvie) and
284
285
// // TypeSystemExtensionNode(Schema, Type);
285
286
// throw new Error(`ERROR: ASTParser.definitionNode: ${node.kind} type not supported`);
@@ -289,19 +290,18 @@ class ASTParser {
289
290
290
291
privatedocumentNode(node: DocumentNode): number{
291
292
letcomplexity=0;
292
-
// sort the definitions array by kind so that fragments are always parsed first.
293
+
// Sort the definitions array by kind so that fragments are always parsed first.
293
294
// Fragments must be parsed first so that their complexity is available to other nodes.
0 commit comments