Skip to content

Commit af04443

Browse files
committed
added descriptive error handling to middleware setup
1 parent f222b82 commit af04443

File tree

4 files changed

+71
-43
lines changed

4 files changed

+71
-43
lines changed

src/analysis/buildTypeWeights.ts

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -417,22 +417,28 @@ function buildTypeWeightsFromSchema(
417417
typeWeightsConfig: TypeWeightConfig = defaultTypeWeightsConfig,
418418
enforceBoundedLists = false
419419
): TypeWeightObject {
420-
if (!schema) throw new Error('Missing Argument: schema is required');
420+
try {
421+
if (!schema) throw new Error('Missing Argument: schema is required');
421422

422-
// Merge the provided type weights with the default to account for missing values
423-
const typeWeights: TypeWeightSet = {
424-
...defaultTypeWeightsConfig,
425-
...typeWeightsConfig,
426-
};
423+
// Merge the provided type weights with the default to account for missing values
424+
const typeWeights: TypeWeightSet = {
425+
...defaultTypeWeightsConfig,
426+
...typeWeightsConfig,
427+
};
427428

428-
// Confirm that any custom weights are non-negative
429-
Object.entries(typeWeights).forEach((value: [string, number]) => {
430-
if (value[1] < 0) {
431-
throw new Error(`Type weights cannot be negative. Received: ${value[0]}: ${value[1]} `);
432-
}
433-
});
429+
// Confirm that any custom weights are non-negative
430+
Object.entries(typeWeights).forEach((value: [string, number]) => {
431+
if (value[1] < 0) {
432+
throw new Error(
433+
`Type weights cannot be negative. Received: ${value[0]}: ${value[1]} `
434+
);
435+
}
436+
});
434437

435-
return parseTypes(schema, typeWeights, enforceBoundedLists);
438+
return parseTypes(schema, typeWeights, enforceBoundedLists);
439+
} catch (err) {
440+
throw new Error(`Error in expressGraphQLRateLimiter when parsing schema object: ${err}`);
441+
}
436442
}
437443

438444
export default buildTypeWeightsFromSchema;

src/middleware/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,15 @@ export default function expressGraphQLRateLimiter(
4646
enforceBoundedLists: middlewareConfig.enforceBoundedLists || false,
4747
depthLimit: middlewareConfig.depthLimit || Infinity,
4848
};
49+
if (middlewareSetup.depthLimit <= 1) {
50+
throw new Error(
51+
`Error in expressGraphQLRateLimiter: depthLimit cannot be less than or equal to 1`
52+
);
53+
}
4954
/**
5055
* build the type weight object, create the redis client and instantiate the ratelimiter
5156
* before returning the express middleware that calculates query complexity and throttles the requests
5257
*/
53-
// FIXME: Error handling
5458
const typeWeightObject = buildTypeWeightsFromSchema(
5559
schema,
5660
middlewareSetup.typeWeights,

src/middleware/rateLimiterSetup.ts

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,45 @@ export default function setupRateLimiter(
1919
client: Redis,
2020
keyExpiry: number
2121
) {
22-
switch (rateLimiter.type) {
23-
case 'TOKEN_BUCKET':
24-
return new TokenBucket(rateLimiter.capacity, rateLimiter.refillRate, client, keyExpiry);
25-
break;
26-
case 'LEAKY_BUCKET':
27-
throw new Error('Leaky Bucket algonithm has not be implemented.');
28-
case 'FIXED_WINDOW':
29-
return new FixedWindow(rateLimiter.capacity, rateLimiter.windowSize, client, keyExpiry);
30-
case 'SLIDING_WINDOW_LOG':
31-
return new SlidingWindowLog(
32-
rateLimiter.windowSize,
33-
rateLimiter.capacity,
34-
client,
35-
keyExpiry
36-
);
37-
case 'SLIDING_WINDOW_COUNTER':
38-
return new SlidingWindowCounter(
39-
rateLimiter.windowSize,
40-
rateLimiter.capacity,
41-
client,
42-
keyExpiry
43-
);
44-
break;
45-
default:
46-
// typescript should never let us invoke this function with anything other than the options above
47-
throw new Error('Selected rate limiting algorithm is not suppported');
22+
try {
23+
switch (rateLimiter.type) {
24+
case 'TOKEN_BUCKET':
25+
return new TokenBucket(
26+
rateLimiter.capacity,
27+
rateLimiter.refillRate,
28+
client,
29+
keyExpiry
30+
);
31+
break;
32+
case 'LEAKY_BUCKET':
33+
throw new Error('Leaky Bucket algonithm has not be implemented.');
34+
case 'FIXED_WINDOW':
35+
return new FixedWindow(
36+
rateLimiter.capacity,
37+
rateLimiter.windowSize,
38+
client,
39+
keyExpiry
40+
);
41+
case 'SLIDING_WINDOW_LOG':
42+
return new SlidingWindowLog(
43+
rateLimiter.windowSize,
44+
rateLimiter.capacity,
45+
client,
46+
keyExpiry
47+
);
48+
case 'SLIDING_WINDOW_COUNTER':
49+
return new SlidingWindowCounter(
50+
rateLimiter.windowSize,
51+
rateLimiter.capacity,
52+
client,
53+
keyExpiry
54+
);
55+
break;
56+
default:
57+
// typescript should never let us invoke this function with anything other than the options above
58+
throw new Error('Selected rate limiting algorithm is not suppported');
59+
}
60+
} catch (err) {
61+
throw new Error(`Error in expressGraphQLRateLimiter setting up rate-limiter: ${err}`);
4862
}
4963
}

src/utils/redis.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@ const clients: Redis[] = [];
99
export function connect(options: RedisOptions): Redis {
1010
// TODO: Figure out what other options we should set (timeouts, etc)
1111
// TODO: pass on connection error
12-
const client: Redis = new Redis(options);
13-
clients.push(client);
14-
return client;
12+
try {
13+
const client: Redis = new Redis(options);
14+
clients.push(client);
15+
return client;
16+
} catch (err) {
17+
throw new Error(`Error in expressGraphQLRateLimiter when connecting to redis: ${err}`);
18+
}
1519
}
1620

1721
/**

0 commit comments

Comments
 (0)