diff --git a/.changeset/eight-llamas-mate.md b/.changeset/eight-llamas-mate.md new file mode 100644 index 0000000000..2b5b313a4c --- /dev/null +++ b/.changeset/eight-llamas-mate.md @@ -0,0 +1,5 @@ +--- +'@envelop/rate-limiter': patch +--- + +Fix rate limiting being wrongly applied to all fields with a default configuration. diff --git a/packages/plugins/rate-limiter/src/index.ts b/packages/plugins/rate-limiter/src/index.ts index 1b92018f68..c083849370 100644 --- a/packages/plugins/rate-limiter/src/index.ts +++ b/packages/plugins/rate-limiter/src/index.ts @@ -147,9 +147,10 @@ export const useRateLimiter = (options: RateLimiterPluginOptions): Plugin { ), ).toThrow(`Config error: field 'Query.foo' has both a configuration and a directive`); }); + it('should not rate limit fields that are not in configByField', async () => { + const schema = makeExecutableSchema({ + typeDefs: /* GraphQL */ ` + type Query { + limitedField: String + unlimitedField: String + } + `, + resolvers: { + Query: { + limitedField: () => 'limited', + unlimitedField: () => 'unlimited', + }, + }, + }); + + const testkit = createTestkit( + [ + useRateLimiter({ + identifyFn: (ctx: any) => ctx.ip, + configByField: [ + { + type: 'Query', + field: 'limitedField', + max: 1, + window: '60s', + }, + ], + }), + ], + schema, + ); + + const context = { ip: '127.0.0.1' }; + + const result1 = await testkit.execute(`{ limitedField }`, {}, context); + expect(result1).toEqual({ data: { limitedField: 'limited' } }); + + const result2 = await testkit.execute(`{ limitedField }`, {}, context); + assertSingleExecutionValue(result2); + expect(result2.errors?.[0]?.message).toBe("You are trying to access 'limitedField' too often"); + + // unlimitedField should not be rate limited at all, so we should be able to call it many times + for (let i = 0; i < 10; i++) { + const result = await testkit.execute(`{ unlimitedField }`, {}, context); + assertSingleExecutionValue(result); + expect(result).toEqual({ data: { unlimitedField: 'unlimited' } }); + expect(result.errors).toBeUndefined(); + } + }); });