fix(routing+backends): Pfad-Präfix-Validierung + Warnung bei leerem Backend-Pool (v1.1.141)
- RoutingRules: path_prefix Pattern-Validator (muss mit / beginnen) + destroyOnHidden - Backends: Alert-Banner wenn aktives Backend 0 Server hat (→ HAProxy 503) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -60,7 +60,7 @@ import (
|
||||
usersvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/users"
|
||||
)
|
||||
|
||||
var version = "1.1.140"
|
||||
var version = "1.1.141"
|
||||
|
||||
func main() {
|
||||
addr := os.Getenv("EDGEGUARD_API_ADDR")
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"git.netcell-it.de/projekte/edgeguard-native/internal/services/setup"
|
||||
)
|
||||
|
||||
var version = "1.1.140"
|
||||
var version = "1.1.141"
|
||||
|
||||
const usage = `edgeguard-ctl — EdgeGuard CLI
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ import (
|
||||
"git.netcell-it.de/projekte/edgeguard-native/internal/services/tlscerts"
|
||||
)
|
||||
|
||||
var version = "1.1.140"
|
||||
var version = "1.1.141"
|
||||
|
||||
const (
|
||||
// renewTickInterval — how often we re-evaluate expiring certs.
|
||||
|
||||
@@ -380,6 +380,8 @@
|
||||
"forceHttp1Hint": "Deaktiviert HTTP/2 (h2) auf der Backend-Verbindung — HAProxy handelt nur noch HTTP/1.1 aus. Nötig für Backends die kein h2 unterstützen (z. B. ältere nginx-Konfigurationen ohne h2-Modul, Legacy-Apps).",
|
||||
"servers": "Server",
|
||||
"noServers": "kein Server",
|
||||
"noServersWarning": "Ein oder mehrere aktive Backends haben keine Server konfiguriert.",
|
||||
"noServersWarningDesc": "HAProxy liefert für Traffic auf diese Backends 503. Backend öffnen (oranger Tag) und mindestens einen Server hinzufügen.",
|
||||
"nServers": "{{n}} Server",
|
||||
"serversIn": "Server in „{{name}}\"",
|
||||
"serverHintCreate": "Speichern legt nur den Pool an. Server kommen im nächsten Schritt — Pool öffnen → „Server hinzufügen\".",
|
||||
@@ -415,6 +417,8 @@
|
||||
"editRule": "Regel bearbeiten",
|
||||
"domain": "Domain",
|
||||
"pathPrefix": "Pfad-Präfix",
|
||||
"pathPrefixHint": "Muss mit / beginnen. HAProxy matcht als Präfix.",
|
||||
"pathPrefixInvalid": "Pfad muss mit / beginnen und darf nur gültige URL-Zeichen enthalten",
|
||||
"backend": "Backend",
|
||||
"priority": "Priorität",
|
||||
"active": "Aktiv",
|
||||
|
||||
@@ -380,6 +380,8 @@
|
||||
"forceHttp1Hint": "Disables HTTP/2 (h2) on the backend connection — HAProxy negotiates HTTP/1.1 only. Required for backends that don't support h2 (e.g. older nginx configs without the h2 module, legacy apps).",
|
||||
"servers": "Servers",
|
||||
"noServers": "no server",
|
||||
"noServersWarning": "One or more active backends have no servers configured.",
|
||||
"noServersWarningDesc": "HAProxy will return 503 for any traffic routed to these backends. Open the backend (orange tag) and add at least one server.",
|
||||
"nServers": "{{n}} servers",
|
||||
"serversIn": "Servers in “{{name}}”",
|
||||
"serverHintCreate": "Saving creates the pool only. Add servers in the next step — open the pool and click “Add server”.",
|
||||
@@ -415,6 +417,8 @@
|
||||
"editRule": "Edit rule",
|
||||
"domain": "Domain",
|
||||
"pathPrefix": "Path prefix",
|
||||
"pathPrefixHint": "Must start with /. HAProxy uses prefix matching.",
|
||||
"pathPrefixInvalid": "Path must start with / and contain only valid URL characters",
|
||||
"backend": "Backend",
|
||||
"priority": "Priority",
|
||||
"active": "Active",
|
||||
|
||||
@@ -329,6 +329,15 @@ export default function BackendsPage() {
|
||||
</Tag>
|
||||
)}
|
||||
/>
|
||||
{serverCounts && (data ?? []).some(b => b.active && (serverCounts[b.id] ?? 0) === 0) && (
|
||||
<Alert
|
||||
type="warning"
|
||||
showIcon
|
||||
className="mb-12"
|
||||
message={t('backends.noServersWarning')}
|
||||
description={t('backends.noServersWarningDesc')}
|
||||
/>
|
||||
)}
|
||||
<DataTable
|
||||
rowKey="id"
|
||||
loading={isLoading}
|
||||
|
||||
@@ -270,6 +270,7 @@ export default function RoutingRulesPage() {
|
||||
onCancel={() => { setEditing(null); setCreating(false) }}
|
||||
onOk={() => { void form.submit() }}
|
||||
confirmLoading={create.isPending || update.isPending}
|
||||
destroyOnHidden
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
@@ -285,7 +286,15 @@ export default function RoutingRulesPage() {
|
||||
placeholder={t('routing.selectDomain')}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('routing.pathPrefix')} name="path_prefix" rules={[{ required: true }]}>
|
||||
<Form.Item
|
||||
label={t('routing.pathPrefix')}
|
||||
name="path_prefix"
|
||||
extra={t('routing.pathPrefixHint')}
|
||||
rules={[
|
||||
{ required: true },
|
||||
{ pattern: /^\/[a-zA-Z0-9\-._~!$&'()*+,;=:@/%]*$/, message: t('routing.pathPrefixInvalid') },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="/" />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('routing.backend')} name="backend_id" rules={[{ required: true }]}>
|
||||
|
||||
Reference in New Issue
Block a user