feat: implement user and forward max connection limit (#461)

* docs: add implementation plan for max conn limit

* feat: add CLimiters support for websocket reporter

* feat: add max_conn field to user and forward models

* feat: implement max conn limiter dispatching

* feat: add maxConn to user and forward CRUD API

* feat: add max conn UI to user management and forward rules

* fix: load MaxConn in get forward record and add e2e contract test for max conn limit
This commit is contained in:
sagit
2026-04-23 17:35:39 +08:00
committed by GitHub
parent bdc2c4ecbb
commit c259645227
15 changed files with 1213 additions and 31 deletions
+16
View File
@@ -157,6 +157,7 @@ interface ForwardForm {
interfaceName?: string;
strategy: string;
speedId: number | null;
maxConn?: number;
}
interface ForwardUserGroup {
@@ -1306,6 +1307,7 @@ export default function ForwardPage() {
interfaceName: "",
strategy: "fifo",
speedId: null,
maxConn: 0,
});
const [inIpTouched, setInIpTouched] = useState(false);
@@ -4723,6 +4725,20 @@ export default function ForwardPage() {
</ModalHeader>
<ModalBody>
<div className="space-y-4 pb-4">
<Input
label="最大连接数"
placeholder="0 或空表示不限制"
type="number"
min="0"
value={form.maxConn === 0 ? "" : String(form.maxConn || "")}
onChange={(e) => {
const value = Math.max(Number(e.target.value) || 0, 0);
setForm((prev) => ({ ...prev, maxConn: value }));
}}
description="此设置优先于用户的全局连接数限制。0 表示不限制。"
variant="bordered"
/>
<Input
errorMessage={errors.name}
isInvalid={!!errors.name}
+25
View File
@@ -219,6 +219,7 @@ export default function UserPage() {
num: 10,
expTime: null,
flowResetTime: 0,
maxConn: 0,
});
const [userFormLoading, setUserFormLoading] = useState(false);
const [quotaResetLoading, setQuotaResetLoading] = useState(false);
@@ -514,6 +515,7 @@ export default function UserPage() {
num: 10,
expTime: null,
flowResetTime: 0,
maxConn: 0,
groupIds: [],
});
onUserModalOpen();
@@ -1516,6 +1518,28 @@ export default function UserPage() {
setUserForm((prev) => ({ ...prev, flow: value }));
}}
/>
<Input
label="最大连接数"
placeholder="0 或空表示不限制"
type="number"
min="0"
value={userForm.maxConn === 0 ? "" : String(userForm.maxConn || "")}
onChange={(e) => {
const value = Math.max(Number(e.target.value) || 0, 0);
setUserForm((prev) => ({ ...prev, maxConn: value }));
}}
/>
<Input
label="最大连接数"
placeholder="0 或空表示不限制"
type="number"
min="0"
value={userForm.maxConn === 0 ? "" : String(userForm.maxConn || "")}
onChange={(e) => {
const value = Math.max(Number(e.target.value) || 0, 0);
setUserForm((prev) => ({ ...prev, maxConn: value }));
}}
/>
<Input
isRequired
label="规则数量"
@@ -1926,6 +1950,7 @@ export default function UserPage() {
<TableColumn>规则数量</TableColumn>
<TableColumn>状态</TableColumn>
<TableColumn>限速规则</TableColumn>
<TableColumn>最大连接</TableColumn>
<TableColumn>重置时间</TableColumn>
<TableColumn>到期时间</TableColumn>
<TableColumn>操作</TableColumn>