在我的 fastify 项目中,我想根据 api 密钥的有效性有条件地对某些路由应用速率限制。 如果 validate api 函数返回 false,则限制。如果返回 true,则不应用限制或应用更高的限制。
我尝试按照文档中的说明使用密钥生成器,但由于密钥必须是唯一的。限制是将客户分为两大组。如果客户端 1 受到速率限制,则其他客户端也受到速率限制。
import Fastify from 'fastify';
import fastifyRateLimit from '@fastify/rate-limit';
import dotenv from 'dotenv';
import { redisConnector, validateToken } from './redis/redisConnector.js';
import { psqlConnector } from './database/psqlConnector.js';
import { rpcPost, getRandomNode } from './helpers/rpc.js';
dotenv.config();
const fastify = Fastify({
logger: true
});
redisConnector(fastify);
psqlConnector(fastify);
await fastify.register(fastifyRateLimit, {
async keyGenerator (request) { return await validateToken(fastify, request.headers['x-api-key']) },
max: async (request, key) => { return key === 'true' ? 1000 : 1 },
timeWindow: '1 minute',
global: true,
});
fastify.get('/', async (request, reply) => {
return { hello: 'world' };
});
fastify.post('/test', async (request, reply) => {
let isValidApiKey = 'false';
if (request.headers["x-api-key"]) {
isValidApiKey = await validateToken(fastify, request.headers["x-api-key"]);
console.log(isValidApiKey);
}
return { foo: 'bar' };;
});
fastify.listen({ port: process.env.FASTIFY_PORT || 3000 }, (err, address) => {
if (err) throw err;
});
还有其他想法吗?也许设置 global: false 并使用 preHandler? 任何例子都非常感激
keyGenerator
函数返回 true 或 false,因此所有路由都分配给其中之一。
您应该返回用户独有的内容。更重要的是,我会将
validateToken
逻辑从速率限制一中移出:
// add first an hook to validate the input:
fastify.addHook('onRequest', async (request) => {
return await validateToken(fastify, request.headers['x-api-key'])
})
// then register the plugin:
await fastify.register(fastifyRateLimit, {
async keyGenerator (request) {
// return something that is unique for the user, like a piece of the api key or an hash
return request.headers['x-api-key'].slice(-5)
},
max: async (request, key) => { return key === 'true' ? 1000 : 1 },
timeWindow: '1 minute',
global: true,
});