+
+
+
+ ${r.description ? html`
${r.description}
` : ''}
+
+
+
+
+
+
Match
+
+ Ports
+ ${formatPorts(match.ports)}
+
+ ${match.domains
+ ? html`
+
+ Domains
+ ${this.renderDomains(match.domains)}
+
+ `
+ : ''}
+ ${match.path
+ ? html`
+
+ Path
+ ${match.path}
+
+ `
+ : ''}
+ ${match.protocol
+ ? html`
+
+ Protocol
+
+ ${match.protocol}
+
+
+ `
+ : ''}
+ ${match.clientIp && match.clientIp.length > 0
+ ? html`
+
+ Client
+ ${match.clientIp.join(', ')}
+
+ `
+ : ''}
+ ${match.tlsVersion && match.tlsVersion.length > 0
+ ? html`
+
+ TLS Ver
+ ${match.tlsVersion.join(', ')}
+
+ `
+ : ''}
+ ${match.headers
+ ? html`
+
+ Headers
+
+ ${Object.entries(match.headers).map(
+ ([k, v]) => html` `
+ )}
+
+
+ `
+ : ''}
+
+
+
+
+
Action
+ ${action.targets && action.targets.length > 0
+ ? html`
+
+ Targets
+ ${formatTargets(action.targets).join(', ')}
+
+ `
+ : ''}
+ ${action.tls
+ ? html`
+
+ TLS
+
+ ${action.tls.mode}
+ ${action.tls.certificate
+ ? action.tls.certificate === 'auto'
+ ? html` auto cert`
+ : html` custom cert`
+ : ''}
+
+
+ `
+ : ''}
+ ${action.forwardingEngine
+ ? html`
+
+ Engine
+ ${action.forwardingEngine}
+
+ `
+ : ''}
+ ${action.loadBalancing
+ ? html`
+
+ LB
+ ${action.loadBalancing.algorithm}
+
+ `
+ : ''}
+ ${action.websocket?.enabled
+ ? html`
+
+ WS
+ enabled
+
+ `
+ : ''}
+
+
+
+ ${security
+ ? html`
+
+
Security
+ ${security.ipAllowList && security.ipAllowList.length > 0
+ ? html`
+
+ Allow
+ ${security.ipAllowList.join(', ')}
+
+ `
+ : ''}
+ ${security.ipBlockList && security.ipBlockList.length > 0
+ ? html`
+
+ Block
+ ${security.ipBlockList.join(', ')}
+
+ `
+ : ''}
+ ${security.rateLimit?.enabled
+ ? html`
+
+ Rate
+ ${security.rateLimit.maxRequests} req / ${security.rateLimit.window}s
+
+ `
+ : ''}
+ ${security.maxConnections
+ ? html`
+
+ Max Conn
+ ${security.maxConnections}
+
+ `
+ : ''}
+
+ `
+ : ''}
+
+
+ ${this.renderFeatures()}
+
+ `;
+ }
+
+ private renderDomains(domains: string | string[]): TemplateResult {
+ const list = Array.isArray(domains) ? domains : [domains];
+ return html`${list.map(
+ (d) =>
+ html`
+
{
+ this.searchQuery = (e.target as HTMLInputElement).value;
+ }}
+ />
+
+ ${(['all', 'forward', 'socket-handler'] as const).map(
+ (type) => html`
+
+ `
+ )}
+
+
+ ${(['all', 'enabled', 'disabled'] as const).map(
+ (status) => html`
+
+ `
+ )}
+
+
+
+
+ ${filtered.map(
+ (route) => html`
+ this.handleRouteClick(route)}
+ >
+ `
+ )}
+
+ `
+ : html`
+