mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-02 14:56:38 +08:00
feat(rate-limit): add default request rate limit configuration
- Support openresty_default_limit_req_per_ip in system_configs. - Add limit_req and limit_req_status 429 directive generation in openresty renderer. - Implement route-level limit_req_per_ip override and explicit disable. - Add frontend UI inputs and validation in rate limits tab config. - Update swagger API docs and changelog for v3.4.3-beta.3.
This commit is contained in:
@@ -25,6 +25,7 @@ const optionsQueryKey = ['openflare', 'options'] as const;
|
||||
const KEY_CONN_PER_SERVER = 'openresty_default_limit_conn_per_server';
|
||||
const KEY_CONN_PER_IP = 'openresty_default_limit_conn_per_ip';
|
||||
const KEY_LIMIT_RATE = 'openresty_default_limit_rate';
|
||||
const KEY_LIMIT_REQ_PER_IP = 'openresty_default_limit_req_per_ip';
|
||||
|
||||
const limitRatePattern = /^\d+(?:[kKmM])?$/;
|
||||
|
||||
@@ -32,12 +33,14 @@ type RateLimitFields = {
|
||||
openresty_default_limit_conn_per_server: string;
|
||||
openresty_default_limit_conn_per_ip: string;
|
||||
openresty_default_limit_rate: string;
|
||||
openresty_default_limit_req_per_ip: string;
|
||||
};
|
||||
|
||||
const defaultFields: RateLimitFields = {
|
||||
openresty_default_limit_conn_per_server: '0',
|
||||
openresty_default_limit_conn_per_ip: '0',
|
||||
openresty_default_limit_rate: '',
|
||||
openresty_default_limit_req_per_ip: '',
|
||||
};
|
||||
|
||||
function optionsToMap(options: Array<{ key: string; value: string }>) {
|
||||
@@ -55,6 +58,7 @@ function mapOptionsToFields(
|
||||
optionMap[KEY_CONN_PER_SERVER] ?? '0',
|
||||
openresty_default_limit_conn_per_ip: optionMap[KEY_CONN_PER_IP] ?? '0',
|
||||
openresty_default_limit_rate: optionMap[KEY_LIMIT_RATE] ?? '',
|
||||
openresty_default_limit_req_per_ip: optionMap[KEY_LIMIT_REQ_PER_IP] ?? '',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -71,6 +75,13 @@ function validateFields(fields: RateLimitFields) {
|
||||
if (rate && rate !== '0' && !limitRatePattern.test(rate)) {
|
||||
throw new Error('限速格式不合法,请使用 512k、1m、纯数字,或留空关闭');
|
||||
}
|
||||
|
||||
const reqRate = fields.openresty_default_limit_req_per_ip.trim();
|
||||
if (reqRate && reqRate !== '0' && !/^\d+r\/[sm]$/i.test(reqRate)) {
|
||||
throw new Error(
|
||||
'请求频率限制格式不合法,请使用类似 10r/s、100r/m,或留空关闭',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeConnValue(value: string) {
|
||||
@@ -119,6 +130,10 @@ export function ConfigTab() {
|
||||
key: KEY_LIMIT_RATE,
|
||||
value: normalizeRateValue(fields.openresty_default_limit_rate),
|
||||
},
|
||||
{
|
||||
key: KEY_LIMIT_REQ_PER_IP,
|
||||
value: normalizeRateValue(fields.openresty_default_limit_req_per_ip),
|
||||
},
|
||||
]);
|
||||
},
|
||||
onSuccess: async () => {
|
||||
@@ -256,6 +271,25 @@ export function ConfigTab() {
|
||||
单请求带宽默认值,例如 512k 或 1m
|
||||
</p>
|
||||
</div>
|
||||
<div className='space-y-1.5'>
|
||||
<Label className='text-xs text-muted-foreground'>
|
||||
默认单 IP 请求频率限制
|
||||
</Label>
|
||||
<Input
|
||||
value={fields.openresty_default_limit_req_per_ip}
|
||||
placeholder='10r/s / 100r/m'
|
||||
onChange={(e) =>
|
||||
updateField(
|
||||
'openresty_default_limit_req_per_ip',
|
||||
e.target.value,
|
||||
)
|
||||
}
|
||||
className='h-9 text-xs'
|
||||
/>
|
||||
<p className='text-xs text-muted-foreground'>
|
||||
单个 IP 请求频率默认值,例如 10r/s 或 100r/m,留空关闭
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user