DI Integration
The rateLimiterFactoryResolverDiFactory function creates an IRateLimiterFactoryResolver whose underlying resolver is resolved from a DI container.
The returned proxy implements both IRateLimiterFactoryResolver and IRateLimiterFactory:
use(adapterName?)selects an adapter on the resolvedRateLimiterFactoryResolver.create(key, settings)creates a rate limiter through the resolver's default adapter.
The proxy is wired to the container during container.init(). Create it before calling init(); calling use() or create() before the container is initialized throws an error.
Initial configuration
Set up the memory and Redis rate-limiter adapters, create the container, then register the RateLimiterFactoryResolver and wrap it with rateLimiterFactoryResolverDiFactory:
1. Set up the memory rate-limiter adapter
import { DatabaseRateLimiterAdapter } from "eridu-tech/rate-limiter/database-rate-limiter-adapter";
import { MemoryRateLimiterStorageAdapter } from "eridu-tech/rate-limiter/memory-rate-limiter-storage-adapter";
export const memoryRateLimiterAdapter = new DatabaseRateLimiterAdapter({
adapter: new MemoryRateLimiterStorageAdapter(),
});
2. Set up the Redis rate-limiter adapter
import { RedisRateLimiterAdapter } from "eridu-tech/rate-limiter/redis-rate-limiter-adapter";
import { Redis } from "ioredis";
export const redisRateLimiterAdapter = new RedisRateLimiterAdapter({
database: new Redis("YOUR_REDIS_CONNECTION_STRING"),
});
3. Create the dependency injection container
import { Container } from "eridu-tech/di";
import { ExecutionContext } from "eridu-tech/execution-context";
import { AlsExecutionContextAdapter } from "eridu-tech/execution-context/als-execution-context-adapter";
export const executionContext = new ExecutionContext(
new AlsExecutionContextAdapter(),
);
export const container = new Container({ executionContext });
4. Register and initialize the rate-limiter factory resolver
import { RateLimiterFactoryResolver } from "eridu-tech/rate-limiter";
import { ProxyRateLimiterFactoryResolver } from "eridu-tech/rate-limiter/di";
import { container } from "./container.js";
import { memoryRateLimiterAdapter } from "./memory-rate-limiter-adapter.js";
import { redisRateLimiterAdapter } from "./redis-rate-limiter-adapter.js";
import { SuperJsonSerde } from "eridu-tech/serde/super-json-serde";
type Adapters = "memory" | "redis";
const serde = new SuperJsonSerde();
const rateLimiterFactoryResolver = new RateLimiterFactoryResolver<Adapters>({
serde,
adapters: {
memory: memoryRateLimiterAdapter,
redis: redisRateLimiterAdapter,
},
defaultAdapter: "memory",
});
await rateLimiterFactoryResolver.init();
container.registerValue({
token: RateLimiterFactoryResolver,
value: rateLimiterFactoryResolver,
});
// Create the proxy before container.init()
export const rateLimiterFactory = new ProxyRateLimiterFactoryResolver<Adapters>(
{
container,
resolverToken: RateLimiterFactoryResolver,
},
);
await container.init();
Usage
1. Using the default adapter
import { rateLimiterFactory } from "./rate-limiter-factory-resolver-di-factory.js";
// Uses the adapter configured as the default (memory)
await rateLimiterFactory
.create("shared-resource", {
limit: 10,
})
.runOrFail(async () => {
// code to run
});
2. Specifying an adapter explicitly
import { rateLimiterFactory } from "./rate-limiter-factory-resolver-di-factory.js";
// Uses the Redis adapter
await rateLimiterFactory
.use("redis")
.create("shared-resource", {
limit: 10,
})
.runOrFail(async () => {
// code to run
});
Using it with the middlewares
Because the proxy implements IRateLimiterFactoryResolver, it can be passed straight to the rate-limiter middleware factories:
import { use } from "eridu-tech/middleware";
import { withRateLimiterFactory } from "eridu-tech/rate-limiter/middlewares";
import { rateLimiterFactory } from "./rate-limiter-factory-resolver-di-factory.js";
const withRateLimiter = withRateLimiterFactory(rateLimiterFactory);
const fetchHandler = async (request: Request): Promise<Response> => {
// ... handle the request
return new Response("OK");
};
const rateLimitedCall = use(
fetchHandler,
withRateLimiter.use("redis")({
key: ([req]) => `api:${String(req.headers.get("x-ip"))}`,
limit: 10,
}),
);
await rateLimitedCall(
new Request("/url", {
method: "POST",
}),
);
Further information
For further information refer to eridu-tech/rate-limiter API docs.