Documentation
¶
Overview ¶
internal/api/awg_outbounds.go
Package api — NDMS-specific endpoints (non-routing, non-tunnel).
Currently exposes GET /api/ndms/save-status, which mirrors the former save:status SSE event. The endpoint is part of the state-sync redesign: SaveCoordinator publishes a resource:invalidated hint on state changes and clients refetch this endpoint.
Package api — singbox_proxies.go exposes runtime controls for sing-box composite outbounds (selector / urltest / loadbalance) by relaying typed requests to the upstream Clash API. The handler is kept thin: shape the request, call Clash, shape the response into project-standard envelopes.
Index ¶
- Constants
- func BuildTunnelResponse(r *http.Request, svc TunnelService, store *storage.AWGTunnelStore, id string, ...) (map[string]interface{}, error)
- func ServeOS4EmptyAccessPolicies(w http.ResponseWriter, r *http.Request)
- func ServeOS4EmptyPolicyInterfaces(w http.ResponseWriter, r *http.Request)
- func WriteTunnelReferenced(w http.ResponseWriter, err tunnelservice.ErrTunnelReferenced)
- type APIEnvelope
- type APIErrorEnvelope
- type ASCParamsResponse
- type AWGInterfaceDTO
- type AWGOutboundTagDTO
- type AWGOutboundTagsResponse
- type AWGOutboundsHandler
- type AWGOutboundsService
- type AWGPeerDTO
- type AWGTunnelDTO
- type AccessPoliciesListResponse
- type AccessPolicyDTO
- type AccessPolicyHandler
- func (h *AccessPolicyHandler) AssignDevice(w http.ResponseWriter, r *http.Request)
- func (h *AccessPolicyHandler) Create(w http.ResponseWriter, r *http.Request)
- func (h *AccessPolicyHandler) Delete(w http.ResponseWriter, r *http.Request)
- func (h *AccessPolicyHandler) List(w http.ResponseWriter, r *http.Request)
- func (h *AccessPolicyHandler) ListDevices(w http.ResponseWriter, r *http.Request)
- func (h *AccessPolicyHandler) ListGlobalInterfaces(w http.ResponseWriter, r *http.Request)
- func (h *AccessPolicyHandler) PermitInterface(w http.ResponseWriter, r *http.Request)
- func (h *AccessPolicyHandler) SetDescription(w http.ResponseWriter, r *http.Request)
- func (h *AccessPolicyHandler) SetEventBus(bus *events.Bus)
- func (h *AccessPolicyHandler) SetInterfaceUp(w http.ResponseWriter, r *http.Request)
- func (h *AccessPolicyHandler) SetStandalone(w http.ResponseWriter, r *http.Request)
- type AccessPolicyInterfaceDTO
- type AccessPolicyResponse
- type ActiveMemberRequest
- type ActiveNowResponse
- type AddGeoFileRequest
- type AddMemberRequest
- type AddPeerRequestDTO
- type AdoptRequest
- type AllInterfacesResponse
- type AmneziaCPHandler
- type AmneziaPremiumAccountInfoRequest
- type AmneziaPremiumAccountInfoResponse
- type AmneziaPremiumDownloadConfigData
- type AmneziaPremiumDownloadConfigRequest
- type AmneziaPremiumDownloadConfigResponse
- type AmneziaPremiumLoginData
- type AmneziaPremiumLoginRequest
- type AmneziaPremiumLoginResponse
- type AssignDeviceRequest
- type AuthHandler
- type AuthStatusResponse
- type BackupWarningDTO
- type BootStatusHandler
- type BootStatusResponse
- type ChangelogData
- type ChangelogEntryDTO
- type ChangelogGroupDTO
- type ChangelogResponse
- type ClashProxy
- type ClientRouteDTO
- type ClientRouteHandler
- func (h *ClientRouteHandler) HandleCreate(w http.ResponseWriter, r *http.Request)
- func (h *ClientRouteHandler) HandleDelete(w http.ResponseWriter, r *http.Request)
- func (h *ClientRouteHandler) HandleList(w http.ResponseWriter, r *http.Request)
- func (h *ClientRouteHandler) HandleToggle(w http.ResponseWriter, r *http.Request)
- func (h *ClientRouteHandler) HandleUpdate(w http.ResponseWriter, r *http.Request)
- func (h *ClientRouteHandler) SetEventBus(bus *events.Bus)
- type ClientRoutesListResponse
- type ConnectionProtocolsDTO
- type ConnectionStatsDTO
- type ConnectionsData
- type ConnectionsHandler
- type ConnectionsPaginationDTO
- type ConnectionsResponseEnvelope
- type ConnectivityResultData
- type ConnectivityResultResponse
- type ConntrackConnectionDTO
- type ControlHandler
- func (h *ControlHandler) Restart(w http.ResponseWriter, r *http.Request)
- func (h *ControlHandler) RestartAll(w http.ResponseWriter, r *http.Request)
- func (h *ControlHandler) SetCatalog(_ routing.Catalog)
- func (h *ControlHandler) SetEventBus(bus *events.Bus)
- func (h *ControlHandler) SetOrchestrator(orch *orchestrator.Orchestrator)
- func (h *ControlHandler) SetPingCheckService(svc PingCheckService)
- func (h *ControlHandler) SetTunnelsHandler(th *TunnelsHandler)
- func (h *ControlHandler) Start(w http.ResponseWriter, r *http.Request)
- func (h *ControlHandler) Stop(w http.ResponseWriter, r *http.Request)
- func (h *ControlHandler) ToggleDefaultRoute(w http.ResponseWriter, r *http.Request)
- func (h *ControlHandler) ToggleEnabled(w http.ResponseWriter, r *http.Request)
- type CreateAccessPolicyRequest
- type CreateServerRequestDTO
- type CreateSubscriptionRequest
- type DNSRewritesHandler
- func (h *DNSRewritesHandler) Add(w http.ResponseWriter, r *http.Request)
- func (h *DNSRewritesHandler) Delete(w http.ResponseWriter, r *http.Request)
- func (h *DNSRewritesHandler) List(w http.ResponseWriter, r *http.Request)
- func (h *DNSRewritesHandler) Move(w http.ResponseWriter, r *http.Request)
- func (h *DNSRewritesHandler) Update(w http.ResponseWriter, r *http.Request)
- type DNSRewritesService
- type DNSRouteHandler
- func (h *DNSRouteHandler) BulkBackend(w http.ResponseWriter, r *http.Request)
- func (h *DNSRouteHandler) Create(w http.ResponseWriter, r *http.Request)
- func (h *DNSRouteHandler) CreateBatch(w http.ResponseWriter, r *http.Request)
- func (h *DNSRouteHandler) Delete(w http.ResponseWriter, r *http.Request)
- func (h *DNSRouteHandler) DeleteBatch(w http.ResponseWriter, r *http.Request)
- func (h *DNSRouteHandler) Get(w http.ResponseWriter, r *http.Request)
- func (h *DNSRouteHandler) List(w http.ResponseWriter, r *http.Request)
- func (h *DNSRouteHandler) Refresh(w http.ResponseWriter, r *http.Request)
- func (h *DNSRouteHandler) SetEnabled(w http.ResponseWriter, r *http.Request)
- func (h *DNSRouteHandler) SetEventBus(bus *events.Bus)
- func (h *DNSRouteHandler) Update(w http.ResponseWriter, r *http.Request)
- type DNSRouteService
- type DNSRouteSettingsDTO
- type DeviceProxyAuthDTO
- type DeviceProxyConfigData
- type DeviceProxyHandler
- func (h *DeviceProxyHandler) ApplyInstances(w http.ResponseWriter, r *http.Request)
- func (h *DeviceProxyHandler) CheckInstanceExternalIP(w http.ResponseWriter, r *http.Request)
- func (h *DeviceProxyHandler) DeleteInstance(w http.ResponseWriter, r *http.Request)
- func (h *DeviceProxyHandler) ForceApply(w http.ResponseWriter, r *http.Request)
- func (h *DeviceProxyHandler) GetConfig(w http.ResponseWriter, r *http.Request)
- func (h *DeviceProxyHandler) GetInstance(w http.ResponseWriter, r *http.Request)
- func (h *DeviceProxyHandler) GetInstanceRuntime(w http.ResponseWriter, r *http.Request)
- func (h *DeviceProxyHandler) GetRuntime(w http.ResponseWriter, r *http.Request)
- func (h *DeviceProxyHandler) ListInstances(w http.ResponseWriter, r *http.Request)
- func (h *DeviceProxyHandler) ListOutbounds(w http.ResponseWriter, r *http.Request)
- func (h *DeviceProxyHandler) ListenChoices(w http.ResponseWriter, r *http.Request)
- func (h *DeviceProxyHandler) SaveConfig(w http.ResponseWriter, r *http.Request)
- func (h *DeviceProxyHandler) SaveInstance(w http.ResponseWriter, r *http.Request)
- func (h *DeviceProxyHandler) SelectInstanceRuntime(w http.ResponseWriter, r *http.Request)
- func (h *DeviceProxyHandler) SelectRuntime(w http.ResponseWriter, r *http.Request)
- type DeviceProxyInstanceData
- type DeviceProxyInstanceIPCheckResponse
- type DeviceProxyInstanceIPCheckResultDTO
- type DeviceProxyOutboundDTO
- type DeviceProxyRuntimeData
- type DiagnosticsHandler
- func (h *DiagnosticsHandler) Result(w http.ResponseWriter, r *http.Request)
- func (h *DiagnosticsHandler) Run(w http.ResponseWriter, r *http.Request)
- func (h *DiagnosticsHandler) Status(w http.ResponseWriter, r *http.Request)
- func (h *DiagnosticsHandler) Stream(w http.ResponseWriter, r *http.Request)
- type DiagnosticsRunner
- type DiagnosticsStatusData
- type DiagnosticsStatusResponse
- type DnsCheckHandler
- type DnsCheckResultDTO
- type DnsCheckStartData
- type DnsCheckStartResponseEnvelope
- type DnsProxyInfoData
- type DnsProxyInfoEnvelope
- type DnsProxyInfoHandler
- type DnsRouteDTO
- type DnsRouteDeleteBatchRequest
- type DnsRouteResponse
- type DnsRouteSubscriptionDTO
- type DnsRouteTargetDTO
- type DnsRouteUpsertRequest
- type DnsRoutesListResponse
- type DownloadHandler
- type DownloadOutboundDTO
- type DownloadOutboundsResponse
- type DownloadRouteDTO
- type DownloadSettingsDTO
- type EnabledToggleRequest
- type EventsHandler
- type ExcludeMembersRequest
- type ExternalTunnelDTO
- type ExternalTunnelService
- type ExternalTunnelsHandler
- type ExternalTunnelsResponse
- type GeoExpandData
- type GeoFileEntryDTO
- type GeoFileResponse
- type GeoFileSettingsDTO
- type GeoFileUpdatedData
- type GeoFileUpdatedResponse
- type GeoFilesRescannedData
- type GeoFilesRescannedResponse
- type GeoFilesResponse
- type GeoTagDTO
- type GeoTagsResponse
- type HealthData
- type HealthHandler
- type HealthResponse
- type HookDispatcher
- type HookHandler
- func (h *HookHandler) EnterSelfCreate()
- func (h *HookHandler) ExitSelfCreate()
- func (h *HookHandler) HandleNDMS(w http.ResponseWriter, r *http.Request)
- func (h *HookHandler) SetDispatcher(d HookDispatcher)
- func (h *HookHandler) SetTunnelRefresher(fn TunnelHookInvalidator)
- func (h *HookHandler) SetWANModel(m HookWANModel)
- type HookWANModel
- type HotspotLister
- type HydraRouteConfigData
- type HydraRouteConfigResponse
- type HydraRouteHandler
- func (h *HydraRouteHandler) AddGeoFile(w http.ResponseWriter, r *http.Request)
- func (h *HydraRouteHandler) DeleteGeoFile(w http.ResponseWriter, r *http.Request)
- func (h *HydraRouteHandler) ExpandGeoTag(w http.ResponseWriter, r *http.Request)
- func (h *HydraRouteHandler) GetConfig(w http.ResponseWriter, r *http.Request)
- func (h *HydraRouteHandler) GetGeoTags(w http.ResponseWriter, r *http.Request)
- func (h *HydraRouteHandler) GetIpsetUsage(w http.ResponseWriter, r *http.Request)
- func (h *HydraRouteHandler) GetOversizedTags(w http.ResponseWriter, r *http.Request)
- func (h *HydraRouteHandler) ListGeoFiles(w http.ResponseWriter, r *http.Request)
- func (h *HydraRouteHandler) RescanGeoFiles(w http.ResponseWriter, r *http.Request)
- func (h *HydraRouteHandler) SetEventBus(bus *events.Bus)
- func (h *HydraRouteHandler) SetPolicyOrder(w http.ResponseWriter, r *http.Request)
- func (h *HydraRouteHandler) TakeGeoFileControl(w http.ResponseWriter, r *http.Request)
- func (h *HydraRouteHandler) UpdateConfig(w http.ResponseWriter, r *http.Request)
- func (h *HydraRouteHandler) UpdateGeoFile(w http.ResponseWriter, r *http.Request)
- type HydraRouteStatusData
- type HydraRouteStatusResponse
- type IPCheckServiceDTO
- type IPResultData
- type IPResultResponse
- type IPServicesResponse
- type ImportHandler
- type IpsetUsageData
- type IpsetUsageResponse
- type KmodLoader
- type LANSegmentEntryDTO
- type LANSegmentsListResponse
- type LogEntryDTO
- type LoggingHandler
- func (h *LoggingHandler) ClearLogs(w http.ResponseWriter, r *http.Request)
- func (h *LoggingHandler) GetLogs(w http.ResponseWriter, r *http.Request)
- func (h *LoggingHandler) GetSubgroups(w http.ResponseWriter, r *http.Request)
- func (h *LoggingHandler) PublishSnapshot()
- func (h *LoggingHandler) SetEventBus(bus *events.Bus)
- type LoggingSettingsDTO
- type LoginRequest
- type LoginResponseRaw
- type LogsData
- type LogsResponse
- type LogsResponseEnvelope
- type ManagedPeerDTO
- type ManagedPeerResponse
- type ManagedPeerStatsDTO
- type ManagedServerBackupDTO
- type ManagedServerBackupFile
- type ManagedServerBackupHandler
- func (h *ManagedServerBackupHandler) Drift(w http.ResponseWriter, r *http.Request)
- func (h *ManagedServerBackupHandler) Export(w http.ResponseWriter, r *http.Request)
- func (h *ManagedServerBackupHandler) Import(w http.ResponseWriter, r *http.Request)
- func (h *ManagedServerBackupHandler) RestoreDrift(w http.ResponseWriter, r *http.Request)
- func (h *ManagedServerBackupHandler) SetEventBus(bus *events.Bus)
- type ManagedServerDTO
- type ManagedServerDriftEnvelope
- type ManagedServerDriftResponse
- type ManagedServerExportEnvelope
- type ManagedServerHandler
- func (h *ManagedServerHandler) ASC(w http.ResponseWriter, r *http.Request, id string)
- func (h *ManagedServerHandler) AddPeer(w http.ResponseWriter, r *http.Request, id string)
- func (h *ManagedServerHandler) Collection(w http.ResponseWriter, r *http.Request)
- func (h *ManagedServerHandler) Create(w http.ResponseWriter, r *http.Request)
- func (h *ManagedServerHandler) Delete(w http.ResponseWriter, r *http.Request, id string)
- func (h *ManagedServerHandler) DeletePeer(w http.ResponseWriter, r *http.Request, id, pubkey string)
- func (h *ManagedServerHandler) Get(w http.ResponseWriter, r *http.Request, id string)
- func (h *ManagedServerHandler) GetPolicies(w http.ResponseWriter, r *http.Request)
- func (h *ManagedServerHandler) LANSegments(w http.ResponseWriter, r *http.Request, id string)
- func (h *ManagedServerHandler) List(w http.ResponseWriter, r *http.Request)
- func (h *ManagedServerHandler) ListLANSegments(w http.ResponseWriter, r *http.Request)
- func (h *ManagedServerHandler) NAT(w http.ResponseWriter, r *http.Request, id string)
- func (h *ManagedServerHandler) PeerConf(w http.ResponseWriter, r *http.Request, id, pubkey string)
- func (h *ManagedServerHandler) Restart(w http.ResponseWriter, r *http.Request, id string)
- func (h *ManagedServerHandler) SetEnabled(w http.ResponseWriter, r *http.Request, id string)
- func (h *ManagedServerHandler) SetPolicy(w http.ResponseWriter, r *http.Request, id string)
- func (h *ManagedServerHandler) SetServersHandler(s *ServersHandler)
- func (h *ManagedServerHandler) Stats(w http.ResponseWriter, r *http.Request, id string)
- func (h *ManagedServerHandler) Subtree(w http.ResponseWriter, r *http.Request)
- func (h *ManagedServerHandler) SuggestAddress(w http.ResponseWriter, r *http.Request)
- func (h *ManagedServerHandler) TogglePeer(w http.ResponseWriter, r *http.Request, id, pubkey string)
- func (h *ManagedServerHandler) Update(w http.ResponseWriter, r *http.Request, id string)
- func (h *ManagedServerHandler) UpdatePeer(w http.ResponseWriter, r *http.Request, id, pubkey string)
- type ManagedServerImportEnvelope
- type ManagedServerImportRequest
- type ManagedServerResponse
- type ManagedServerRestoreDriftRequest
- type ManagedServerRestoreResponse
- type ManagedServerStatsDTO
- type ManagedServerStatsResponse
- type ManagedServersListResponse
- type MonitoringCellDTO
- type MonitoringHandler
- type MonitoringRefreshService
- type MonitoringSnapshotData
- type MonitoringSnapshotResponse
- type MonitoringTargetDTO
- type MonitoringTunnelDTO
- type MoveRejectedToInfoRequest
- type NDMSHandler
- type NativePingCheckStatusDTO
- type NativePingCheckStatusResponse
- type OkData
- type OkResponse
- type OversizedTagDTO
- type OversizedTagsData
- type OversizedTagsResponse
- type PeerConfData
- type PeerConfResponse
- type PermitInterfaceRequest
- type PingCheckDefaultsDTO
- type PingCheckHandler
- func (h *PingCheckHandler) CheckNow(w http.ResponseWriter, r *http.Request)
- func (h *PingCheckHandler) ClearLogs(w http.ResponseWriter, r *http.Request)
- func (h *PingCheckHandler) ConfigureTunnelPingCheck(w http.ResponseWriter, r *http.Request)
- func (h *PingCheckHandler) GetLogs(w http.ResponseWriter, r *http.Request)
- func (h *PingCheckHandler) GetStatus(w http.ResponseWriter, r *http.Request)
- func (h *PingCheckHandler) GetTunnelPingCheckStatus(w http.ResponseWriter, r *http.Request)
- func (h *PingCheckHandler) PublishSnapshot()
- func (h *PingCheckHandler) RemoveTunnelPingCheck(w http.ResponseWriter, r *http.Request)
- func (h *PingCheckHandler) SetEventBus(bus *events.Bus)
- func (h *PingCheckHandler) SetOrchestrator(orch *orchestrator.Orchestrator)
- type PingCheckService
- type PingCheckSettingsDTO
- type PingCheckStatusData
- type PingCheckStatusResponse
- type PingCheckToggleService
- type PingLogEntryDTO
- type PingLogsResponse
- type PoliciesListResponse
- type PolicyDeviceDTO
- type PolicyDevicesListResponse
- type PolicyGlobalInterfaceDTO
- type PolicyInterfacesListResponse
- type PolicyOptionDTO
- type PolicyOrderData
- type PolicyOrderResponse
- type PresetsHandler
- type PresetsListResponse
- type PreviewURLRequest
- type ProxyConfigResponse
- type ProxyInstanceResponse
- type ProxyInstancesResponse
- type ProxyListenChoicesData
- type ProxyListenChoicesResponse
- type ProxyOutboundsResponse
- type ProxyRuntimeResponse
- type RemoveInfoItemRequest
- type RemoveMemberRequest
- type RemoveMemberResponseData
- type ResolveHandler
- type ResolveResponse
- type RestoreMembersRequest
- type RestoreOptionsDTO
- type RestoreOutcomeDTO
- type RouterDetails
- type RouterInterfaceDTO
- type RouterStagingStatusResponse
- type RouterStagingValidationError
- type RouterValidationDTO
- type RouterValidationErrorDTO
- type RoutingHandler
- type RoutingRefreshData
- type RoutingRefreshResponse
- type RoutingTunnelDTO
- type RoutingTunnelsResponse
- type SaveStatusDTO
- type ServerAddPeerRequestDTO
- type ServerConfigResponse
- type ServerSettingsDTO
- type ServerUpdatePeerRequestDTO
- type ServersAllData
- type ServersAllResponse
- type ServersHandler
- func (h *ServersHandler) AddServerPeer(w http.ResponseWriter, r *http.Request, name string)
- func (h *ServersHandler) Config(w http.ResponseWriter, r *http.Request)
- func (h *ServersHandler) DeleteServerPeer(w http.ResponseWriter, r *http.Request, name, pubkey string)
- func (h *ServersHandler) Get(w http.ResponseWriter, r *http.Request)
- func (h *ServersHandler) GetAll(w http.ResponseWriter, r *http.Request)
- func (h *ServersHandler) List(w http.ResponseWriter, r *http.Request)
- func (h *ServersHandler) Mark(w http.ResponseWriter, r *http.Request)
- func (h *ServersHandler) Marked(w http.ResponseWriter, r *http.Request)
- func (h *ServersHandler) PublishServerSnapshot(ctx context.Context)
- func (h *ServersHandler) Restart(w http.ResponseWriter, r *http.Request)
- func (h *ServersHandler) ServerPeerConf(w http.ResponseWriter, r *http.Request, name, pubkey string)
- func (h *ServersHandler) SetCommands(commands *ndmscommand.Commands)
- func (h *ServersHandler) SetEnabled(w http.ResponseWriter, r *http.Request)
- func (h *ServersHandler) SetEndpoint(w http.ResponseWriter, r *http.Request, name string)
- func (h *ServersHandler) SetEventBus(bus *events.Bus)
- func (h *ServersHandler) SetManagedHandler(m *ManagedServerHandler)
- func (h *ServersHandler) SetManagedService(svc *managed.Service)
- func (h *ServersHandler) SetNAT(w http.ResponseWriter, r *http.Request, name string)
- func (h *ServersHandler) SetPolicy(w http.ResponseWriter, r *http.Request, name string)
- func (h *ServersHandler) Subtree(w http.ResponseWriter, r *http.Request)
- func (h *ServersHandler) ToggleServerPeer(w http.ResponseWriter, r *http.Request, name, pubkey string)
- func (h *ServersHandler) UpdateServerPeer(w http.ResponseWriter, r *http.Request, name, pubkey string)
- func (h *ServersHandler) WANIP(w http.ResponseWriter, r *http.Request)
- type SetDescriptionRequest
- type SetInterfaceUpRequest
- type SetLANSegmentsRequest
- type SetNATModeRequest
- type SetPolicyOrderRequest
- type SetServerEndpointRequest
- type SetServerPolicyRequest
- type SetStandaloneRequest
- type SettingsData
- type SettingsHandler
- func (h *SettingsHandler) Get(w http.ResponseWriter, r *http.Request)
- func (h *SettingsHandler) RegenerateApiKey(w http.ResponseWriter, r *http.Request)
- func (h *SettingsHandler) SetApplyLoggingSettings(fn func())
- func (h *SettingsHandler) SetApplySingboxLogSettings(fn func() error)
- func (h *SettingsHandler) SetDownloadService(svc *downloader.Service)
- func (h *SettingsHandler) SetEventBus(bus *events.Bus)
- func (h *SettingsHandler) SetLogsSnapshot(fn func())
- func (h *SettingsHandler) SetMonitoringService(svc MonitoringRefreshService)
- func (h *SettingsHandler) SetPingCheckService(svc PingCheckToggleService)
- func (h *SettingsHandler) SetPingCheckSnapshot(fn func())
- func (h *SettingsHandler) SetTunnelStore(tunnels *storage.AWGTunnelStore)
- func (h *SettingsHandler) Update(w http.ResponseWriter, r *http.Request)
- type SettingsProvider
- type SettingsResponse
- type SignatureCaptureData
- type SignatureCaptureResponse
- type SignatureHandler
- type SignaturePacketsDTO
- type SingboxConfigHandler
- type SingboxConfigPreviewResponse
- type SingboxConnectionsClientsData
- type SingboxConnectionsClientsResponse
- type SingboxConnectionsHandler
- type SingboxControlRequest
- type SingboxDNSGlobalsData
- type SingboxDNSGlobalsResponse
- type SingboxDNSRewriteDTO
- type SingboxDNSRewriteDeleteRequest
- type SingboxDNSRewriteMoveRequest
- type SingboxDNSRewriteUpdateRequest
- type SingboxDNSRewritesListResponse
- type SingboxDNSRuleDTO
- type SingboxDNSRuleDeleteRequest
- type SingboxDNSRuleMoveRequest
- type SingboxDNSRuleUpdateRequest
- type SingboxDNSRulesListResponse
- type SingboxDNSServerDTO
- type SingboxDNSServerDeleteRequest
- type SingboxDNSServerMoveRequest
- type SingboxDNSServerUpdateRequest
- type SingboxDNSServersListResponse
- type SingboxDomainResolverDTO
- type SingboxFakeIPConfigHandler
- func (h *SingboxFakeIPConfigHandler) AddDNSRule(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) AddDNSServer(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) AddOutbound(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) AddRule(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) AddRuleSet(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) DeleteDNSRule(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) DeleteDNSServer(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) DeleteOutbound(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) DeleteRule(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) DeleteRuleSet(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) GetDNSGlobals(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) ListDNSRules(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) ListDNSServers(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) ListOutbounds(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) ListRuleSets(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) ListRules(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) MoveDNSRule(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) MoveDNSServer(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) MoveRule(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) PutDNSGlobals(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) SetRouteFinal(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) UpdateDNSRule(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) UpdateDNSServer(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) UpdateOutbound(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) UpdateRule(w http.ResponseWriter, r *http.Request)
- func (h *SingboxFakeIPConfigHandler) UpdateRuleSet(w http.ResponseWriter, r *http.Request)
- type SingboxHandler
- func (h *SingboxHandler) AddTunnels(w http.ResponseWriter, r *http.Request)
- func (h *SingboxHandler) CheckConnectivity(w http.ResponseWriter, r *http.Request)
- func (h *SingboxHandler) CheckIP(w http.ResponseWriter, r *http.Request)
- func (h *SingboxHandler) Control(w http.ResponseWriter, r *http.Request)
- func (h *SingboxHandler) DelayCheck(w http.ResponseWriter, r *http.Request)
- func (h *SingboxHandler) DeleteTunnel(w http.ResponseWriter, r *http.Request)
- func (h *SingboxHandler) ExportShareLink(w http.ResponseWriter, r *http.Request)
- func (h *SingboxHandler) GetTunnel(w http.ResponseWriter, r *http.Request)
- func (h *SingboxHandler) Install(w http.ResponseWriter, r *http.Request)
- func (h *SingboxHandler) ListTunnels(w http.ResponseWriter, r *http.Request)
- func (h *SingboxHandler) RenameTunnel(w http.ResponseWriter, r *http.Request)
- func (h *SingboxHandler) ServeGETTunnels(w http.ResponseWriter, r *http.Request)
- func (h *SingboxHandler) SetNDMSProxyMigrator(m *singbox.Migrator, settings ndmsProxyToggler)
- func (h *SingboxHandler) SetOutboundRefCheckers(dp tunnelservice.DeviceProxyRefChecker, r tunnelservice.RouterRefChecker)
- func (h *SingboxHandler) SetSettingsStore(settings *storage.SettingsStore)
- func (h *SingboxHandler) SpeedTestStream(w http.ResponseWriter, r *http.Request)
- func (h *SingboxHandler) Status(w http.ResponseWriter, r *http.Request)
- func (h *SingboxHandler) ToggleNDMSProxy(w http.ResponseWriter, r *http.Request)
- func (h *SingboxHandler) Update(w http.ResponseWriter, r *http.Request)
- func (h *SingboxHandler) UpdateTunnel(w http.ResponseWriter, r *http.Request)
- type SingboxPresenceProbe
- type SingboxProxiesHandler
- type SingboxProxiesListResponse
- type SingboxProxiesSelectRequest
- type SingboxProxiesTestRequest
- type SingboxProxiesTestResponse
- type SingboxProxyGroup
- type SingboxProxyMember
- type SingboxRouterApplyPresetRequest
- type SingboxRouterBindDeviceRequest
- type SingboxRouterCreatePolicyRequest
- type SingboxRouterDatRuleSetURLData
- type SingboxRouterDatRuleSetURLResponse
- type SingboxRouterHandler
- func (h *SingboxRouterHandler) AddDNSRule(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) AddDNSServer(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) AddOutbound(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) AddRule(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) AddRuleSet(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) ApplyPreset(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) BindDevice(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) DatRuleSetSRS(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) DatRuleSetURL(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) DeleteDNSRule(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) DeleteDNSServer(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) DeleteOutbound(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) DeleteRule(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) DeleteRuleSet(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) Disable(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) Enable(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) GetDNSGlobals(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) GetSettings(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) GetStaging(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) GetStatus(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) Inspect(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) InspectDNS(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) InspectStream(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) ListBindableInterfaces(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) ListDNSRules(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) ListDNSServers(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) ListIngressEligibleInterfaces(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) ListOutbounds(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) ListPolicyDevices(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) ListPresets(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) ListRuleSets(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) ListRules(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) ListWANInterfaces(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) MoveDNSRule(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) MoveDNSServer(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) MoveRule(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) PoliciesCollection(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) PostStagingApply(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) PostStagingDiscard(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) PutDNSGlobals(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) PutSettings(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) SetOutboundRefCheckers(dp tunnelservice.DeviceProxyRefChecker, r tunnelservice.RouterRefChecker)
- func (h *SingboxRouterHandler) SetRouteFinal(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) SwitchMode(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) UnbindDevice(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) UpdateDNSRule(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) UpdateDNSServer(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) UpdateOutbound(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) UpdateRule(w http.ResponseWriter, r *http.Request)
- func (h *SingboxRouterHandler) UpdateRuleSet(w http.ResponseWriter, r *http.Request)
- type SingboxRouterInspectDNSData
- type SingboxRouterInspectDNSMatchDTO
- type SingboxRouterInspectDNSRequest
- type SingboxRouterInspectDNSResponse
- type SingboxRouterInspectData
- type SingboxRouterInspectMatchDTO
- type SingboxRouterInspectProgressDTO
- type SingboxRouterInspectRequest
- type SingboxRouterInspectResponse
- type SingboxRouterInspectStreamEventDTO
- type SingboxRouterIssueDTO
- type SingboxRouterModeRequest
- type SingboxRouterOutboundDTO
- type SingboxRouterOutboundDeleteRequest
- type SingboxRouterOutboundUpdateRequest
- type SingboxRouterOutboundsListResponse
- type SingboxRouterPoliciesListResponse
- type SingboxRouterPolicyDeviceDTO
- type SingboxRouterPolicyDevicesListResponse
- type SingboxRouterPolicyInfoDTO
- type SingboxRouterPolicyResponse
- type SingboxRouterPresetDTO
- type SingboxRouterPresetRuleLinkDTO
- type SingboxRouterPresetRuleRefDTO
- type SingboxRouterPresetsListResponse
- type SingboxRouterRouteFinalRequest
- type SingboxRouterRuleDTO
- type SingboxRouterRuleDeleteRequest
- type SingboxRouterRuleMoveRequest
- type SingboxRouterRuleSetDTO
- type SingboxRouterRuleSetDeleteRequest
- type SingboxRouterRuleSetUpdateRequest
- type SingboxRouterRuleSetsListResponse
- type SingboxRouterRuleUpdateRequest
- type SingboxRouterRulesListResponse
- type SingboxRouterSettingsData
- type SingboxRouterSettingsResponse
- type SingboxRouterStatusData
- type SingboxRouterStatusResponse
- type SingboxRouterTransitionData
- type SingboxRouterTransitionStepDTO
- type SingboxRouterUnbindDeviceRequest
- type SingboxRouterWANInterfaceDTO
- type SingboxRouterWANInterfacesListResponse
- type SingboxStatusData
- type SingboxStatusResponse
- type SingboxTunnelConnectivity
- type SingboxTunnelDTO
- type SingboxTunnelsResponse
- type SpeedTestInfoData
- type SpeedTestInfoResponse
- type SpeedTestResultData
- type SpeedTestResultResponse
- type SpeedTestServerDTO
- type StaticRouteDTO
- type StaticRouteHandler
- func (h *StaticRouteHandler) Create(w http.ResponseWriter, r *http.Request)
- func (h *StaticRouteHandler) Delete(w http.ResponseWriter, r *http.Request)
- func (h *StaticRouteHandler) Import(w http.ResponseWriter, r *http.Request)
- func (h *StaticRouteHandler) List(w http.ResponseWriter, r *http.Request)
- func (h *StaticRouteHandler) SetEnabled(w http.ResponseWriter, r *http.Request)
- func (h *StaticRouteHandler) SetEventBus(bus *events.Bus)
- func (h *StaticRouteHandler) Update(w http.ResponseWriter, r *http.Request)
- type StaticRouteService
- type StaticRoutesListResponse
- type SubgroupsData
- type SubgroupsResponseEnvelope
- type SubscriptionDTO
- type SubscriptionHandler
- func (h *SubscriptionHandler) ActiveMember(w http.ResponseWriter, r *http.Request)
- func (h *SubscriptionHandler) ActiveNow(w http.ResponseWriter, r *http.Request)
- func (h *SubscriptionHandler) AddMember(w http.ResponseWriter, r *http.Request)
- func (h *SubscriptionHandler) Create(w http.ResponseWriter, r *http.Request)
- func (h *SubscriptionHandler) Delete(w http.ResponseWriter, r *http.Request)
- func (h *SubscriptionHandler) ExcludeMembers(w http.ResponseWriter, r *http.Request)
- func (h *SubscriptionHandler) Get(w http.ResponseWriter, r *http.Request)
- func (h *SubscriptionHandler) GetStream(w http.ResponseWriter, r *http.Request)
- func (h *SubscriptionHandler) InfoRemove(w http.ResponseWriter, r *http.Request)
- func (h *SubscriptionHandler) List(w http.ResponseWriter, r *http.Request)
- func (h *SubscriptionHandler) OrphansDelete(w http.ResponseWriter, r *http.Request)
- func (h *SubscriptionHandler) PreviewURL(w http.ResponseWriter, r *http.Request)
- func (h *SubscriptionHandler) Refresh(w http.ResponseWriter, r *http.Request)
- func (h *SubscriptionHandler) RejectedToInfo(w http.ResponseWriter, r *http.Request)
- func (h *SubscriptionHandler) RemoveMember(w http.ResponseWriter, r *http.Request)
- func (h *SubscriptionHandler) RestoreMembers(w http.ResponseWriter, r *http.Request)
- func (h *SubscriptionHandler) SetNDMSProxyToggler(s ndmsProxyToggler)
- func (h *SubscriptionHandler) SetOutboundRefCheckers(dp tunnelservice.DeviceProxyRefChecker, r tunnelservice.RouterRefChecker)
- func (h *SubscriptionHandler) Update(w http.ResponseWriter, r *http.Request)
- type SubscriptionHeader
- type SubscriptionInfoItemDTO
- type SubscriptionListResponse
- type SubscriptionMemberDTO
- type SubscriptionMetaDTO
- type SubscriptionRejectedDTO
- type SubscriptionResponse
- type SubscriptionStreamDoneDTO
- type SubscriptionStreamMemberDTO
- type SubscriptionURLTestDTO
- type SuggestAddressData
- type SuggestAddressResponse
- type SystemHandler
- func (h *SystemHandler) AllInterfaces(w http.ResponseWriter, r *http.Request)
- func (h *SystemHandler) BuildSystemInfo() map[string]interface{}
- func (h *SystemHandler) HydraRouteControl(w http.ResponseWriter, r *http.Request)
- func (h *SystemHandler) HydraRouteStatus(w http.ResponseWriter, r *http.Request)
- func (h *SystemHandler) Info(w http.ResponseWriter, r *http.Request)
- func (h *SystemHandler) RestartDaemon(w http.ResponseWriter, r *http.Request)
- func (h *SystemHandler) SetActiveBackend(b backend.Backend)
- func (h *SystemHandler) SetBootStatusFunc(fn func() bool)
- func (h *SystemHandler) SetEventBus(bus *events.Bus)
- func (h *SystemHandler) SetHydraRoute(svc *hydraroute.Service)
- func (h *SystemHandler) SetKmodLoader(l KmodLoader)
- func (h *SystemHandler) SetNDMSQueries(q *ndmsquery.Queries)
- func (h *SystemHandler) SetPingCheckService(svc PingCheckService)
- func (h *SystemHandler) SetRestartFunc(fn func())
- func (h *SystemHandler) SetSettingsStore(sp SettingsProvider)
- func (h *SystemHandler) SetSettingsWriter(sw *storage.SettingsStore)
- func (h *SystemHandler) SetSingboxOperator(op *singbox.Operator)
- func (h *SystemHandler) SetSlowRequestThresholdMs(ms int)
- func (h *SystemHandler) SetTunnelService(svc TunnelService)
- func (h *SystemHandler) WANInterfaces(w http.ResponseWriter, r *http.Request)
- type SystemInfoBackendAvailability
- type SystemInfoData
- type SystemInfoResponse
- type SystemInfoSingbox
- type SystemTunnelDTO
- type SystemTunnelPeerDTO
- type SystemTunnelsHandler
- func (h *SystemTunnelsHandler) ASC(w http.ResponseWriter, r *http.Request)
- func (h *SystemTunnelsHandler) CheckConnectivity(w http.ResponseWriter, r *http.Request)
- func (h *SystemTunnelsHandler) CheckIP(w http.ResponseWriter, r *http.Request)
- func (h *SystemTunnelsHandler) Get(w http.ResponseWriter, r *http.Request)
- func (h *SystemTunnelsHandler) List(w http.ResponseWriter, r *http.Request)
- func (h *SystemTunnelsHandler) SpeedTestStream(w http.ResponseWriter, r *http.Request)
- type SystemTunnelsResponse
- type TakeGeoFileControlRequest
- type TerminalHandler
- func (h *TerminalHandler) Install(w http.ResponseWriter, r *http.Request)
- func (h *TerminalHandler) Start(w http.ResponseWriter, r *http.Request)
- func (h *TerminalHandler) Status(w http.ResponseWriter, r *http.Request)
- func (h *TerminalHandler) Stop(w http.ResponseWriter, r *http.Request)
- func (h *TerminalHandler) WebSocket(w http.ResponseWriter, r *http.Request)
- type TerminalStartData
- type TerminalStartResponse
- type TerminalStatusResponse
- type TestingHandler
- func (h *TestingHandler) CheckConnectivity(w http.ResponseWriter, r *http.Request)
- func (h *TestingHandler) CheckIP(w http.ResponseWriter, r *http.Request)
- func (h *TestingHandler) IPCheckServices(w http.ResponseWriter, r *http.Request)
- func (h *TestingHandler) SpeedTest(w http.ResponseWriter, r *http.Request)
- func (h *TestingHandler) SpeedTestServers(w http.ResponseWriter, r *http.Request)
- func (h *TestingHandler) SpeedTestStream(w http.ResponseWriter, r *http.Request)
- type ToggleNDMSProxyRequest
- type TunnelConnectionInfoDTO
- type TunnelControlData
- type TunnelControlResponse
- type TunnelDeleteResponse
- type TunnelDeleteResultData
- type TunnelDetailResponse
- type TunnelHookInvalidator
- type TunnelListItemDTO
- type TunnelListResponse
- type TunnelPingCheckStatus
- type TunnelPingStatusDTO
- type TunnelReferencedDetails
- type TunnelReferencedResponse
- type TunnelService
- type TunnelStateInfoDTO
- type TunnelTrafficData
- type TunnelTrafficPoint
- type TunnelTrafficResponse
- type TunnelTrafficStats
- type TunnelsAllResponse
- type TunnelsAllSnapshotData
- type TunnelsHandler
- func (h *TunnelsHandler) Create(w http.ResponseWriter, r *http.Request)
- func (h *TunnelsHandler) Delete(w http.ResponseWriter, r *http.Request)
- func (h *TunnelsHandler) Export(w http.ResponseWriter, r *http.Request)
- func (h *TunnelsHandler) ExportAll(w http.ResponseWriter, r *http.Request)
- func (h *TunnelsHandler) Get(w http.ResponseWriter, r *http.Request)
- func (h *TunnelsHandler) GetAll(w http.ResponseWriter, r *http.Request)
- func (h *TunnelsHandler) List(w http.ResponseWriter, r *http.Request)
- func (h *TunnelsHandler) PublishTunnelList(ctx context.Context)
- func (h *TunnelsHandler) ReplaceConf(w http.ResponseWriter, r *http.Request)
- func (h *TunnelsHandler) SetCatalog(cat routing.Catalog)
- func (h *TunnelsHandler) SetEventBus(bus *events.Bus)
- func (h *TunnelsHandler) SetOrchestrator(orch *orchestrator.Orchestrator)
- func (h *TunnelsHandler) SetPingCheckService(svc PingCheckService)
- func (h *TunnelsHandler) SetPingCheckSnapshot(fn func())
- func (h *TunnelsHandler) SetSelfCreateGate(g tunnel.SelfCreateGater)
- func (h *TunnelsHandler) SetSettingsStore(store *storage.SettingsStore)
- func (h *TunnelsHandler) SetTrafficHistory(th *traffic.History)
- func (h *TunnelsHandler) SetTunnelsSnapshotBuilder(fn func(ctx context.Context) map[string]interface{})
- func (h *TunnelsHandler) Traffic(w http.ResponseWriter, r *http.Request)
- func (h *TunnelsHandler) Update(w http.ResponseWriter, r *http.Request)
- type TunnelsSnapshotBuilder
- func (b *TunnelsSnapshotBuilder) Build(ctx context.Context) map[string]interface{}
- func (b *TunnelsSnapshotBuilder) SetExternalHandler(h *ExternalTunnelsHandler)
- func (b *TunnelsSnapshotBuilder) SetSystemTunnelsHandler(h *SystemTunnelsHandler)
- func (b *TunnelsSnapshotBuilder) SetTunnelsHandler(h *TunnelsHandler)
- type UpdateApplyData
- type UpdateApplyResponse
- type UpdateCheckResponse
- type UpdateGeoFileRequest
- type UpdateHandler
- type UpdateInfoData
- type UpdatePeerRequestDTO
- type UpdateServerRequestDTO
- type UpdateSettingsDTO
- type UpdateSubscriptionRequest
- type WANHandler
- type WANIPData
- type WANIPResponse
- type WANInterfaceDTO
- type WANInterfaceStatusDTO
- type WANInterfaceStatusItemDTO
- type WANInterfacesResponse
- type WANStatusEnvelope
- type WANStatusResponse
- type WireguardServerConfigDTO
- type WireguardServerConfigPeerDTO
- type WireguardServerDTO
- type WireguardServerPeerDTO
Constants ¶
const ( ResourceTunnels = "tunnels" ResourceServers = "servers" ResourceSingboxStatus = "singbox.status" ResourceSingboxTunnels = "singbox.tunnels" ResourceSysInfo = "sysInfo" ResourcePingcheck = "pingcheck" ResourceSaveStatus = "saveStatus" ResourceSettings = "settings" ResourceRoutingDnsRoutes = "routing.dnsRoutes" ResourceRoutingStaticRoutes = "routing.staticRoutes" ResourceRoutingAccessPolicies = "routing.accessPolicies" ResourceRoutingPolicyDevices = "routing.policyDevices" ResourceRoutingPolicyInterfaces = "routing.policyInterfaces" ResourceRoutingClientRoutes = "routing.clientRoutes" ResourceRoutingTunnels = "routing.tunnels" ResourceRoutingHydrarouteStatus = "routing.hydrarouteStatus" ResourceDeviceProxy = "deviceproxy" ResourceDeviceProxyConfig = "deviceproxy.config" ResourceDeviceProxyRuntime = "deviceproxy.runtime" )
Resource keys — closed set. Keep in sync with frontend/src/lib/stores/storeRegistry.ts.
Variables ¶
This section is empty.
Functions ¶
func BuildTunnelResponse ¶
func BuildTunnelResponse(r *http.Request, svc TunnelService, store *storage.AWGTunnelStore, id string, quiescentUntil time.Time) (map[string]interface{}, error)
BuildTunnelResponse builds a consistent tunnel response with stored data. Exported so Import and External handlers can reuse the same response format. quiescentUntil is the orchestrator bring-up window (zero when unknown) so the "state" string carries the same boot-pending overlay the list shows.
func ServeOS4EmptyAccessPolicies ¶
func ServeOS4EmptyAccessPolicies(w http.ResponseWriter, r *http.Request)
ServeOS4EmptyAccessPolicies returns an empty access-policies list on OS4 (no NDMS policies API).
@Summary OS4 access policies stub
@Description Always {"data":[]}. Real data on KeeneticOS 5 only.
@Tags routing
@Produce json
@Security CookieAuth
@Success 200 {object} AccessPoliciesListResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /routing/access-policies [get]
func ServeOS4EmptyPolicyInterfaces ¶
func ServeOS4EmptyPolicyInterfaces(w http.ResponseWriter, r *http.Request)
ServeOS4EmptyPolicyInterfaces returns an empty policy-interfaces list on OS4.
@Summary OS4 policy interfaces stub
@Description Always {"data":[]}. Real data on KeeneticOS 5 only.
@Tags routing
@Produce json
@Security CookieAuth
@Success 200 {object} PolicyInterfacesListResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /routing/policy-interfaces [get]
func WriteTunnelReferenced ¶
func WriteTunnelReferenced(w http.ResponseWriter, err tunnelservice.ErrTunnelReferenced)
WriteTunnelReferenced responds with HTTP 409 and the structured payload the frontend uses for TunnelReferencedModal.
Types ¶
type APIEnvelope ¶
type APIEnvelope struct {
Success bool `json:"success" example:"true"`
Data any `json:"data,omitempty" swaggertype:"object"`
Message string `json:"message,omitempty" example:"ok"`
}
APIEnvelope describes the common successful API response shape. Most handlers return: { success: true, data: ... }.
type APIErrorEnvelope ¶
type APIErrorEnvelope struct {
Error bool `json:"error" example:"true"`
Message string `json:"message" example:"invalid request"`
Code string `json:"code" example:"BAD_REQUEST"`
}
APIErrorEnvelope describes the common error response shape. Most handlers return: { error: true, message: "...", code: "..." }.
type ASCParamsResponse ¶
type ASCParamsResponse struct {
Success bool `json:"success" example:"true"`
Data map[string]interface{} `json:"data" swaggertype:"object"`
}
ASCParamsResponse is the envelope for GET /managed-servers/{id}/asc. The data field is the AWG signature/obfuscation params object — its shape depends on the active signature preset, so it is intentionally an opaque object in OpenAPI.
type AWGInterfaceDTO ¶
type AWGInterfaceDTO struct {
PrivateKey string `json:"privateKey" example:"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="`
Address string `json:"address" example:"10.0.0.2/32"`
MTU int `json:"mtu" example:"1420"`
DNS string `json:"dns,omitempty" example:"8.8.8.8"`
Jc int `json:"jc" example:"4"`
Jmin int `json:"jmin" example:"40"`
Jmax int `json:"jmax" example:"70"`
S1 int `json:"s1" example:"0"`
S2 int `json:"s2" example:"0"`
S3 int `json:"s3" example:"0"`
S4 int `json:"s4" example:"0"`
H1 string `json:"h1" example:"1"`
H2 string `json:"h2" example:"2"`
H3 string `json:"h3" example:"3"`
H4 string `json:"h4" example:"4"`
}
AWGInterfaceDTO mirrors frontend AWGInterface.
type AWGOutboundTagDTO ¶
type AWGOutboundTagDTO struct {
Tag string `json:"tag" example:"awg-vpn0"`
Label string `json:"label" example:"My VPN"`
Kind string `json:"kind" example:"managed"`
Iface string `json:"iface" example:"nwg0"`
}
AWGOutboundTagDTO mirrors awgoutbounds.TagInfo for OpenAPI exposure.
type AWGOutboundTagsResponse ¶
type AWGOutboundTagsResponse struct {
Success bool `json:"success" example:"true"`
Data []AWGOutboundTagDTO `json:"data"`
}
AWGOutboundTagsResponse is the envelope shape for /singbox/awg-outbounds/tags.
type AWGOutboundsHandler ¶
type AWGOutboundsHandler struct {
// contains filtered or unexported fields
}
AWGOutboundsHandler exposes the catalog of AWG-direct outbound tags for the frontend (singbox-router rule editor outbound dropdown).
func NewAWGOutboundsHandler ¶
func NewAWGOutboundsHandler(svc AWGOutboundsService) *AWGOutboundsHandler
func (*AWGOutboundsHandler) ServeHTTP ¶
func (h *AWGOutboundsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP returns the catalog of AWG-direct outbound tags.
@Summary List AWG outbound tags
@Description Returns the catalog of AWG-direct outbound tags currently exposed to sing-box (one per managed/system AWG tunnel). Used by the singbox-router rule editor outbound dropdown.
@Tags singbox
@Produce json
@Security CookieAuth
@Success 200 {object} AWGOutboundTagsResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/awg-outbounds/tags [get]
type AWGOutboundsService ¶
type AWGOutboundsService interface {
ListTags(ctx context.Context) ([]awgoutbounds.TagInfo, error)
}
AWGOutboundsService is the narrow contract this handler needs. Implemented by awgoutbounds.Service.
type AWGPeerDTO ¶
type AWGPeerDTO struct {
PublicKey string `json:"publicKey" example:"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="`
Endpoint string `json:"endpoint" example:"vpn.example.com:51820"`
AllowedIPs []string `json:"allowedIPs" example:"0.0.0.0/0"`
PersistentKeepalive int `json:"persistentKeepalive,omitempty" example:"25"`
}
AWGPeerDTO mirrors frontend AWGPeer.
type AWGTunnelDTO ¶
type AWGTunnelDTO struct {
ID string `json:"id" example:"tun_abc123"`
Name string `json:"name" example:"My VPN"`
Type string `json:"type" example:"awg" enums:"awg,wg"`
Enabled bool `json:"enabled" example:"true"`
DefaultRoute bool `json:"defaultRoute" example:"false"`
InterfaceName string `json:"interfaceName,omitempty" example:"nwg0"`
State string `json:"state,omitempty" example:"connected"`
Backend string `json:"backend,omitempty" example:"nativewg"`
Interface AWGInterfaceDTO `json:"interface"`
Peer AWGPeerDTO `json:"peer"`
StateInfo *TunnelStateInfoDTO `json:"stateInfo,omitempty"`
}
AWGTunnelDTO mirrors frontend AWGTunnel.
type AccessPoliciesListResponse ¶
type AccessPoliciesListResponse struct {
Success bool `json:"success" example:"true"`
Data []AccessPolicyDTO `json:"data"`
}
AccessPoliciesListResponse is the envelope for GET /access-policies.
type AccessPolicyDTO ¶
type AccessPolicyDTO struct {
Name string `json:"name" example:"default"`
Description string `json:"description" example:"Default policy"`
Standalone bool `json:"standalone" example:"false"`
Interfaces []AccessPolicyInterfaceDTO `json:"interfaces"`
DeviceCount int `json:"deviceCount" example:"5"`
IsStandard bool `json:"isStandard" example:"true"`
}
AccessPolicyDTO mirrors frontend AccessPolicy.
type AccessPolicyHandler ¶
type AccessPolicyHandler struct {
// contains filtered or unexported fields
}
AccessPolicyHandler handles access policy CRUD and device assignment operations.
func NewAccessPolicyHandler ¶
func NewAccessPolicyHandler(svc accesspolicy.Service) *AccessPolicyHandler
NewAccessPolicyHandler creates a new access policy handler.
func (*AccessPolicyHandler) AssignDevice ¶
func (h *AccessPolicyHandler) AssignDevice(w http.ResponseWriter, r *http.Request)
AssignDevice handles device assignment to policies. POST /api/access-policies/assign — assign device Body: {"mac":"AA:BB:CC:DD:EE:FF","policy":"Policy0"} DELETE /api/access-policies/assign?mac=AA:BB:CC:DD:EE:FF — unassign device
func (*AccessPolicyHandler) Create ¶
func (h *AccessPolicyHandler) Create(w http.ResponseWriter, r *http.Request)
Create creates a new access policy. POST /api/access-policies/create Body: {"description":"..."}
@Summary Create access policy
@Tags access-policy
@Accept json
@Produce json
@Security CookieAuth
@Param body body CreateAccessPolicyRequest true "Policy description"
@Success 200 {object} AccessPolicyResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /access-policies/create [post]
func (*AccessPolicyHandler) Delete ¶
func (h *AccessPolicyHandler) Delete(w http.ResponseWriter, r *http.Request)
Delete removes an access policy. DELETE /api/access-policies/delete?name=Policy0
@Summary Delete access policy
@Description Removes the named access policy. Bound LAN devices revert to the default policy.
@Tags access-policy
@Produce json
@Security CookieAuth
@Param name query string true "Policy name (e.g. Policy0)"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /access-policies/delete [delete]
func (*AccessPolicyHandler) List ¶
func (h *AccessPolicyHandler) List(w http.ResponseWriter, r *http.Request)
List returns all access policies. GET /api/access-policies
@Summary List access policies
@Description KeeneticOS 5 only when route is registered.
@Tags access-policy
@Produce json
@Security CookieAuth
@Param refresh query string false "Pass 'true' to bypass NDMS cache"
@Success 200 {object} AccessPoliciesListResponse
@Failure 500 {object} APIErrorEnvelope
@Router /access-policies [get]
func (*AccessPolicyHandler) ListDevices ¶
func (h *AccessPolicyHandler) ListDevices(w http.ResponseWriter, r *http.Request)
ListDevices returns all LAN devices with their policy assignments. GET /api/access-policies/devices
@Summary List policy devices
@Tags access-policy
@Produce json
@Security CookieAuth
@Param refresh query string false "Pass 'true' to bypass NDMS cache"
@Success 200 {object} PolicyDevicesListResponse
@Failure 500 {object} APIErrorEnvelope
@Router /access-policies/devices [get]
@Router /routing/policy-devices [get]
func (*AccessPolicyHandler) ListGlobalInterfaces ¶
func (h *AccessPolicyHandler) ListGlobalInterfaces(w http.ResponseWriter, r *http.Request)
ListGlobalInterfaces returns all router interfaces available for policy routing. GET /api/access-policies/interfaces
@Summary List global policy interfaces
@Tags access-policy
@Produce json
@Security CookieAuth
@Success 200 {object} PolicyInterfacesListResponse
@Failure 500 {object} APIErrorEnvelope
@Router /access-policies/interfaces [get]
func (*AccessPolicyHandler) PermitInterface ¶
func (h *AccessPolicyHandler) PermitInterface(w http.ResponseWriter, r *http.Request)
PermitInterface handles permit/deny operations for policy interfaces. POST /api/access-policies/permit — add interface DELETE /api/access-policies/permit?name=...&interface=... — remove interface
func (*AccessPolicyHandler) SetDescription ¶
func (h *AccessPolicyHandler) SetDescription(w http.ResponseWriter, r *http.Request)
SetDescription updates the description of an access policy. POST /api/access-policies/description Body: {"name":"Policy0","description":"..."}
@Summary Set access policy description
@Tags access-policy
@Accept json
@Produce json
@Security CookieAuth
@Param body body SetDescriptionRequest true "Policy name + new description"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /access-policies/description [post]
func (*AccessPolicyHandler) SetEventBus ¶
func (h *AccessPolicyHandler) SetEventBus(bus *events.Bus)
SetEventBus sets the event bus for SSE publishing.
func (*AccessPolicyHandler) SetInterfaceUp ¶
func (h *AccessPolicyHandler) SetInterfaceUp(w http.ResponseWriter, r *http.Request)
SetInterfaceUp brings an interface up or down. POST /api/access-policies/interface-up Body: {"name":"Wireguard0","up":true}
@Summary Set interface admin up
@Tags access-policy
@Accept json
@Produce json
@Security CookieAuth
@Param body body SetInterfaceUpRequest true "Interface name + admin up flag"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /access-policies/interface-up [post]
func (*AccessPolicyHandler) SetStandalone ¶
func (h *AccessPolicyHandler) SetStandalone(w http.ResponseWriter, r *http.Request)
SetStandalone enables or disables standalone mode on an access policy. POST /api/access-policies/standalone Body: {"name":"Policy0","enabled":true}
@Summary Set access policy standalone mode
@Tags access-policy
@Accept json
@Produce json
@Security CookieAuth
@Param body body SetStandaloneRequest true "Policy name + enabled flag"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /access-policies/standalone [post]
type AccessPolicyInterfaceDTO ¶
type AccessPolicyInterfaceDTO struct {
Name string `json:"name" example:"nwg0"`
Label string `json:"label,omitempty" example:"My VPN"`
Order int `json:"order" example:"1"`
Denied bool `json:"denied,omitempty" example:"false"`
}
AccessPolicyInterfaceDTO mirrors frontend AccessPolicyInterface.
type AccessPolicyResponse ¶
type AccessPolicyResponse struct {
Success bool `json:"success" example:"true"`
Data AccessPolicyDTO `json:"data"`
}
AccessPolicyResponse is the envelope for endpoints that return a single access policy (e.g. POST /access-policies/create).
type ActiveMemberRequest ¶
type ActiveMemberRequest struct {
MemberTag string `json:"memberTag" example:"sub-demo-001"`
}
ActiveMemberRequest is the body for POST /api/singbox/subscriptions/active-member.
type ActiveNowResponse ¶
type ActiveNowResponse struct {
Now string `json:"now" example:"sub-abc-aaaa"`
}
ActiveNowResponse is the payload for GET /api/singbox/subscriptions/active-now. Surface only the live "now" pointer from Clash for urltest mode UI.
type AddGeoFileRequest ¶
type AddGeoFileRequest struct {
Type string `json:"type" example:"geosite"`
URL string `json:"url" example:"https://cdn.example.com/geosite.db"`
Route *DownloadRouteDTO `json:"route,omitempty"`
}
AddGeoFileRequest is the body for POST /hydraroute/geo-files/add.
type AddMemberRequest ¶
type AddMemberRequest struct {
}
AddMemberRequest is the body for POST /api/singbox/subscriptions/members/add. Inline subscriptions only — manual CRUD is rejected on URL-backed subscriptions (the URL refresh diff owns the truth there).
type AddPeerRequestDTO ¶
type AddPeerRequestDTO struct {
Description string `json:"description" example:"My Phone"`
TunnelIP string `json:"tunnelIP" example:"10.10.0.2/32"`
DNS string `json:"dns,omitempty" example:"8.8.8.8"`
}
AddPeerRequestDTO is the swagger-visible body for POST /managed-servers/{id}/peers.
type AdoptRequest ¶
AdoptRequest is the request body for adopting an external tunnel.
type AllInterfacesResponse ¶
type AllInterfacesResponse struct {
Success bool `json:"success" example:"true"`
Data []RouterInterfaceDTO `json:"data"`
}
AllInterfacesResponse is the envelope for GET /system/all-interfaces.
type AmneziaCPHandler ¶
type AmneziaCPHandler struct {
// contains filtered or unexported fields
}
AmneziaCPHandler proxies Amnezia Premium customer portal API so the SPA can load country lists and configs without browser CORS issues.
func NewAmneziaCPHandler ¶
func NewAmneziaCPHandler(appLogger logging.AppLogger) *AmneziaCPHandler
func (*AmneziaCPHandler) AccountInfo ¶
func (h *AmneziaCPHandler) AccountInfo(w http.ResponseWriter, r *http.Request)
AccountInfo returns subscription metadata including available_countries (proxied JSON.data).
@Summary Get Amnezia Premium account info
@Tags amnezia-premium
@Accept json
@Produce json
@Security CookieAuth
@Param body body AmneziaPremiumAccountInfoRequest true "Portal session id returned by login"
@Success 200 {object} AmneziaPremiumAccountInfoResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /amnezia-premium/account-info [post]
func (*AmneziaCPHandler) DownloadConfig ¶
func (h *AmneziaCPHandler) DownloadConfig(w http.ResponseWriter, r *http.Request)
DownloadConfig fetches AWG/WG client config text for a country code.
@Summary Download Amnezia Premium config
@Tags amnezia-premium
@Accept json
@Produce json
@Security CookieAuth
@Param body body AmneziaPremiumDownloadConfigRequest true "Portal session id and country code"
@Success 200 {object} AmneziaPremiumDownloadConfigResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /amnezia-premium/download-config [post]
func (*AmneziaCPHandler) Login ¶
func (h *AmneziaCPHandler) Login(w http.ResponseWriter, r *http.Request)
Login exchanges vpnKey for a portal session JWT (v_sid).
@Summary Login to Amnezia Premium portal
@Tags amnezia-premium
@Accept json
@Produce json
@Security CookieAuth
@Param body body AmneziaPremiumLoginRequest true "Premium vpn:// key"
@Success 200 {object} AmneziaPremiumLoginResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 422 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /amnezia-premium/login [post]
func (*AmneziaCPHandler) SetDownloader ¶
func (h *AmneziaCPHandler) SetDownloader(svc *downloader.Service)
type AmneziaPremiumAccountInfoRequest ¶
type AmneziaPremiumAccountInfoRequest struct {
Sid string `json:"sid" example:"v_sid_cookie_value"`
}
AmneziaPremiumAccountInfoRequest is the body for POST /amnezia-premium/account-info.
type AmneziaPremiumAccountInfoResponse ¶
type AmneziaPremiumAccountInfoResponse struct {
Success bool `json:"success" example:"true"`
Data map[string]any `json:"data" swaggertype:"object"`
}
AmneziaPremiumAccountInfoResponse is a typed envelope around the proxied CP account payload.
type AmneziaPremiumDownloadConfigData ¶
type AmneziaPremiumDownloadConfigData struct {
Config string `json:"config" example:"[Interface]\nPrivateKey = ..."`
}
AmneziaPremiumDownloadConfigData contains the downloaded WireGuard/AmneziaWG config.
type AmneziaPremiumDownloadConfigRequest ¶
type AmneziaPremiumDownloadConfigRequest struct {
Sid string `json:"sid" example:"v_sid_cookie_value"`
CountryCode string `json:"countryCode" example:"nl"`
}
AmneziaPremiumDownloadConfigRequest is the body for POST /amnezia-premium/download-config.
type AmneziaPremiumDownloadConfigResponse ¶
type AmneziaPremiumDownloadConfigResponse struct {
Success bool `json:"success" example:"true"`
Data AmneziaPremiumDownloadConfigData `json:"data"`
}
AmneziaPremiumDownloadConfigResponse is the typed success envelope for config downloads.
type AmneziaPremiumLoginData ¶
type AmneziaPremiumLoginData struct {
Sid string `json:"sid" example:"v_sid_cookie_value"`
}
AmneziaPremiumLoginData is returned after a successful portal login.
type AmneziaPremiumLoginRequest ¶
type AmneziaPremiumLoginRequest struct {
VPNKey string `json:"vpnKey" example:"vpn://..."`
VPNKeySnake string `json:"vpn_key,omitempty" example:"vpn://..."`
Remember *bool `json:"remember,omitempty" example:"true"`
}
AmneziaPremiumLoginRequest is the body for POST /amnezia-premium/login.
type AmneziaPremiumLoginResponse ¶
type AmneziaPremiumLoginResponse struct {
Success bool `json:"success" example:"true"`
Data AmneziaPremiumLoginData `json:"data"`
}
AmneziaPremiumLoginResponse is the typed success envelope for Premium login.
type AssignDeviceRequest ¶
type AssignDeviceRequest struct {
MAC string `json:"mac" example:"aa:bb:cc:dd:ee:ff"`
Policy string `json:"policy" example:"Policy0"`
}
AssignDeviceRequest is the body for POST /access-policies/assign.
type AuthHandler ¶
type AuthHandler struct {
// contains filtered or unexported fields
}
AuthHandler handles authentication endpoints.
func NewAuthHandler ¶
func NewAuthHandler(keenetic *auth.KeeneticClient, sessions *auth.SessionStore, settings *storage.SettingsStore, appLogger logging.AppLogger) *AuthHandler
NewAuthHandler creates a new auth handler.
func (*AuthHandler) Login ¶
func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request)
Login authenticates against the router and sets the session cookie.
@Summary Login
@Description Authenticates with Keenetic credentials; sets HttpOnly session cookie awg_session.
@Tags auth
@Accept json
@Produce json
@Param body body LoginRequest true "Router login and password"
@Success 200 {object} LoginResponseRaw
@Failure 400 {object} APIErrorEnvelope
@Failure 401 {object} APIErrorEnvelope
@Failure 503 {object} APIErrorEnvelope
@Router /auth/login [post]
func (*AuthHandler) Logout ¶
func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request)
Logout clears the session cookie and invalidates the server-side session.
@Summary Logout
@Tags auth
@Produce json
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /auth/logout [post]
func (*AuthHandler) Status ¶
func (h *AuthHandler) Status(w http.ResponseWriter, r *http.Request)
Status returns whether the client is authenticated and optional session metadata.
@Summary Auth status
@Tags auth
@Produce json
@Success 200 {object} AuthStatusResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /auth/status [get]
type AuthStatusResponse ¶
type AuthStatusResponse struct {
Authenticated bool `json:"authenticated" example:"true"`
AuthDisabled bool `json:"authDisabled" example:"false"`
Login string `json:"login,omitempty" example:"admin"`
ExpiresIn int `json:"expiresIn,omitempty" example:"3600"`
}
AuthStatusResponse is the raw (non-enveloped) payload for GET /auth/status.
type BackupWarningDTO ¶
type BootStatusHandler ¶
type BootStatusHandler struct {
InstanceID string
}
BootStatusHandler serves GET /api/boot-status (public).
func NewBootStatusHandler ¶
func NewBootStatusHandler(instanceID string) *BootStatusHandler
NewBootStatusHandler returns a handler that reports boot phase and instance id.
func (*BootStatusHandler) Get ¶
func (h *BootStatusHandler) Get(w http.ResponseWriter, r *http.Request)
Get responds with boot readiness and instance id for frontend restart detection.
@Summary Boot status
@Description Public snapshot: initializing flag, phase, instance id.
@Tags system
@Produce json
@Success 200 {object} BootStatusResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /boot-status [get]
type BootStatusResponse ¶
type BootStatusResponse struct {
Initializing bool `json:"initializing" example:"false"`
RemainingSeconds int `json:"remainingSeconds" example:"0"`
Phase string `json:"phase" example:"ready"`
InstanceId string `json:"instanceId" example:"a1b2c3d4e5f6"`
}
BootStatusResponse is the raw (non-enveloped) payload for GET /boot-status.
type ChangelogData ¶
type ChangelogData struct {
Entries []ChangelogEntryDTO `json:"entries"`
}
ChangelogData is the payload for GET /system/update/changelog.
type ChangelogEntryDTO ¶
type ChangelogEntryDTO struct {
Version string `json:"version" example:"2.5.0"`
Date string `json:"date" example:"2024-01-15"`
Groups []ChangelogGroupDTO `json:"groups"`
}
ChangelogEntryDTO mirrors frontend ChangelogEntry.
type ChangelogGroupDTO ¶
type ChangelogGroupDTO struct {
Heading string `json:"heading" example:"Bug Fixes"`
Items []string `json:"items" example:"Fixed tunnel restart loop"`
}
ChangelogGroupDTO mirrors frontend ChangelogGroup.
type ChangelogResponse ¶
type ChangelogResponse struct {
Success bool `json:"success" example:"true"`
Data ChangelogData `json:"data"`
}
ChangelogResponse is the envelope for GET /system/update/changelog.
type ClashProxy ¶
type ClashProxy struct {
// contains filtered or unexported fields
}
ClashProxy forwards /api/singbox/clash/* to the sing-box embedded Clash API. Supports both plain HTTP (GET/DELETE/POST) and WebSocket upgrade (for /traffic, /connections, /logs endpoints).
func NewClashProxy ¶
func NewClashProxy(op *singbox.Operator) *ClashProxy
NewClashProxy creates a ClashProxy backed by the given sing-box Operator.
func (*ClashProxy) ClashBaseURL ¶
func (p *ClashProxy) ClashBaseURL() string
ClashBaseURL returns the upstream clash_api endpoint, e.g. "http://127.0.0.1:9099". Used by SingboxProxiesHandler to make internal HTTP calls instead of duplicating the URL. Returns an empty string if the underlying ClashClient has no address yet so callers can short-circuit before issuing a malformed request.
func (*ClashProxy) ServeHTTP ¶
func (p *ClashProxy) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP routes HTTP and WebSocket upgrade requests to the Clash upstream.
type ClientRouteDTO ¶
type ClientRouteDTO struct {
ID string `json:"id" example:"cr_001"`
ClientIp string `json:"clientIp" example:"192.168.1.100"`
ClientHostname string `json:"clientHostname" example:"My-Phone"`
TunnelId string `json:"tunnelId" example:"tun_abc123"`
Fallback string `json:"fallback" example:"drop"`
Enabled bool `json:"enabled" example:"true"`
}
ClientRouteDTO mirrors frontend ClientRoute.
type ClientRouteHandler ¶
type ClientRouteHandler struct {
// contains filtered or unexported fields
}
ClientRouteHandler handles client route CRUD operations.
func NewClientRouteHandler ¶
func NewClientRouteHandler(svc clientroute.Service) *ClientRouteHandler
NewClientRouteHandler creates a new client route handler.
func (*ClientRouteHandler) HandleCreate ¶
func (h *ClientRouteHandler) HandleCreate(w http.ResponseWriter, r *http.Request)
HandleCreate creates a new client route. POST /api/client-routes/create Body: ClientRoute JSON
@Summary Create client route
@Tags client-routes
@Accept json
@Produce json
@Security CookieAuth
@Success 200 {object} ClientRoutesListResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /client-routes/create [post]
func (*ClientRouteHandler) HandleDelete ¶
func (h *ClientRouteHandler) HandleDelete(w http.ResponseWriter, r *http.Request)
HandleDelete deletes a client route. POST /api/client-routes/delete?id=xxx
@Summary Delete client route
@Tags client-routes
@Produce json
@Security CookieAuth
@Param id query string true "Route id"
@Success 200 {object} ClientRoutesListResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /client-routes/delete [post]
func (*ClientRouteHandler) HandleList ¶
func (h *ClientRouteHandler) HandleList(w http.ResponseWriter, r *http.Request)
HandleList returns all client routes. GET /api/client-routes
@Summary List client routes
@Tags client-routes
@Produce json
@Security CookieAuth
@Success 200 {object} ClientRoutesListResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /client-routes [get]
@Router /routing/client-routes [get]
func (*ClientRouteHandler) HandleToggle ¶
func (h *ClientRouteHandler) HandleToggle(w http.ResponseWriter, r *http.Request)
HandleToggle enables or disables a client route. POST /api/client-routes/toggle?id=xxx Body: {"enabled": bool}
@Summary Toggle client route
@Tags client-routes
@Accept json
@Produce json
@Security CookieAuth
@Param id query string true "Route id"
@Success 200 {object} ClientRoutesListResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /client-routes/toggle [post]
func (*ClientRouteHandler) HandleUpdate ¶
func (h *ClientRouteHandler) HandleUpdate(w http.ResponseWriter, r *http.Request)
HandleUpdate updates an existing client route. POST /api/client-routes/update?id=xxx Body: ClientRoute JSON
@Summary Update client route
@Tags client-routes
@Accept json
@Produce json
@Security CookieAuth
@Param id query string true "Route id"
@Success 200 {object} ClientRoutesListResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /client-routes/update [post]
func (*ClientRouteHandler) SetEventBus ¶
func (h *ClientRouteHandler) SetEventBus(bus *events.Bus)
SetEventBus sets the event bus for SSE publishing.
type ClientRoutesListResponse ¶
type ClientRoutesListResponse struct {
Success bool `json:"success" example:"true"`
Data []ClientRouteDTO `json:"data"`
}
ClientRoutesListResponse is the envelope for GET /client-routes.
type ConnectionProtocolsDTO ¶
type ConnectionProtocolsDTO struct {
TCP int `json:"tcp" example:"28"`
UDP int `json:"udp" example:"12"`
ICMP int `json:"icmp" example:"2"`
}
ConnectionProtocolsDTO holds per-protocol connection counts.
type ConnectionStatsDTO ¶
type ConnectionStatsDTO struct {
Total int `json:"total" example:"42"`
Direct int `json:"direct" example:"30"`
Tunneled int `json:"tunneled" example:"12"`
Protocols ConnectionProtocolsDTO `json:"protocols"`
}
ConnectionStatsDTO mirrors frontend ConnectionStats.
type ConnectionsData ¶
type ConnectionsData struct {
Stats ConnectionStatsDTO `json:"stats"`
// Tunnels: per-tunnel counts; key "" is direct traffic (same as query tunnel=direct / UI Direct chip).
Tunnels map[string]TunnelConnectionInfoDTO `json:"tunnels"`
Connections []ConntrackConnectionDTO `json:"connections"`
Pagination ConnectionsPaginationDTO `json:"pagination"`
FetchedAt string `json:"fetchedAt" example:"2024-01-15T10:30:00Z"`
}
ConnectionsData mirrors frontend ConnectionsResponse.
type ConnectionsHandler ¶
type ConnectionsHandler struct {
// contains filtered or unexported fields
}
ConnectionsHandler handles GET /api/connections.
func NewConnectionsHandler ¶
func NewConnectionsHandler(svc *connections.Service) *ConnectionsHandler
NewConnectionsHandler creates a new connections handler.
func (*ConnectionsHandler) List ¶
func (h *ConnectionsHandler) List(w http.ResponseWriter, r *http.Request)
List returns filtered and paginated conntrack connections.
@Summary Connections list
@Tags connections
@Produce json
@Security CookieAuth
@Success 200 {object} ConnectionsResponseEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /connections [get]
type ConnectionsPaginationDTO ¶
type ConnectionsPaginationDTO struct {
Total int `json:"total" example:"42"`
Offset int `json:"offset" example:"0"`
Limit int `json:"limit" example:"50"`
Returned int `json:"returned" example:"42"`
}
ConnectionsPaginationDTO mirrors frontend ConnectionsPagination.
type ConnectionsResponseEnvelope ¶
type ConnectionsResponseEnvelope struct {
Success bool `json:"success" example:"true"`
Data ConnectionsData `json:"data"`
}
ConnectionsResponseEnvelope is the envelope for GET /connections.
type ConnectivityResultData ¶
type ConnectivityResultData struct {
Connected bool `json:"connected" example:"true"`
Latency int `json:"latency,omitempty" example:"42"`
Reason string `json:"reason,omitempty" example:""`
}
ConnectivityResultData mirrors frontend ConnectivityResult.
type ConnectivityResultResponse ¶
type ConnectivityResultResponse struct {
Success bool `json:"success" example:"true"`
Data ConnectivityResultData `json:"data"`
}
ConnectivityResultResponse is the envelope for GET /test/connectivity.
type ConntrackConnectionDTO ¶
type ConntrackConnectionDTO struct {
Protocol string `json:"protocol" example:"tcp"`
Src string `json:"src" example:"192.168.1.100"`
Dst string `json:"dst" example:"8.8.8.8"`
SrcPort int `json:"srcPort" example:"54321"`
DstPort int `json:"dstPort" example:"443"`
State string `json:"state" example:"ESTABLISHED"`
Packets int `json:"packets" example:"15"`
Bytes int `json:"bytes" example:"4096"`
Interface string `json:"interface" example:"nwg0"`
TunnelId string `json:"tunnelId" example:"tun_abc123"`
TunnelName string `json:"tunnelName" example:"My VPN"`
ClientMac string `json:"clientMac" example:"aa:bb:cc:dd:ee:ff"`
ClientName string `json:"clientName" example:"My Phone"`
}
ConntrackConnectionDTO mirrors frontend ConntrackConnection.
type ControlHandler ¶
type ControlHandler struct {
// contains filtered or unexported fields
}
ControlHandler handles tunnel start/stop/restart operations.
func NewControlHandler ¶
func NewControlHandler(svc TunnelService, appLogger logging.AppLogger) *ControlHandler
NewControlHandler creates a new control handler.
func (*ControlHandler) Restart ¶
func (h *ControlHandler) Restart(w http.ResponseWriter, r *http.Request)
Restart restarts a tunnel.
@Summary Restart tunnel
@Tags control
@Produce json
@Security CookieAuth
@Param id query string true "Tunnel id"
@Success 200 {object} TunnelControlResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /control/restart [post]
func (*ControlHandler) RestartAll ¶
func (h *ControlHandler) RestartAll(w http.ResponseWriter, r *http.Request)
RestartAll restarts all enabled tunnels.
@Summary Restart all enabled tunnels
@Tags control
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /control/restart-all [post]
func (*ControlHandler) SetCatalog ¶
func (h *ControlHandler) SetCatalog(_ routing.Catalog)
SetCatalog is a no-op retained for API compatibility. The control handler no longer needs direct catalog access — it just emits a resource:invalidated hint so the polling store refetches.
func (*ControlHandler) SetEventBus ¶
func (h *ControlHandler) SetEventBus(bus *events.Bus)
SetEventBus sets the event bus for SSE publishing.
func (*ControlHandler) SetOrchestrator ¶
func (h *ControlHandler) SetOrchestrator(orch *orchestrator.Orchestrator)
SetOrchestrator sets the orchestrator for lifecycle operations.
func (*ControlHandler) SetPingCheckService ¶
func (h *ControlHandler) SetPingCheckService(svc PingCheckService)
SetPingCheckService sets the ping check service for monitoring control.
func (*ControlHandler) SetTunnelsHandler ¶
func (h *ControlHandler) SetTunnelsHandler(th *TunnelsHandler)
SetTunnelsHandler sets the tunnels handler for SSE list publishing.
func (*ControlHandler) Start ¶
func (h *ControlHandler) Start(w http.ResponseWriter, r *http.Request)
Start starts a tunnel.
@Summary Start tunnel
@Tags control
@Produce json
@Security CookieAuth
@Param id query string true "Tunnel id"
@Success 200 {object} TunnelControlResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /control/start [post]
func (*ControlHandler) Stop ¶
func (h *ControlHandler) Stop(w http.ResponseWriter, r *http.Request)
Stop stops a tunnel.
@Summary Stop tunnel
@Tags control
@Produce json
@Security CookieAuth
@Param id query string true "Tunnel id"
@Success 200 {object} TunnelControlResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /control/stop [post]
func (*ControlHandler) ToggleDefaultRoute ¶
func (h *ControlHandler) ToggleDefaultRoute(w http.ResponseWriter, r *http.Request)
ToggleDefaultRoute toggles the default route setting for a tunnel.
@Summary Toggle default route
@Tags control
@Produce json
@Security CookieAuth
@Param id query string true "Tunnel id"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /control/toggle-default-route [post]
func (*ControlHandler) ToggleEnabled ¶
func (h *ControlHandler) ToggleEnabled(w http.ResponseWriter, r *http.Request)
ToggleEnabled toggles the auto-start setting for a tunnel.
@Summary Toggle tunnel autostart
@Tags control
@Produce json
@Security CookieAuth
@Param id query string true "Tunnel id"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /control/toggle-enabled [post]
type CreateAccessPolicyRequest ¶
type CreateAccessPolicyRequest struct {
Description string `json:"description" example:"My VPN policy"`
}
CreateAccessPolicyRequest is the body for POST /access-policies/create.
type CreateServerRequestDTO ¶
type CreateServerRequestDTO struct {
Address string `json:"address" example:"10.10.0.1"`
Mask string `json:"mask" example:"255.255.255.0"`
ListenPort int `json:"listenPort" example:"51821"`
Description string `json:"description,omitempty" example:"My WG Server"`
Endpoint string `json:"endpoint,omitempty" example:"203.0.113.42:51821"`
DNS string `json:"dns,omitempty" example:"8.8.8.8"`
MTU int `json:"mtu,omitempty" example:"1420"`
GenerateASC *bool `json:"generateAsc,omitempty" example:"true"`
}
CreateServerRequestDTO is the swagger-visible body for POST /managed-servers.
type CreateSubscriptionRequest ¶
type CreateSubscriptionRequest struct {
Label string `json:"label" example:"Demo Provider"`
URL string `json:"url,omitempty" example:"https://example.com/subscriptions/demo.txt"`
Inline string `` /* 256-byte string literal not displayed */
Headers []SubscriptionHeader `json:"headers"`
RefreshHours int `json:"refreshHours" example:"24"`
Enabled bool `json:"enabled" example:"true"`
Mode string `json:"mode,omitempty"` // "selector" (default) | "urltest"
URLTest *SubscriptionURLTestDTO `json:"urlTest,omitempty"`
ExcludedKeys []string `json:"excludedKeys,omitempty"` // identity-суффиксы серверов, снятых в import-preview
}
CreateSubscriptionRequest is the body for POST /api/singbox/subscriptions/create. Exactly one of URL or Inline must be provided.
type DNSRewritesHandler ¶
type DNSRewritesHandler struct {
// contains filtered or unexported fields
}
func NewDNSRewritesHandler ¶
func NewDNSRewritesHandler(svc DNSRewritesService) *DNSRewritesHandler
func (*DNSRewritesHandler) Add ¶
func (h *DNSRewritesHandler) Add(w http.ResponseWriter, r *http.Request)
Add registers a new DNS rewrite.
@Summary Add singbox-router DNS rewrite
@Description Appends a new DNS rewrite (glob pattern → IPs). The pattern must be unique.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSRewriteDTO true "DNS rewrite descriptor"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/rewrites/add [post]
func (*DNSRewritesHandler) Delete ¶
func (h *DNSRewritesHandler) Delete(w http.ResponseWriter, r *http.Request)
Delete removes the DNS rewrite at the given index.
@Summary Delete singbox-router DNS rewrite
@Description Removes the DNS rewrite at the given index (0-based priority slot).
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSRewriteDeleteRequest true "Index of the rewrite to remove"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/rewrites/delete [post]
func (*DNSRewritesHandler) List ¶
func (h *DNSRewritesHandler) List(w http.ResponseWriter, r *http.Request)
List returns all DNS rewrites in priority order.
@Summary List singbox-router DNS rewrites
@Description Returns all DNS rewrites (glob pattern → IPs) in priority order. Always a JSON array, never null.
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxDNSRewritesListResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/rewrites/list [get]
func (*DNSRewritesHandler) Move ¶
func (h *DNSRewritesHandler) Move(w http.ResponseWriter, r *http.Request)
Move reorders a DNS rewrite from one priority slot to another.
@Summary Move singbox-router DNS rewrite
@Description Moves the DNS rewrite from index `from` to index `to` (both 0-based).
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSRewriteMoveRequest true "from/to indices"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/rewrites/move [post]
func (*DNSRewritesHandler) Update ¶
func (h *DNSRewritesHandler) Update(w http.ResponseWriter, r *http.Request)
Update replaces the DNS rewrite at the given index.
@Summary Update singbox-router DNS rewrite
@Description Replaces the DNS rewrite at the given index (0-based priority slot) with the provided one.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSRewriteUpdateRequest true "Index + replacement rewrite"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/rewrites/update [post]
type DNSRewritesService ¶
type DNSRewritesService interface {
List() ([]dnsrewrite.DNSRewrite, error)
Add(dnsrewrite.DNSRewrite) error
Update(int, dnsrewrite.DNSRewrite) error
Delete(int) error
Move(from, to int) error
}
type DNSRouteHandler ¶
type DNSRouteHandler struct {
// contains filtered or unexported fields
}
DNSRouteHandler handles DNS route API endpoints.
func NewDNSRouteHandler ¶
func NewDNSRouteHandler(svc DNSRouteService, appLogger logging.AppLogger) *DNSRouteHandler
NewDNSRouteHandler creates a new DNS route handler.
func (*DNSRouteHandler) BulkBackend ¶
func (h *DNSRouteHandler) BulkBackend(w http.ResponseWriter, r *http.Request)
BulkBackend switches the routing backend for multiple lists.
@Summary Bulk set DNS route backend
@Tags dns-routes
@Accept json
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /dns-routes/bulk-backend [post]
func (*DNSRouteHandler) Create ¶
func (h *DNSRouteHandler) Create(w http.ResponseWriter, r *http.Request)
Create creates a new domain list.
@Summary Create DNS route list
@Tags dns-routes
@Accept json
@Produce json
@Security CookieAuth
@Param body body DnsRouteUpsertRequest true "DNS route list payload"
@Success 200 {object} DnsRouteResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /dns-routes/create [post]
func (*DNSRouteHandler) CreateBatch ¶
func (h *DNSRouteHandler) CreateBatch(w http.ResponseWriter, r *http.Request)
CreateBatch creates multiple domain lists at once.
@Summary Create DNS route lists (batch)
@Tags dns-routes
@Accept json
@Produce json
@Security CookieAuth
@Param body body []DnsRouteUpsertRequest true "DNS route list payloads"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /dns-routes/create-batch [post]
func (*DNSRouteHandler) Delete ¶
func (h *DNSRouteHandler) Delete(w http.ResponseWriter, r *http.Request)
Delete deletes a domain list by ID and returns the fresh list so the client can call applyMutationResponse without a separate refetch.
@Summary Delete DNS route list
@Tags dns-routes
@Produce json
@Security CookieAuth
@Param id query string true "List id"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /dns-routes/delete [post]
func (*DNSRouteHandler) DeleteBatch ¶
func (h *DNSRouteHandler) DeleteBatch(w http.ResponseWriter, r *http.Request)
DeleteBatch deletes multiple domain lists by IDs.
@Summary Delete DNS route lists (batch)
@Tags dns-routes
@Accept json
@Produce json
@Security CookieAuth
@Param body body DnsRouteDeleteBatchRequest true "IDs to delete"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /dns-routes/delete-batch [post]
func (*DNSRouteHandler) Get ¶
func (h *DNSRouteHandler) Get(w http.ResponseWriter, r *http.Request)
Get returns a single domain list by ID.
@Summary Get DNS route list
@Tags dns-routes
@Produce json
@Security CookieAuth
@Param id query string true "List id"
@Success 200 {object} DnsRouteResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /dns-routes/get [get]
func (*DNSRouteHandler) List ¶
func (h *DNSRouteHandler) List(w http.ResponseWriter, r *http.Request)
List returns all domain lists.
@Summary List DNS route lists
@Tags dns-routes
@Produce json
@Security CookieAuth
@Success 200 {object} DnsRoutesListResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /dns-routes/list [get]
@Router /routing/dns-routes [get]
func (*DNSRouteHandler) Refresh ¶
func (h *DNSRouteHandler) Refresh(w http.ResponseWriter, r *http.Request)
Refresh refreshes subscriptions for a single list or all lists.
@Summary Refresh DNS route subscriptions
@Tags dns-routes
@Produce json
@Security CookieAuth
@Param id query string false "List id (omit for all)"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /dns-routes/refresh [post]
func (*DNSRouteHandler) SetEnabled ¶
func (h *DNSRouteHandler) SetEnabled(w http.ResponseWriter, r *http.Request)
SetEnabled toggles the enabled state of a domain list.
@Summary Set DNS route list enabled
@Tags dns-routes
@Accept json
@Produce json
@Security CookieAuth
@Param id query string true "List id"
@Param body body EnabledToggleRequest true "Enabled flag"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /dns-routes/set-enabled [post]
func (*DNSRouteHandler) SetEventBus ¶
func (h *DNSRouteHandler) SetEventBus(bus *events.Bus)
SetEventBus sets the event bus for SSE publishing.
func (*DNSRouteHandler) Update ¶
func (h *DNSRouteHandler) Update(w http.ResponseWriter, r *http.Request)
Update updates an existing domain list.
@Summary Update DNS route list
@Tags dns-routes
@Accept json
@Produce json
@Security CookieAuth
@Param id query string true "List id"
@Param body body DnsRouteUpsertRequest true "DNS route list payload"
@Success 200 {object} DnsRouteResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /dns-routes/update [post]
type DNSRouteService ¶
type DNSRouteService interface {
Create(ctx context.Context, list dnsroute.DomainList) (*dnsroute.DomainList, error)
Get(ctx context.Context, id string) (*dnsroute.DomainList, error)
List(ctx context.Context) ([]dnsroute.DomainList, error)
Update(ctx context.Context, list dnsroute.DomainList) (*dnsroute.DomainList, error)
Delete(ctx context.Context, id string) error
DeleteBatch(ctx context.Context, ids []string) (int, error)
CreateBatch(ctx context.Context, lists []dnsroute.DomainList) ([]*dnsroute.DomainList, error)
SetEnabled(ctx context.Context, id string, enabled bool) error
RefreshSubscriptions(ctx context.Context, id string) error
RefreshAllSubscriptions(ctx context.Context) error
}
DNSRouteService defines what the DNS route handler needs from the service.
type DNSRouteSettingsDTO ¶
type DNSRouteSettingsDTO struct {
AutoRefreshEnabled bool `json:"autoRefreshEnabled" example:"true"`
RefreshIntervalHours int `json:"refreshIntervalHours" example:"24"`
RefreshMode string `json:"refreshMode" example:"interval"`
RefreshDailyTime string `json:"refreshDailyTime" example:"03:00"`
}
DNSRouteSettingsDTO mirrors frontend DNSRouteSettings.
type DeviceProxyAuthDTO ¶
type DeviceProxyAuthDTO struct {
Enabled bool `json:"enabled" example:"false"`
Username string `json:"username" example:""`
Password string `json:"password" example:""`
}
DeviceProxyAuthDTO mirrors frontend DeviceProxyAuth.
type DeviceProxyConfigData ¶
type DeviceProxyConfigData struct {
Enabled bool `json:"enabled" example:"false"`
ListenAll bool `json:"listenAll" example:"true"`
ListenInterface string `json:"listenInterface" example:"br0"`
Port int `json:"port" example:"1080"`
Auth DeviceProxyAuthDTO `json:"auth"`
SelectedOutbound string `json:"selectedOutbound" example:"proxy-01"`
}
DeviceProxyConfigData mirrors frontend DeviceProxyConfig.
type DeviceProxyHandler ¶
type DeviceProxyHandler struct {
// contains filtered or unexported fields
}
DeviceProxyHandler handles /api/proxy/* endpoints.
func NewDeviceProxyHandler ¶
func NewDeviceProxyHandler(svc *deviceproxy.Service, appLogger logging.AppLogger) *DeviceProxyHandler
NewDeviceProxyHandler wires a DeviceProxyHandler with the given service and logger.
func (*DeviceProxyHandler) ApplyInstances ¶
func (h *DeviceProxyHandler) ApplyInstances(w http.ResponseWriter, r *http.Request)
ApplyInstances handles POST /api/proxy/instances/apply.
@Summary Apply all device proxy instances
@Tags device-proxy
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /proxy/instances/apply [post]
func (*DeviceProxyHandler) CheckInstanceExternalIP ¶
func (h *DeviceProxyHandler) CheckInstanceExternalIP(w http.ResponseWriter, r *http.Request)
CheckInstanceExternalIP handles GET /api/proxy/instance/check-ip?id=...
@Summary Check external IP through one device proxy instance
@Tags device-proxy
@Produce json
@Security CookieAuth
@Param id query string true "Instance ID"
@Param service query string false "Specific IP service URL"
@Success 200 {object} DeviceProxyInstanceIPCheckResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /proxy/instance/check-ip [get]
func (*DeviceProxyHandler) DeleteInstance ¶
func (h *DeviceProxyHandler) DeleteInstance(w http.ResponseWriter, r *http.Request)
DeleteInstance handles DELETE /api/proxy/instance?id=...
@Summary Delete one device proxy instance
@Tags device-proxy
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /proxy/instance [delete]
func (*DeviceProxyHandler) ForceApply ¶
func (h *DeviceProxyHandler) ForceApply(w http.ResponseWriter, r *http.Request)
ForceApply — POST /api/proxy/apply
Forces a full sing-box reload with the currently-persisted Config, bypassing the smart-reload diff in SaveConfig. Used by the UI "Применить сейчас" affordance when the user saved a new default via the no-reload surgical path and now wants the live selector to snap to that default.
@Summary Force apply device proxy
@Tags device-proxy
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /proxy/apply [post]
func (*DeviceProxyHandler) GetConfig ¶
func (h *DeviceProxyHandler) GetConfig(w http.ResponseWriter, r *http.Request)
GetConfig handles GET /api/proxy/config.
@Summary Get device proxy config
@Tags device-proxy
@Produce json
@Security CookieAuth
@Success 200 {object} ProxyConfigResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /proxy/config [get]
func (*DeviceProxyHandler) GetInstance ¶
func (h *DeviceProxyHandler) GetInstance(w http.ResponseWriter, r *http.Request)
GetInstance handles GET /api/proxy/instance?id=...
@Summary Get one device proxy instance
@Tags device-proxy
@Produce json
@Security CookieAuth
@Success 200 {object} ProxyInstanceResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /proxy/instance [get]
func (*DeviceProxyHandler) GetInstanceRuntime ¶
func (h *DeviceProxyHandler) GetInstanceRuntime(w http.ResponseWriter, r *http.Request)
GetInstanceRuntime handles GET /api/proxy/instance/runtime?id=...
@Summary Get device proxy instance runtime state
@Tags device-proxy
@Produce json
@Security CookieAuth
@Success 200 {object} ProxyRuntimeResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /proxy/instance/runtime [get]
func (*DeviceProxyHandler) GetRuntime ¶
func (h *DeviceProxyHandler) GetRuntime(w http.ResponseWriter, r *http.Request)
GetRuntime — GET /api/proxy/runtime
@Summary Device proxy runtime state
@Tags device-proxy
@Produce json
@Security CookieAuth
@Success 200 {object} ProxyRuntimeResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /proxy/runtime [get]
func (*DeviceProxyHandler) ListInstances ¶
func (h *DeviceProxyHandler) ListInstances(w http.ResponseWriter, r *http.Request)
ListInstances handles GET /api/proxy/instances.
@Summary List device proxy instances
@Tags device-proxy
@Produce json
@Security CookieAuth
@Success 200 {object} ProxyInstancesResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /proxy/instances [get]
func (*DeviceProxyHandler) ListOutbounds ¶
func (h *DeviceProxyHandler) ListOutbounds(w http.ResponseWriter, r *http.Request)
ListOutbounds handles GET /api/proxy/outbounds.
@Summary List device proxy outbounds
@Tags device-proxy
@Produce json
@Security CookieAuth
@Success 200 {object} ProxyOutboundsResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /proxy/outbounds [get]
func (*DeviceProxyHandler) ListenChoices ¶
func (h *DeviceProxyHandler) ListenChoices(w http.ResponseWriter, r *http.Request)
ListenChoices handles GET /api/proxy/listen-choices. Returns the bridge interface list, LAN IP, and singbox-running status needed by the frontend inbound settings form.
@Summary Device proxy listen choices
@Tags device-proxy
@Produce json
@Security CookieAuth
@Success 200 {object} ProxyListenChoicesResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /proxy/listen-choices [get]
func (*DeviceProxyHandler) SaveConfig ¶
func (h *DeviceProxyHandler) SaveConfig(w http.ResponseWriter, r *http.Request)
SaveConfig handles PUT /api/proxy/config.
@Summary Save device proxy config
@Tags device-proxy
@Accept json
@Produce json
@Security CookieAuth
@Success 200 {object} ProxyConfigResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /proxy/config [put]
func (*DeviceProxyHandler) SaveInstance ¶
func (h *DeviceProxyHandler) SaveInstance(w http.ResponseWriter, r *http.Request)
SaveInstance handles PUT /api/proxy/instance.
@Summary Save one device proxy instance
@Tags device-proxy
@Accept json
@Produce json
@Security CookieAuth
@Success 200 {object} ProxyInstanceResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /proxy/instance [put]
func (*DeviceProxyHandler) SelectInstanceRuntime ¶
func (h *DeviceProxyHandler) SelectInstanceRuntime(w http.ResponseWriter, r *http.Request)
SelectInstanceRuntime handles POST /api/proxy/instance/runtime/select.
@Summary Select device proxy instance outbound
@Tags device-proxy
@Accept json
@Produce json
@Security CookieAuth
@Success 200 {object} ProxyRuntimeResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 409 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /proxy/instance/runtime/select [post]
func (*DeviceProxyHandler) SelectRuntime ¶
func (h *DeviceProxyHandler) SelectRuntime(w http.ResponseWriter, r *http.Request)
SelectRuntime — POST /api/proxy/runtime/select body {"tag":"..."}
@Summary Select device proxy outbound
@Tags device-proxy
@Accept json
@Produce json
@Security CookieAuth
@Success 200 {object} ProxyRuntimeResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /proxy/runtime/select [post]
type DeviceProxyInstanceData ¶
type DeviceProxyInstanceData struct {
ID string `json:"id" example:"default"`
Name string `json:"name" example:"Прокси"`
Enabled bool `json:"enabled" example:"false"`
ListenAll bool `json:"listenAll" example:"true"`
ListenInterface string `json:"listenInterface" example:"br0"`
Port int `json:"port" example:"1099"`
Auth DeviceProxyAuthDTO `json:"auth"`
SelectedOutbound string `json:"selectedOutbound" example:"proxy-01"`
}
DeviceProxyInstanceData mirrors deviceproxy.Instance for multi-instance API.
type DeviceProxyInstanceIPCheckResponse ¶
type DeviceProxyInstanceIPCheckResponse struct {
Success bool `json:"success" example:"true"`
Data DeviceProxyInstanceIPCheckResultDTO `json:"data"`
}
DeviceProxyInstanceIPCheckResponse is the envelope for GET /proxy/instance/check-ip.
type DeviceProxyInstanceIPCheckResultDTO ¶
type DeviceProxyInstanceIPCheckResultDTO struct {
DirectIP string `json:"directIp" example:"203.0.113.1"`
ProxyIP string `json:"proxyIp" example:"198.51.100.42"`
IPChanged bool `json:"ipChanged" example:"false"`
Service string `json:"service" example:"https://api.ipify.org"`
}
DeviceProxyInstanceIPCheckResultDTO mirrors frontend DeviceProxyInstanceIPCheckResult and deviceproxy.InstanceIPCheckResult (OpenAPI / swag only sees types in internal/api).
type DeviceProxyOutboundDTO ¶
type DeviceProxyOutboundDTO struct {
Tag string `json:"tag" example:"proxy-01"`
Kind string `json:"kind" example:"singbox"`
Label string `json:"label" example:"proxy-01 (VLESS)"`
Detail string `json:"detail" example:"proxy.example.com:443"`
}
DeviceProxyOutboundDTO mirrors frontend DeviceProxyOutbound.
type DeviceProxyRuntimeData ¶
type DeviceProxyRuntimeData struct {
Alive bool `json:"alive" example:"true"`
ActiveTag string `json:"activeTag" example:"proxy-01"`
DefaultTag string `json:"defaultTag" example:"proxy-01"`
}
DeviceProxyRuntimeData mirrors frontend DeviceProxyRuntime.
type DiagnosticsHandler ¶
type DiagnosticsHandler struct {
// contains filtered or unexported fields
}
DiagnosticsHandler handles diagnostics API endpoints.
func NewDiagnosticsHandler ¶
func NewDiagnosticsHandler(runner DiagnosticsRunner) *DiagnosticsHandler
NewDiagnosticsHandler creates a new diagnostics handler.
func (*DiagnosticsHandler) Result ¶
func (h *DiagnosticsHandler) Result(w http.ResponseWriter, r *http.Request)
Result returns the last completed diagnostics report as a JSON file download. GET /api/diagnostics/result
@Summary Download diagnostics report
@Tags diagnostics
@Produce application/json
@Security CookieAuth
@Success 200 {file} binary
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /diagnostics/result [get]
func (*DiagnosticsHandler) Run ¶
func (h *DiagnosticsHandler) Run(w http.ResponseWriter, r *http.Request)
Run starts a background diagnostic run. POST /api/diagnostics/run
@Summary Run diagnostics
@Tags diagnostics
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /diagnostics/run [post]
func (*DiagnosticsHandler) Status ¶
func (h *DiagnosticsHandler) Status(w http.ResponseWriter, r *http.Request)
Status returns the current diagnostic run status. GET /api/diagnostics/status
@Summary Diagnostics status
@Tags diagnostics
@Produce json
@Security CookieAuth
@Success 200 {object} DiagnosticsStatusResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /diagnostics/status [get]
func (*DiagnosticsHandler) Stream ¶
func (h *DiagnosticsHandler) Stream(w http.ResponseWriter, r *http.Request)
Stream starts a diagnostic run and streams results via SSE. GET /api/diagnostics/stream?restart=false Legacy `mode`, `route`, `tunnelId` query params are silently ignored for back-compat with old clients.
@Summary Diagnostics SSE stream
@Tags diagnostics
@Produce text/event-stream
@Security CookieAuth
@Success 200 {string} string "SSE stream"
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /diagnostics/stream [get]
type DiagnosticsRunner ¶
type DiagnosticsRunner interface {
Run(ctx context.Context) error
RunWithStream(ctx context.Context, opts diagnostics.RunOptions) (<-chan diagnostics.DiagEvent, error)
Status() diagnostics.RunStatus
Result() ([]byte, error)
}
DiagnosticsRunner is the interface for running diagnostics.
type DiagnosticsStatusData ¶
type DiagnosticsStatusData struct {
Status string `json:"status" example:"idle"`
Progress string `json:"progress" example:""`
}
DiagnosticsStatusData mirrors frontend DiagnosticsStatus.
type DiagnosticsStatusResponse ¶
type DiagnosticsStatusResponse struct {
Success bool `json:"success" example:"true"`
Data DiagnosticsStatusData `json:"data"`
}
DiagnosticsStatusResponse is the envelope for GET /diagnostics/status.
type DnsCheckHandler ¶
type DnsCheckHandler struct {
// contains filtered or unexported fields
}
func NewDnsCheckHandler ¶
func NewDnsCheckHandler(svc *dnscheck.Service) *DnsCheckHandler
func (*DnsCheckHandler) Client ¶
func (h *DnsCheckHandler) Client(w http.ResponseWriter, r *http.Request)
Client returns client IP, hostname, and access-policy assignment only (fast path).
@Summary Client context for diagnostics
@Tags dns-check
@Produce json
@Security CookieAuth
@Success 200 {object} DnsCheckStartResponseEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /dns-check/client [get]
func (*DnsCheckHandler) Probe ¶
func (h *DnsCheckHandler) Probe(w http.ResponseWriter, r *http.Request)
Probe — cross-origin endpoint hit by the client's DNS probe fetch. If the client's DNS resolves awgm-dnscheck.test to the router, this endpoint is reachable and responds with 200. NO auth required.
@Summary DNS check probe (CORS)
@Tags dns-check
@Produce json
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /dns-check/probe [get]
func (*DnsCheckHandler) Start ¶
func (h *DnsCheckHandler) Start(w http.ResponseWriter, r *http.Request)
Start initiates DNS diagnostic check (server-side checks only).
@Summary Start DNS check
@Tags dns-check
@Produce json
@Security CookieAuth
@Success 200 {object} DnsCheckStartResponseEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /dns-check/start [post]
type DnsCheckResultDTO ¶
type DnsCheckResultDTO struct {
ID string `json:"id" example:"dns_leak"`
Status string `json:"status" example:"ok"`
Title string `json:"title" example:"DNS Leak Test"`
Message string `json:"message" example:"No DNS leak detected"`
Detail string `json:"detail,omitempty" example:""`
}
DnsCheckResultDTO mirrors frontend DnsCheckResult.
type DnsCheckStartData ¶
type DnsCheckStartData struct {
ClientIP string `json:"clientIP" example:"192.168.1.100"`
Hostname string `json:"hostname" example:"my-phone.local"`
Checks []DnsCheckResultDTO `json:"checks"`
}
DnsCheckStartData mirrors frontend DnsCheckStartResponse.
type DnsCheckStartResponseEnvelope ¶
type DnsCheckStartResponseEnvelope struct {
Success bool `json:"success" example:"true"`
Data DnsCheckStartData `json:"data"`
}
DnsCheckStartResponseEnvelope is the envelope for POST /dns-check/start.
type DnsProxyInfoData ¶
type DnsProxyInfoData struct {
Proxies []diagnostics.DNSProxy `json:"proxies"`
}
DnsProxyInfoData is the response payload.
type DnsProxyInfoEnvelope ¶
type DnsProxyInfoEnvelope struct {
Success bool `json:"success" example:"true"`
Data DnsProxyInfoData `json:"data"`
}
DnsProxyInfoEnvelope documents the success envelope for swagger.
type DnsProxyInfoHandler ¶
type DnsProxyInfoHandler struct {
// contains filtered or unexported fields
}
func NewDnsProxyInfoHandler ¶
func NewDnsProxyInfoHandler(store dnsProxyStatusReader, policies accessPolicyLister) *DnsProxyInfoHandler
func (*DnsProxyInfoHandler) Get ¶
func (h *DnsProxyInfoHandler) Get(w http.ResponseWriter, r *http.Request)
Get returns the parsed /show/dns-proxy state.
@Summary DNS proxy info
@Description Running ndnproxy state: upstreams, per-policy stats, static records, rebind.
@Tags diagnostics
@Produce json
@Security CookieAuth
@Success 200 {object} DnsProxyInfoEnvelope
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /diagnostics/dns-proxy [get]
type DnsRouteDTO ¶
type DnsRouteDTO struct {
ID string `json:"id" example:"dns_xyz789"`
Name string `json:"name" example:"Work VPN"`
Domains []string `json:"domains" example:"example.com"`
Excludes []string `json:"excludes,omitempty" example:"ads.example.com"`
ExcludesText string `json:"excludesText,omitempty" example:"# local bypass\n.local\n10.0.0.0/8"`
ExcludeSubnets []string `json:"excludeSubnets,omitempty" example:"10.0.0.0/24"`
Subnets []string `json:"subnets,omitempty" example:"10.0.0.0/8"`
ManualDomains []string `json:"manualDomains" example:"corp.internal"`
ManualText string `json:"manualText,omitempty" example:"# streaming\nyoutube.com\n# backup\ngooglevideo.com"`
Subscriptions []DnsRouteSubscriptionDTO `json:"subscriptions,omitempty"`
Routes []DnsRouteTargetDTO `json:"routes"`
Enabled bool `json:"enabled" example:"true"`
CreatedAt string `json:"createdAt" example:"2024-01-01T00:00:00Z"`
UpdatedAt string `json:"updatedAt" example:"2024-01-15T12:00:00Z"`
Backend string `json:"backend,omitempty" enums:"ndms,hydraroute" example:"hydraroute"`
IconURL string `json:"iconUrl,omitempty" example:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."`
HRRouteMode string `json:"hrRouteMode,omitempty" enums:"interface,policy" example:"interface"`
HRPolicyName string `json:"hrPolicyName,omitempty" example:"Streaming"`
HRPolicyInterfaces []string `json:"hrPolicyInterfaces,omitempty" example:"Wireguard0"`
}
DnsRouteDTO mirrors frontend DnsRoute.
type DnsRouteDeleteBatchRequest ¶
type DnsRouteDeleteBatchRequest struct {
IDs []string `json:"ids" example:"dns_a,dns_b"`
}
DnsRouteDeleteBatchRequest is the request body for batch delete.
type DnsRouteResponse ¶
type DnsRouteResponse struct {
Success bool `json:"success" example:"true"`
Data DnsRouteDTO `json:"data"`
}
DnsRouteResponse is the envelope for GET /dns-routes/get and mutations.
type DnsRouteSubscriptionDTO ¶
type DnsRouteSubscriptionDTO struct {
URL string `json:"url" example:"https://example.com/list.txt"`
Name string `json:"name" example:"Block list"`
LastFetched string `json:"lastFetched,omitempty" example:"2024-01-15T02:00:00Z"`
LastCount int `json:"lastCount,omitempty" example:"1500"`
}
DnsRouteSubscriptionDTO mirrors frontend DnsRouteSubscription.
type DnsRouteTargetDTO ¶
type DnsRouteTargetDTO struct {
Interface string `json:"interface" example:"nwg0"`
TunnelId string `json:"tunnelId" example:"tun_abc123"`
Fallback string `json:"fallback,omitempty" example:"auto"`
}
DnsRouteTargetDTO mirrors frontend DnsRouteTarget.
type DnsRouteUpsertRequest ¶
type DnsRouteUpsertRequest struct {
Name string `json:"name" example:"Youtube"`
ManualDomains []string `json:"manualDomains" example:"youtube.com,.googlevideo.com,geosite:GOOGLE"`
ManualText string `json:"manualText,omitempty" example:"# game servers\nexample.com\n203.0.113.0/24"`
Subscriptions []DnsRouteSubscriptionDTO `json:"subscriptions,omitempty"`
Excludes []string `json:"excludes,omitempty" example:"ads.youtube.com"`
ExcludesText string `json:"excludesText,omitempty" example:"# local bypass\n.local\n10.0.0.0/8"`
ExcludeSubnets []string `json:"excludeSubnets,omitempty" example:"10.0.0.0/24"`
Subnets []string `json:"subnets,omitempty" example:"142.250.0.0/15"`
Routes []DnsRouteTargetDTO `json:"routes,omitempty"`
Enabled bool `json:"enabled" example:"true"`
Backend string `json:"backend,omitempty" enums:"ndms,hydraroute" example:"hydraroute"`
IconURL string `json:"iconUrl,omitempty" example:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."`
HRRouteMode string `json:"hrRouteMode,omitempty" enums:"interface,policy" example:"interface"`
HRPolicyName string `json:"hrPolicyName,omitempty" example:"Streaming"`
HRPolicyInterfaces []string `json:"hrPolicyInterfaces,omitempty" example:"Wireguard0"`
}
DnsRouteUpsertRequest is the request body for DNS/HR route list create/update.
type DnsRoutesListResponse ¶
type DnsRoutesListResponse struct {
Success bool `json:"success" example:"true"`
Data []DnsRouteDTO `json:"data"`
}
DnsRoutesListResponse is the envelope for GET /dns-routes/list.
type DownloadHandler ¶
type DownloadHandler struct {
// contains filtered or unexported fields
}
func NewDownloadHandler ¶
func NewDownloadHandler(svc *downloader.Service) *DownloadHandler
func (*DownloadHandler) ListOutbounds ¶
func (h *DownloadHandler) ListOutbounds(w http.ResponseWriter, r *http.Request)
ListOutbounds returns existing route options for service downloads.
@Summary List service download outbounds
@Tags download
@Produce json
@Security CookieAuth
@Success 200 {object} DownloadOutboundsResponse
@Failure 500 {object} APIErrorEnvelope
@Router /download/outbounds [get]
type DownloadOutboundDTO ¶
type DownloadOutboundsResponse ¶
type DownloadOutboundsResponse struct {
Success bool `json:"success" example:"true"`
Data []DownloadOutboundDTO `json:"data"`
}
type DownloadRouteDTO ¶
type DownloadSettingsDTO ¶
type EnabledToggleRequest ¶
type EnabledToggleRequest struct {
Enabled bool `json:"enabled" example:"true"`
}
EnabledToggleRequest is the body for endpoints that flip an enabled flag (SetEnabled, TogglePeer).
type EventsHandler ¶
type EventsHandler struct {
// contains filtered or unexported fields
}
EventsHandler serves the SSE event stream.
func NewEventsHandler ¶
func NewEventsHandler(bus *events.Bus, instanceID string) *EventsHandler
NewEventsHandler creates a new events handler.
func (*EventsHandler) Stream ¶
func (h *EventsHandler) Stream(w http.ResponseWriter, r *http.Request)
Stream serves the SSE event stream. GET /api/events
@Summary SSE event stream
@Tags events
@Produce text/event-stream
@Security CookieAuth
@Success 200 {string} string "Server-Sent Events"
@Success 299 {object} SingboxRouterTransitionData "Schema of a singbox-router:transition push event carried on this stream (documentation only — never an HTTP status)"
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /events [get]
The stream carries only incremental/push-only events (traffic, connectivity, logs, ping-check logs, sing-box delay/traffic, geo download progress, DNS-route failover notifications, and the generic resource:invalidated hint). All cold-tier state is fetched via REST by the frontend polling stores; the initial "connected" marker lets the client confirm the stream is open before any push event arrives.
type ExcludeMembersRequest ¶
type ExcludeMembersRequest struct {
MemberTags []string `json:"memberTags" example:"sub-demo-002,sub-demo-003"`
}
ExcludeMembersRequest is the body for POST /api/singbox/subscriptions/members/exclude. Excluding members is only allowed on URL-backed subscriptions and is reversible via restore.
type ExternalTunnelDTO ¶
type ExternalTunnelDTO struct {
InterfaceName string `json:"interfaceName" example:"Wireguard2"`
TunnelNumber int `json:"tunnelNumber" example:"2"`
IsAWG bool `json:"isAWG" example:"true"`
PublicKey string `json:"publicKey,omitempty" example:"KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK="`
Endpoint string `json:"endpoint,omitempty" example:"ext.example.com:51820"`
RxBytes int64 `json:"rxBytes" example:"1048576"`
TxBytes int64 `json:"txBytes" example:"524288"`
}
ExternalTunnelDTO mirrors frontend ExternalTunnel.
type ExternalTunnelService ¶
type ExternalTunnelService interface {
List(ctx context.Context) ([]external.TunnelInfo, error)
Adopt(ctx context.Context, req external.AdoptRequest) (*service.TunnelWithStatus, error)
}
ExternalTunnelService defines the interface for external tunnel operations.
type ExternalTunnelsHandler ¶
type ExternalTunnelsHandler struct {
// contains filtered or unexported fields
}
ExternalTunnelsHandler handles external tunnel operations.
func NewExternalTunnelsHandler ¶
func NewExternalTunnelsHandler(svc ExternalTunnelService, tunnelSvc TunnelService, store *storage.AWGTunnelStore, appLogger logging.AppLogger) *ExternalTunnelsHandler
NewExternalTunnelsHandler creates a new external tunnels handler.
func (*ExternalTunnelsHandler) Adopt ¶
func (h *ExternalTunnelsHandler) Adopt(w http.ResponseWriter, r *http.Request)
Adopt takes control of an external tunnel. Endpoint: POST /api/external-tunnels/adopt?interface=opkgtunX
@Summary Adopt external tunnel
@Tags tunnels
@Accept json
@Produce json
@Security CookieAuth
@Param interface query string true "NDMS interface name"
@Param body body AdoptRequest true "Tunnel config body"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /external-tunnels/adopt [post]
func (*ExternalTunnelsHandler) List ¶
func (h *ExternalTunnelsHandler) List(w http.ResponseWriter, r *http.Request)
List returns all external (unmanaged) tunnels. Endpoint: GET /api/external-tunnels
@Summary List external tunnels
@Tags tunnels
@Produce json
@Security CookieAuth
@Success 200 {object} ExternalTunnelsResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /external-tunnels [get]
func (*ExternalTunnelsHandler) SetTunnelListPublisher ¶
func (h *ExternalTunnelsHandler) SetTunnelListPublisher(fn func(ctx context.Context))
SetTunnelListPublisher sets the function that publishes the full tunnel list via SSE.
type ExternalTunnelsResponse ¶
type ExternalTunnelsResponse struct {
Success bool `json:"success" example:"true"`
Data []ExternalTunnelDTO `json:"data"`
}
ExternalTunnelsResponse is the envelope for GET /external-tunnels.
type GeoExpandData ¶
type GeoExpandData struct {
Lines []string `json:"lines"`
Path string `json:"path"`
Count int `json:"count"`
}
GeoExpandData is the payload for GET /hydraroute/geo-expand.
type GeoFileEntryDTO ¶
type GeoFileEntryDTO struct {
Type string `json:"type" example:"geosite"`
Path string `json:"path" example:"/opt/etc/hrneo/geosite.db"`
URL string `json:"url" example:"https://cdn.example.com/geosite.db"`
Size int64 `json:"size" example:"3145728"`
TagCount int `json:"tagCount" example:"420"`
Updated string `json:"updated" example:"2024-01-15T02:00:00Z"`
External bool `json:"external,omitempty" example:"true"`
}
GeoFileEntryDTO mirrors frontend GeoFileEntry.
type GeoFileResponse ¶
type GeoFileResponse struct {
Success bool `json:"success" example:"true"`
Data GeoFileEntryDTO `json:"data"`
}
GeoFileResponse is the envelope for endpoints that return a single geo file entry (POST /hydraroute/geo-files/add).
type GeoFileSettingsDTO ¶
type GeoFileSettingsDTO struct {
AutoRefreshEnabled bool `json:"autoRefreshEnabled" example:"false"`
RefreshIntervalHours int `json:"refreshIntervalHours" example:"24"`
RefreshMode string `json:"refreshMode" example:"interval"`
RefreshDailyTime string `json:"refreshDailyTime" example:"03:00"`
}
GeoFileSettingsDTO mirrors frontend GeoFileSettings.
type GeoFileUpdatedData ¶
type GeoFileUpdatedData struct {
Updated int `json:"updated" example:"1"`
Partial bool `json:"partial,omitempty" example:"true"`
Error string `json:"error,omitempty"`
}
GeoFileUpdatedData reports how many geo files were re-downloaded by POST /hydraroute/geo-files/update. The shape is the same whether the caller targeted one path or all paths.
type GeoFileUpdatedResponse ¶
type GeoFileUpdatedResponse struct {
Success bool `json:"success" example:"true"`
Data GeoFileUpdatedData `json:"data"`
}
GeoFileUpdatedResponse is the envelope for POST /hydraroute/geo-files/update.
type GeoFilesRescannedData ¶
type GeoFilesRescannedData struct {
Adopted int `json:"adopted" example:"1"`
}
GeoFilesRescannedData reports how many new paths were adopted from hrneo.conf.
type GeoFilesRescannedResponse ¶
type GeoFilesRescannedResponse struct {
Success bool `json:"success" example:"true"`
Data GeoFilesRescannedData `json:"data"`
}
GeoFilesRescannedResponse is the envelope for POST /hydraroute/geo-files/rescan.
type GeoFilesResponse ¶
type GeoFilesResponse struct {
Success bool `json:"success" example:"true"`
Data []GeoFileEntryDTO `json:"data"`
}
GeoFilesResponse is the envelope for GET /hydraroute/geo-files.
type GeoTagDTO ¶
type GeoTagDTO struct {
Name string `json:"name" example:"google"`
Count int `json:"count" example:"1250"`
}
GeoTagDTO mirrors frontend GeoTag.
type GeoTagsResponse ¶
type GeoTagsResponse struct {
Success bool `json:"success" example:"true"`
Data []GeoTagDTO `json:"data"`
}
GeoTagsResponse is the envelope for GET /hydraroute/geo-tags.
type HealthData ¶
type HealthData struct {
OK bool `json:"ok" example:"true"`
Version string `json:"version" example:"2.5.0"`
InstanceID string `json:"instanceId" example:"b6c2ef8df6cf4b2782f8f45a7dc8e3a1"`
}
HealthData is the response data for GET /health.
type HealthHandler ¶
type HealthHandler struct {
// contains filtered or unexported fields
}
HealthHandler serves GET /api/health. A cheap liveness check that does no I/O, no NDMS calls — used by the frontend 5-second poller to decide when to show the full-screen "backend offline" overlay independently of SSE connection state.
func NewHealthHandler ¶
func NewHealthHandler(version, instanceID string) *HealthHandler
NewHealthHandler constructs a HealthHandler that reports the given build version. The version is set via ldflags at build time and propagated from cmd/awg-manager/main.go through server.Config.Version.
func (*HealthHandler) ServeHTTP ¶
func (h *HealthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP responds to GET with { ok: true, version: "...", instanceId: "..." }. Any other method returns 405 Method Not Allowed.
@Summary Health / liveness
@Description Cheap check for frontend pollers; no NDMS or I/O.
@Tags system
@Produce json
@Success 200 {object} HealthResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /health [get]
type HealthResponse ¶
type HealthResponse struct {
Success bool `json:"success" example:"true"`
Data HealthData `json:"data"`
}
HealthResponse is the envelope for GET /health.
type HookDispatcher ¶
HookDispatcher is the subset of events.Dispatcher that HookHandler uses. Interface so tests can inject a fake.
type HookHandler ¶
type HookHandler struct {
// contains filtered or unexported fields
}
HookHandler handles NDM hook events.
func NewHookHandler ¶
func NewHookHandler(svc TunnelService, orch *orchestrator.Orchestrator, appLogger logging.AppLogger) *HookHandler
NewHookHandler creates a new hook event handler.
func (*HookHandler) EnterSelfCreate ¶
func (h *HookHandler) EnterSelfCreate()
EnterSelfCreate marks the start of an awg-manager-initiated NDMS interface creation. Pair with ExitSelfCreate via defer.
func (*HookHandler) ExitSelfCreate ¶
func (h *HookHandler) ExitSelfCreate()
ExitSelfCreate marks the end of an awg-manager-initiated NDMS interface creation. Callers MUST publish a fresh tunnels invalidation hint themselves after this (typically via TunnelsHandler.publishTunnelList) so UIs see the finalized state.
func (*HookHandler) HandleNDMS ¶
func (h *HookHandler) HandleNDMS(w http.ResponseWriter, r *http.Request)
HandleNDMS is the unified hook endpoint. The shared forwarder script installed into /opt/etc/ndm/{iflayerchanged,ifcreated,ifdestroyed, ifipchanged}.d/ POSTs here with a `type` discriminator. The handler parses the form into a typed events.Event, enqueues it into the Dispatcher for cache invalidation, and (for iflayerchanged only) also forwards to the orchestrator for tunnel-lifecycle decisions.
POST /api/hook/ndms
type=iflayerchanged|ifcreated|ifdestroyed|ifipchanged
id=<ndms-interface-id>
system_name=<kernel-name>
layer=<conf|link|ipv4|ipv6|ctrl> (layerchanged only)
level=<running|disabled|...> (layerchanged only)
address=<ipv4> (ipchanged only)
up=<0|1>
connected=<0|1>
@Summary NDMS shell hook
@Description Called from router scripts (public). Form fields: type, id, system_name, layer, etc.
@Tags hook
@Accept x-www-form-urlencoded
@Produce json
@Param type formData string true "Event type (iflayerchanged, ifcreated, ...)"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /hook/ndms [post]
func (*HookHandler) SetDispatcher ¶
func (h *HookHandler) SetDispatcher(d HookDispatcher)
SetDispatcher wires an events.Dispatcher for hook-driven cache invalidation. Call after construction (typically from server.New).
func (*HookHandler) SetTunnelRefresher ¶
func (h *HookHandler) SetTunnelRefresher(fn TunnelHookInvalidator)
SetTunnelRefresher wires the callback that invalidates NDMS caches and publishes a tunnels `resource:invalidated` hint on ifcreated / ifdestroyed. Without it, the UI keeps showing cards for tunnels that NDMS has already torn down (reported bug).
func (*HookHandler) SetWANModel ¶
func (h *HookHandler) SetWANModel(m HookWANModel)
SetWANModel wires the WAN model so iflayerchanged layer=ipv4 hooks can update WAN interface up/down state in-memory before dispatching EventWANUp/Down to the orchestrator.
type HookWANModel ¶
HookWANModel is the narrow surface HookHandler needs from the WAN model. Kept local so api/hook.go doesn't depend on *wan.Model.
type HotspotLister ¶
HotspotLister is the narrow contract this handler needs from the NDMS hotspot cache. Lives here so the handler doesn't import internal/ndms/query directly — fake-friendly.
type HydraRouteConfigData ¶
type HydraRouteConfigData struct {
AutoStart bool `json:"autoStart" example:"true"`
ClearIPSet bool `json:"clearIPSet" example:"false"`
CIDR bool `json:"cidr" example:"true"`
IpsetEnableTimeout bool `json:"ipsetEnableTimeout" example:"false"`
IpsetTimeout int `json:"ipsetTimeout" example:"0"`
IpsetMaxElem int `json:"ipsetMaxElem" example:"65536"`
DirectRouteEnabled bool `json:"directRouteEnabled" example:"false"`
GlobalRouting bool `json:"globalRouting" example:"false"`
ConntrackFlush bool `json:"conntrackFlush" example:"true"`
Log string `json:"log" example:"warn"`
LogFile string `json:"logFile" example:"/var/log/hrneo.log"`
GeoIPFiles []string `json:"geoIPFiles" example:"/opt/etc/hrneo/geoip.db"`
GeoSiteFiles []string `json:"geoSiteFiles" example:"/opt/etc/hrneo/geosite.db"`
PolicyOrder []string `json:"policyOrder" example:"default"`
}
HydraRouteConfigData mirrors frontend HydraRouteConfig.
type HydraRouteConfigResponse ¶
type HydraRouteConfigResponse struct {
Success bool `json:"success" example:"true"`
Data HydraRouteConfigData `json:"data"`
}
HydraRouteConfigResponse is the envelope for GET /hydraroute/config.
type HydraRouteHandler ¶
type HydraRouteHandler struct {
// contains filtered or unexported fields
}
HydraRouteHandler handles HydraRoute Neo settings API endpoints.
func NewHydraRouteHandler ¶
func NewHydraRouteHandler(svc *hydraroute.Service, downloadSvc *downloader.Service) *HydraRouteHandler
NewHydraRouteHandler creates a new HydraRoute settings handler.
func (*HydraRouteHandler) AddGeoFile ¶
func (h *HydraRouteHandler) AddGeoFile(w http.ResponseWriter, r *http.Request)
AddGeoFile downloads and registers a new geo data file.
@Summary Add HydraRoute geo file
@Tags hydraroute
@Accept json
@Produce json
@Security CookieAuth
@Param body body AddGeoFileRequest true "Geo file source descriptor"
@Success 200 {object} GeoFileResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /hydraroute/geo-files/add [post]
func (*HydraRouteHandler) DeleteGeoFile ¶
func (h *HydraRouteHandler) DeleteGeoFile(w http.ResponseWriter, r *http.Request)
DeleteGeoFile removes a tracked geo data file.
@Summary Delete HydraRoute geo file
@Description Removes the tracked geo data file at the given path and re-syncs the geo file list to config.
@Tags hydraroute
@Produce json
@Security CookieAuth
@Param path query string true "Filesystem path of the geo file"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /hydraroute/geo-files/delete [delete]
func (*HydraRouteHandler) ExpandGeoTag ¶
func (h *HydraRouteHandler) ExpandGeoTag(w http.ResponseWriter, r *http.Request)
ExpandGeoTag expands a geosite:/geoip: tag into inline rule list lines.
@Summary HydraRoute geo tag expand
@Tags hydraroute
@Produce json
@Security CookieAuth
@Param kind query string true "geosite or geoip"
@Param tag query string true "Tag name"
@Success 200 {object} GeoExpandData
@Router /hydraroute/geo-expand [get]
func (*HydraRouteHandler) GetConfig ¶
func (h *HydraRouteHandler) GetConfig(w http.ResponseWriter, r *http.Request)
GetConfig returns the current HydraRoute config.
@Summary Get HydraRoute config
@Description Available when HydraRoute service is wired on the device.
@Tags hydraroute
@Produce json
@Security CookieAuth
@Success 200 {object} HydraRouteConfigResponse
@Router /hydraroute/config [get]
func (*HydraRouteHandler) GetGeoTags ¶
func (h *HydraRouteHandler) GetGeoTags(w http.ResponseWriter, r *http.Request)
GetGeoTags returns the tag list for a specific geo data file.
@Summary HydraRoute geo tags
@Tags hydraroute
@Produce json
@Security CookieAuth
@Param path query string true "Geo file path"
@Success 200 {array} string
@Router /hydraroute/geo-tags [get]
func (*HydraRouteHandler) GetIpsetUsage ¶
func (h *HydraRouteHandler) GetIpsetUsage(w http.ResponseWriter, r *http.Request)
GetIpsetUsage returns the current ipset usage per kernel interface.
@Summary HydraRoute ipset usage
@Tags hydraroute
@Produce json
@Security CookieAuth
@Success 200 {object} IpsetUsageResponse
@Failure 500 {object} APIErrorEnvelope
@Router /hydraroute/ipset-usage [get]
func (*HydraRouteHandler) GetOversizedTags ¶
func (h *HydraRouteHandler) GetOversizedTags(w http.ResponseWriter, r *http.Request)
GetOversizedTags returns the list of geoip tags HR Neo excluded plus the current IpsetMaxElem so the frontend can render the 'Отключённые теги' pane and enforce picker limits.
@Summary HydraRoute oversized geo tags
@Tags hydraroute
@Produce json
@Security CookieAuth
@Success 200 {object} OversizedTagsResponse
@Failure 500 {object} APIErrorEnvelope
@Router /hydraroute/oversized-tags [get]
func (*HydraRouteHandler) ListGeoFiles ¶
func (h *HydraRouteHandler) ListGeoFiles(w http.ResponseWriter, r *http.Request)
ListGeoFiles returns all tracked geo data files.
@Summary List HydraRoute geo files
@Tags hydraroute
@Produce json
@Security CookieAuth
@Success 200 {object} GeoFilesResponse
@Failure 500 {object} APIErrorEnvelope
@Router /hydraroute/geo-files [get]
func (*HydraRouteHandler) RescanGeoFiles ¶
func (h *HydraRouteHandler) RescanGeoFiles(w http.ResponseWriter, r *http.Request)
RescanGeoFiles adopts geo paths from hrneo.conf not yet in the catalog.
@Summary Rescan HydraRoute geo files from hrneo.conf
@Tags hydraroute
@Produce json
@Security CookieAuth
@Success 200 {object} GeoFilesRescannedResponse
@Failure 500 {object} APIErrorEnvelope
@Router /hydraroute/geo-files/rescan [post]
func (*HydraRouteHandler) SetEventBus ¶
func (h *HydraRouteHandler) SetEventBus(bus *events.Bus)
SetEventBus wires the SSE bus so HR Neo mutations that touch the DNS route list (policy order, native rule import, config write) can emit resource:invalidated hints for `routing.dnsRoutes`, and so HR daemon state changes publish `routing.hydrarouteStatus` hints.
func (*HydraRouteHandler) SetPolicyOrder ¶
func (h *HydraRouteHandler) SetPolicyOrder(w http.ResponseWriter, r *http.Request)
SetPolicyOrder updates the PolicyOrder in hrneo.conf.
@Summary Set HydraRoute policy order
@Tags hydraroute
@Accept json
@Produce json
@Security CookieAuth
@Param body body SetPolicyOrderRequest true "Ordered list of policy names"
@Success 200 {object} PolicyOrderResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /hydraroute/policy-order [post]
func (*HydraRouteHandler) TakeGeoFileControl ¶
func (h *HydraRouteHandler) TakeGeoFileControl(w http.ResponseWriter, r *http.Request)
TakeGeoFileControl moves an external HydraRoute file into awg-manager/geo.
@Summary Take HydraRoute geo file under awg-manager control
@Tags hydraroute
@Accept json
@Produce json
@Security CookieAuth
@Param body body TakeGeoFileControlRequest true "Filesystem path of the external geo file"
@Success 200 {object} GeoFileResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /hydraroute/geo-files/take-control [post]
func (*HydraRouteHandler) UpdateConfig ¶
func (h *HydraRouteHandler) UpdateConfig(w http.ResponseWriter, r *http.Request)
UpdateConfig writes the HydraRoute config.
@Summary Update HydraRoute config
@Description Persists the HydraRoute (HrNeo) config and schedules a neo restart. The cached status becomes stale and is invalidated via SSE.
@Tags hydraroute
@Accept json
@Produce json
@Security CookieAuth
@Param body body HydraRouteConfigData true "hydraroute.Config"
@Success 200 {object} HydraRouteConfigResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /hydraroute/config/update [put]
func (*HydraRouteHandler) UpdateGeoFile ¶
func (h *HydraRouteHandler) UpdateGeoFile(w http.ResponseWriter, r *http.Request)
UpdateGeoFile re-downloads a geo data file (or all files if path is empty).
@Summary Refresh HydraRoute geo file(s)
@Description Empty path triggers a bulk refresh of every tracked geo file. Single path refreshes one file. Both branches return an updated count for caller-side feedback; the frontend refetches the list afterwards.
@Tags hydraroute
@Accept json
@Produce json
@Security CookieAuth
@Param body body UpdateGeoFileRequest true "Path to refresh, or empty to refresh all"
@Success 200 {object} GeoFileUpdatedResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /hydraroute/geo-files/update [post]
type HydraRouteStatusData ¶
type HydraRouteStatusData struct {
Installed bool `json:"installed" example:"true"`
Running bool `json:"running" example:"true"`
Version string `json:"version,omitempty" example:"2.4.1"`
PID int `json:"pid,omitempty" example:"12345"`
StalePID int `json:"stalePid,omitempty" example:"12345"`
ProcessState string `json:"processState" example:"running" enums:"not_installed,stopped,running,dead"`
LastError string `json:"lastError,omitempty" example:"neo restart: exit status 1"`
}
HydraRouteStatusData mirrors frontend HydraRouteStatus.
type HydraRouteStatusResponse ¶
type HydraRouteStatusResponse struct {
Success bool `json:"success" example:"true"`
Data HydraRouteStatusData `json:"data"`
}
HydraRouteStatusResponse is the envelope for GET /system/hydraroute-status.
type IPCheckServiceDTO ¶
type IPCheckServiceDTO struct {
Label string `json:"label" example:"ipinfo.io"`
URL string `json:"url" example:"https://ipinfo.io/ip"`
}
IPCheckServiceDTO mirrors frontend IPCheckService.
type IPResultData ¶
type IPResultData struct {
DirectIp string `json:"directIp" example:"203.0.113.1"`
VpnIp string `json:"vpnIp" example:"185.220.101.1"`
EndpointIp string `json:"endpointIp" example:"203.0.113.42"`
IpChanged bool `json:"ipChanged" example:"true"`
}
IPResultData mirrors frontend IPResult.
type IPResultResponse ¶
type IPResultResponse struct {
Success bool `json:"success" example:"true"`
Data IPResultData `json:"data"`
}
IPResultResponse is the envelope for GET /test/ip.
type IPServicesResponse ¶
type IPServicesResponse struct {
Success bool `json:"success" example:"true"`
Data []IPCheckServiceDTO `json:"data"`
}
IPServicesResponse is the envelope for GET /test/ip/services.
type ImportHandler ¶
type ImportHandler struct {
// contains filtered or unexported fields
}
ImportHandler handles config import operations.
func NewImportHandler ¶
func NewImportHandler(svc TunnelService, store *storage.AWGTunnelStore, appLogger logging.AppLogger) *ImportHandler
NewImportHandler creates a new import handler.
func (*ImportHandler) ImportConf ¶
func (h *ImportHandler) ImportConf(w http.ResponseWriter, r *http.Request)
ImportConf imports a WireGuard/AmneziaWG config file.
@Summary Import tunnel config
@Tags import
@Accept json
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /import/conf [post]
func (*ImportHandler) SetPingCheckService ¶
func (h *ImportHandler) SetPingCheckService(svc PingCheckService)
SetPingCheckService sets the ping check service.
func (*ImportHandler) SetSettingsStore ¶
func (h *ImportHandler) SetSettingsStore(store *storage.SettingsStore)
SetSettingsStore sets the settings store for reading defaults.
func (*ImportHandler) SetTunnelsHandler ¶
func (h *ImportHandler) SetTunnelsHandler(th *TunnelsHandler)
SetTunnelsHandler sets the tunnels handler for SSE publishing after import.
type IpsetUsageData ¶
type IpsetUsageData struct {
MaxElem int `json:"maxElem" example:"65536"`
Usage map[string]int `json:"usage"`
}
IpsetUsageData mirrors hydraroute.IpsetUsage.
type IpsetUsageResponse ¶
type IpsetUsageResponse struct {
Success bool `json:"success" example:"true"`
Data IpsetUsageData `json:"data"`
}
IpsetUsageResponse is the envelope for GET /hydraroute/ipset-usage.
type KmodLoader ¶
type KmodLoader interface {
ModuleExists() bool
IsLoaded() bool
Model() string
SoC() kmod.SoC
OnDiskVersion() string
}
KmodLoader provides kernel module status.
type LANSegmentEntryDTO ¶
type LANSegmentEntryDTO struct {
Name string `json:"name" example:"Home"`
Label string `json:"label" example:"Home"`
Subnet string `json:"subnet" example:"192.168.1.0/24"`
}
LANSegmentEntryDTO is a single LAN bridge entry returned by the listing endpoint.
type LANSegmentsListResponse ¶
type LANSegmentsListResponse struct {
Success bool `json:"success" example:"true"`
Data []LANSegmentEntryDTO `json:"data"`
}
LANSegmentsListResponse is the envelope for GET /managed-servers/lan-segments.
type LogEntryDTO ¶
type LogEntryDTO struct {
Timestamp string `json:"timestamp" example:"2024-01-15T10:30:00Z"`
Level string `json:"level" example:"info"`
Group string `json:"group" example:"singbox"`
Subgroup string `json:"subgroup" example:"dns"`
Action string `json:"action" example:"run"`
Target string `json:"target" example:"dns"`
Message string `json:"message" example:"lookup succeed for node.example.org: 203.0.113.77"`
Sanitized bool `json:"sanitized" example:"false"`
}
LogEntryDTO mirrors frontend LogEntry.
type LoggingHandler ¶
type LoggingHandler struct {
// contains filtered or unexported fields
}
LoggingHandler handles logging API endpoints.
func NewLoggingHandler ¶
func NewLoggingHandler(svc *logging.Service, appLogger logging.AppLogger) *LoggingHandler
NewLoggingHandler creates a new logging handler.
func (*LoggingHandler) ClearLogs ¶
func (h *LoggingHandler) ClearLogs(w http.ResponseWriter, r *http.Request)
ClearLogs removes all entries from the requested bucket.
POST /api/logs/clear?bucket=app|singbox
@Summary Clear logs
@Description Clears all entries from the requested bucket. `bucket` is required — there is no implicit "clear everything" since app and sing-box logs serve different audiences.
@Tags logs
@Produce json
@Security CookieAuth
@Param bucket query string true "Bucket to clear" Enums(app, singbox)
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /logs/clear [post]
func (*LoggingHandler) GetLogs ¶
func (h *LoggingHandler) GetLogs(w http.ResponseWriter, r *http.Request)
GetLogs returns log entries from the requested bucket with optional filtering and pagination.
GET /api/logs?bucket=app|singbox&group=&subgroup=&level=&limit=&offset=&since=&sanitize=
@Summary Get logs
@Description Returns log entries from the selected bucket. `bucket=app` (default) covers tunnel/routing/server/system events; `bucket=singbox` covers sing-box forwarder events isolated from app history. By default target/message are backend-masked; pass `sanitize=false` only when the authenticated admin UI explicitly reveals raw logs.
@Tags logs
@Produce json
@Security CookieAuth
@Param bucket query string false "Bucket selector" Enums(app, singbox)
@Param group query []string false "Filter by group (repeat param or comma-separated values)" collectionFormat(multi)
@Param subgroup query []string false "Filter by subgroup (repeat param or comma-separated values)" collectionFormat(multi)
@Param level query string false "Filter by level"
@Param limit query int false "Max entries to return (default 200)"
@Param offset query int false "Skip first N matching entries"
@Param since query int false "Unix seconds — return only entries strictly after this"
@Param sanitize query bool false "Return backend-sanitized target/message values; default true, set false to reveal raw values"
@Success 200 {object} LogsResponseEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /logs [get]
func (*LoggingHandler) GetSubgroups ¶
func (h *LoggingHandler) GetSubgroups(w http.ResponseWriter, r *http.Request)
GetSubgroups returns the static catalog of subgroups for the requested group. Used by the frontend to render a second-row chip filter.
GET /api/logs/subgroups?group=routing
@Summary List known subgroups for a group
@Description Returns the static subgroup catalog from internal/logging.KnownSubgroups. Order is presentation-stable. Empty group returns 400.
@Tags logs
@Produce json
@Security CookieAuth
@Param group query string true "Group name" Enums(tunnel, routing, server, system, singbox)
@Success 200 {object} SubgroupsResponseEnvelope
@Failure 400 {object} APIErrorEnvelope
@Router /logs/subgroups [get]
func (*LoggingHandler) PublishSnapshot ¶
func (h *LoggingHandler) PublishSnapshot()
PublishSnapshot is a retained no-op hook — the legacy `snapshot:logs` SSE event was removed (state-sync redesign), and the frontend now fetches logs via REST. Keeping the method preserves the callback wiring in server.go / settings.go without forcing a broader refactor.
func (*LoggingHandler) SetEventBus ¶
func (h *LoggingHandler) SetEventBus(bus *events.Bus)
SetEventBus sets the event bus for SSE snapshot publishing.
type LoggingSettingsDTO ¶
type LoggingSettingsDTO struct {
Enabled bool `json:"enabled" example:"true"`
MaxAge int `json:"maxAge" example:"2"`
LogLevel string `json:"logLevel" example:"info"`
SingboxLogLevel string `json:"singboxLogLevel" example:"trace" enums:"trace,debug,info,warn,error,fatal,panic"`
AppMaxEntries int `json:"appMaxEntries" example:"5000"`
SingboxMaxEntries int `json:"singboxMaxEntries" example:"5000"`
}
LoggingSettingsDTO mirrors frontend LoggingSettings.
type LoginRequest ¶
LoginRequest is the request body for login.
type LoginResponseRaw ¶
type LoginResponseRaw struct {
Success bool `json:"success" example:"true"`
Login string `json:"login" example:"admin"`
}
LoginResponseRaw is the raw response for POST /auth/login.
type LogsData ¶
type LogsData struct {
Enabled bool `json:"enabled" example:"true"`
Logs []LogEntryDTO `json:"logs"`
Total int `json:"total" example:"42"`
Bucket string `json:"bucket" example:"singbox"`
BufferSize int `json:"bufferSize" example:"123"`
BufferCapacity int `json:"bufferCapacity" example:"5000"`
Sanitized bool `json:"sanitized" example:"false"`
OldestTimestamp string `json:"oldestTimestamp,omitempty" example:"2024-01-15T08:00:00Z"`
}
LogsData mirrors frontend LogsResponse.
type LogsResponse ¶
type LogsResponse struct {
Enabled bool `json:"enabled"`
Logs []LogEntryDTO `json:"logs"`
Total int `json:"total"`
Bucket string `json:"bucket"`
BufferSize int `json:"bufferSize"`
BufferCapacity int `json:"bufferCapacity"`
Sanitized bool `json:"sanitized"`
OldestTimestamp string `json:"oldestTimestamp,omitempty"`
}
LogsResponse represents the response for get logs endpoint.
type LogsResponseEnvelope ¶
type LogsResponseEnvelope struct {
Success bool `json:"success" example:"true"`
Data LogsData `json:"data"`
}
LogsResponseEnvelope is the envelope for GET /logs.
type ManagedPeerDTO ¶
type ManagedPeerDTO struct {
PublicKey string `json:"publicKey" example:"HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH="`
PrivateKey string `json:"privateKey" example:"IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII="`
Description string `json:"description" example:"My Phone"`
TunnelIP string `json:"tunnelIP" example:"10.10.0.2"`
DNS string `json:"dns,omitempty" example:"8.8.8.8"`
Enabled bool `json:"enabled" example:"true"`
}
ManagedPeerDTO mirrors frontend ManagedPeer.
type ManagedPeerResponse ¶
type ManagedPeerResponse struct {
Success bool `json:"success" example:"true"`
Data ManagedPeerDTO `json:"data"`
}
ManagedPeerResponse is the envelope for endpoints that return a single managed-server peer (POST /managed-servers/{id}/peers).
type ManagedPeerStatsDTO ¶
type ManagedPeerStatsDTO struct {
PublicKey string `json:"publicKey" example:"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF="`
Endpoint string `json:"endpoint" example:"5.6.7.8:54321"`
RxBytes int64 `json:"rxBytes" example:"2097152"`
TxBytes int64 `json:"txBytes" example:"1048576"`
LastHandshake string `json:"lastHandshake" example:"2024-01-15T10:30:00Z"`
Online bool `json:"online" example:"true"`
}
ManagedPeerStatsDTO mirrors frontend ManagedPeerStats.
type ManagedServerBackupDTO ¶
type ManagedServerBackupDTO struct {
InterfaceName string `json:"interfaceName" example:"Wireguard1"`
Description string `json:"description,omitempty" example:"My VPN"`
Address string `json:"address" example:"10.10.0.1"`
Mask string `json:"mask" example:"255.255.255.0"`
ListenPort int `json:"listenPort" example:"51821"`
Endpoint string `json:"endpoint,omitempty" example:"vpn.example.com:51821"`
DNS string `json:"dns,omitempty" example:"8.8.8.8"`
MTU int `json:"mtu,omitempty" example:"1420"`
NATEnabled bool `json:"natEnabled,omitempty" example:"true"`
PrivateKey string `json:"privateKey,omitempty" example:"oA..."`
Policy string `json:"policy" example:"none"`
Peers []ManagedPeerDTO `json:"peers"`
I1 string `json:"i1,omitempty"`
I2 string `json:"i2,omitempty"`
I3 string `json:"i3,omitempty"`
I4 string `json:"i4,omitempty"`
I5 string `json:"i5,omitempty"`
ASC json.RawMessage `json:"asc,omitempty" swaggertype:"object"`
}
ManagedServerBackupDTO mirrors storage.ManagedServer for backup/restore transport. Exists in api/ (rather than reusing managed.ManagedServerExport directly) so swag can resolve it without crossing package boundaries — matches the existing ManagedServerDTO pattern but includes the secret fields (PrivateKey, I1, I2) needed for full restore.
type ManagedServerBackupFile ¶
type ManagedServerBackupFile struct {
Version int `json:"version"`
Type string `json:"type"`
ExportedAt time.Time `json:"exportedAt"`
ManagedServers []ManagedServerBackupDTO `json:"managedServers"`
Warnings []BackupWarningDTO `json:"warnings,omitempty"`
}
ManagedServerBackupFile is the on-disk JSON shape.
type ManagedServerBackupHandler ¶
type ManagedServerBackupHandler struct {
// contains filtered or unexported fields
}
ManagedServerBackupHandler exposes Export / Import / Drift / RestoreDrift.
func NewManagedServerBackupHandler ¶
func NewManagedServerBackupHandler(svc *managed.Service) *ManagedServerBackupHandler
NewManagedServerBackupHandler creates a new backup handler.
func (*ManagedServerBackupHandler) Drift ¶
func (h *ManagedServerBackupHandler) Drift(w http.ResponseWriter, r *http.Request)
Drift handles GET /api/managed/drift.
@Summary List managed servers missing from NDMS
@Description Returns settings.json entries whose NDMS interface is absent.
@Tags managed
@Produce json
@Security CookieAuth
@Success 200 {object} ManagedServerDriftEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed/drift [get]
func (*ManagedServerBackupHandler) Export ¶
func (h *ManagedServerBackupHandler) Export(w http.ResponseWriter, r *http.Request)
Export handles GET /api/managed/export.
@Summary Export all managed servers
@Description Returns a JSON backup file with every managed server including private keys.
@Tags managed
@Produce json
@Security CookieAuth
@Success 200 {object} ManagedServerExportEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed/export [get]
func (*ManagedServerBackupHandler) Import ¶
func (h *ManagedServerBackupHandler) Import(w http.ResponseWriter, r *http.Request)
Import handles POST /api/managed/import.
@Summary Import a managed-server backup
@Description Restores managed servers from a backup file. Per-server atomic with pre-flight conflict detection.
@Tags managed
@Accept json
@Produce json
@Security CookieAuth
@Param body body ManagedServerImportRequest true "backup contents + options"
@Success 200 {object} ManagedServerImportEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed/import [post]
func (*ManagedServerBackupHandler) RestoreDrift ¶
func (h *ManagedServerBackupHandler) RestoreDrift(w http.ResponseWriter, r *http.Request)
RestoreDrift handles POST /api/managed/restore-drift.
@Summary Restore drifted managed servers
@Description Detects drift internally then runs Restore on it. Convenience entry for the boot-time banner.
@Tags managed
@Accept json
@Produce json
@Security CookieAuth
@Param body body ManagedServerRestoreDriftRequest false "options"
@Success 200 {object} ManagedServerImportEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed/restore-drift [post]
func (*ManagedServerBackupHandler) SetEventBus ¶
func (h *ManagedServerBackupHandler) SetEventBus(bus *events.Bus)
SetEventBus wires the SSE bus so Import and RestoreDrift can publish resource:invalidated after a successful restore.
type ManagedServerDTO ¶
type ManagedServerDTO struct {
InterfaceName string `json:"interfaceName" example:"Wireguard1"`
Address string `json:"address" example:"10.10.0.1"`
Mask string `json:"mask" example:"255.255.255.0"`
ListenPort int `json:"listenPort" example:"51821"`
Endpoint string `json:"endpoint,omitempty" example:"203.0.113.42:51821"`
DNS string `json:"dns,omitempty" example:"8.8.8.8"`
MTU int `json:"mtu,omitempty" example:"1420"`
NatEnabled bool `json:"natEnabled,omitempty" example:"true"`
NATMode string `json:"natMode,omitempty" example:"internet-only"`
LANSegments []string `json:"lanSegments,omitempty" example:"Home"`
Policy string `json:"policy" example:"default"`
Peers []ManagedPeerDTO `json:"peers"`
}
ManagedServerDTO mirrors frontend ManagedServer.
type ManagedServerDriftEnvelope ¶
type ManagedServerDriftEnvelope struct {
Success bool `json:"success" example:"true"`
Data ManagedServerDriftResponse `json:"data"`
}
ManagedServerDriftEnvelope is the wire shape of GET /api/managed/drift.
type ManagedServerDriftResponse ¶
type ManagedServerDriftResponse struct {
Drift []ManagedServerBackupDTO `json:"drift"`
}
ManagedServerDriftResponse is the response of GET /api/managed/drift.
type ManagedServerExportEnvelope ¶
type ManagedServerExportEnvelope struct {
Success bool `json:"success" example:"true"`
Data ManagedServerBackupFile `json:"data"`
}
ManagedServerExportEnvelope is the wire shape of GET /api/managed/export.
type ManagedServerHandler ¶
type ManagedServerHandler struct {
// contains filtered or unexported fields
}
ManagedServerHandler handles managed WireGuard server operations.
func NewManagedServerHandler ¶
func NewManagedServerHandler(svc managed.ManagedServerService) *ManagedServerHandler
NewManagedServerHandler creates a new managed server handler.
func (*ManagedServerHandler) ASC ¶
func (h *ManagedServerHandler) ASC(w http.ResponseWriter, r *http.Request, id string)
ASC handles GET/PUT for ASC parameters of a managed server.
GET /api/managed-servers/{id}/asc — read params PUT /api/managed-servers/{id}/asc — write params
@Summary Get/set managed-server ASC params
@Description GET returns ASCParamsResponse with the current AWG signature/obfuscation params object. PUT writes new params (raw object whose shape depends on the active signature preset) and returns the fresh ServersSnapshot.
@Tags managed-servers
@Accept json
@Produce json
@Security CookieAuth
@Param id path string true "Server id"
@Param body body object false "ASC params object (PUT only)"
@Success 200 {object} ASCParamsResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers/{id}/asc [get]
@Router /managed-servers/{id}/asc [put]
func (*ManagedServerHandler) AddPeer ¶
func (h *ManagedServerHandler) AddPeer(w http.ResponseWriter, r *http.Request, id string)
AddPeer adds a new peer to a managed server. POST /api/managed-servers/{id}/peers
@Summary Add managed-server peer
@Description Adds a new peer to the named managed server. The pubkey is generated server-side if absent.
@Tags managed-servers
@Accept json
@Produce json
@Security CookieAuth
@Param id path string true "Server id"
@Param body body AddPeerRequestDTO true "Peer payload"
@Success 200 {object} ManagedPeerResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers/{id}/peers [post]
func (*ManagedServerHandler) Collection ¶
func (h *ManagedServerHandler) Collection(w http.ResponseWriter, r *http.Request)
Collection dispatches the exact /api/managed-servers endpoint:
- GET → List
- POST → Create
func (*ManagedServerHandler) Create ¶
func (h *ManagedServerHandler) Create(w http.ResponseWriter, r *http.Request)
Create creates a new managed WireGuard server. The id is allocated by the service (next free Wireguard{N} slot) — the request body has no id. POST /api/managed-servers
@Summary Create managed server
@Description Creates a new managed WireGuard server. The id is allocated server-side (next free Wireguard{N} slot).
@Tags managed-servers
@Accept json
@Produce json
@Security CookieAuth
@Param body body CreateServerRequestDTO true "Address, mask, port, ASC, name"
@Success 200 {object} ManagedServerResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers [post]
func (*ManagedServerHandler) Delete ¶
func (h *ManagedServerHandler) Delete(w http.ResponseWriter, r *http.Request, id string)
Delete removes a managed server and all its peers. DELETE /api/managed-servers/{id}
@Summary Delete managed server
@Description Removes the named managed server along with all its peers. Returns the fresh ServersSnapshot.
@Tags managed-servers
@Produce json
@Security CookieAuth
@Param id path string true "Server id"
@Success 200 {object} ServersAllResponse
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers/{id} [delete]
func (*ManagedServerHandler) DeletePeer ¶
func (h *ManagedServerHandler) DeletePeer(w http.ResponseWriter, r *http.Request, id, pubkey string)
DeletePeer removes a peer from a managed server. DELETE /api/managed-servers/{id}/peers/{pubkey}
@Summary Delete managed-server peer
@Description Removes the peer identified by pubkey from the named managed server.
@Tags managed-servers
@Produce json
@Security CookieAuth
@Param id path string true "Server id"
@Param pubkey path string true "Peer public key (URL-encoded)"
@Success 200 {object} ServersAllResponse
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers/{id}/peers/{pubkey} [delete]
func (*ManagedServerHandler) Get ¶
func (h *ManagedServerHandler) Get(w http.ResponseWriter, r *http.Request, id string)
Get returns a single managed server by id. GET /api/managed-servers/{id}
@Summary Get managed server
@Description Returns a single managed server by id (Wireguard{N}).
@Tags managed-servers
@Produce json
@Security CookieAuth
@Param id path string true "Server id (e.g. Wireguard0)"
@Success 200 {object} ManagedServerResponse
@Failure 404 {object} APIErrorEnvelope
@Failure 405 {object} APIErrorEnvelope
@Router /managed-servers/{id} [get]
func (*ManagedServerHandler) GetPolicies ¶
func (h *ManagedServerHandler) GetPolicies(w http.ResponseWriter, r *http.Request)
GetPolicies returns every IP Policy profile available on the router. This is a global catalog — not per-server — so it lives at the collection level even though the consumer is a per-server dropdown. GET /api/managed-servers/policies
@Summary List IP Policy profiles
@Description Returns the global router catalog of IP Policy profiles for use by the per-server policy dropdown. Always a JSON array, never null.
@Tags managed-servers
@Produce json
@Security CookieAuth
@Success 200 {object} PoliciesListResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers/policies [get]
func (*ManagedServerHandler) LANSegments ¶
func (h *ManagedServerHandler) LANSegments(w http.ResponseWriter, r *http.Request, id string)
LANSegments sets the LAN bridge segments accessible to peers of one managed server. POST /api/managed-servers/{id}/lan-segments
@Summary Set managed-server LAN segments
@Description Configures which LAN bridge segments (by NDMS interface name) peers of the managed server are allowed to reach via ACL-based forwarding.
@Tags managed-servers
@Accept json
@Produce json
@Security CookieAuth
@Param id path string true "Server id"
@Param body body SetLANSegmentsRequest true "LAN segment names"
@Success 200 {object} ServersAllResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers/{id}/lan-segments [post]
func (*ManagedServerHandler) List ¶
func (h *ManagedServerHandler) List(w http.ResponseWriter, r *http.Request)
List returns every managed server. Always emits a JSON array (never null). GET /api/managed-servers
@Summary List managed servers
@Description Returns every managed server (id, address, listen port, peers, ASC, NAT, enabled flag, ...). Always a JSON array, never null.
@Tags managed-servers
@Produce json
@Security CookieAuth
@Success 200 {object} ManagedServersListResponse
@Failure 405 {object} APIErrorEnvelope
@Router /managed-servers [get]
func (*ManagedServerHandler) ListLANSegments ¶
func (h *ManagedServerHandler) ListLANSegments(w http.ResponseWriter, r *http.Request)
ListLANSegments returns the router LAN bridge catalog for the UI picker. GET /api/managed-servers/lan-segments
@Summary List router LAN segments
@Description Returns the router's LAN bridge catalog (name, label, subnet) for use by the per-server LAN segment picker. Always a JSON array, never null.
@Tags managed-servers
@Produce json
@Security CookieAuth
@Success 200 {object} LANSegmentsListResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers/lan-segments [get]
func (*ManagedServerHandler) NAT ¶
func (h *ManagedServerHandler) NAT(w http.ResponseWriter, r *http.Request, id string)
NAT enables or disables NAT on one managed server interface. POST /api/managed-servers/{id}/nat
@Summary Toggle managed-server NAT
@Description Enables or disables NAT (masquerade) on the named managed server interface.
@Tags managed-servers
@Accept json
@Produce json
@Security CookieAuth
@Param id path string true "Server id"
@Param body body SetNATModeRequest true "NAT mode"
@Success 200 {object} ServersAllResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers/{id}/nat [post]
func (*ManagedServerHandler) PeerConf ¶
func (h *ManagedServerHandler) PeerConf(w http.ResponseWriter, r *http.Request, id, pubkey string)
PeerConf returns the WireGuard client .conf file for a peer. GET /api/managed-servers/{id}/peers/{pubkey}/conf
@Summary Generate peer .conf
@Description Returns the WireGuard client .conf for the peer identified by pubkey on the named managed server.
@Tags managed-servers
@Produce json
@Security CookieAuth
@Param id path string true "Server id"
@Param pubkey path string true "Peer public key (URL-encoded)"
@Success 200 {object} PeerConfResponse
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers/{id}/peers/{pubkey}/conf [get]
func (*ManagedServerHandler) Restart ¶
func (h *ManagedServerHandler) Restart(w http.ResponseWriter, r *http.Request, id string)
Restart accepts a restart/start command for one managed server. POST /api/managed-servers/{id}/restart
@Summary Restart or start managed server
@Description If the managed server is up, restarts it with down -> pause -> up. If it is down, starts it. The command is accepted quickly and executed in background so a client connected through this server does not cancel the operation.
@Tags managed-servers
@Produce json
@Security CookieAuth
@Param id path string true "Server id"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 405 {object} APIErrorEnvelope
@Router /managed-servers/{id}/restart [post]
func (*ManagedServerHandler) SetEnabled ¶
func (h *ManagedServerHandler) SetEnabled(w http.ResponseWriter, r *http.Request, id string)
SetEnabled enables or disables one managed server interface. POST /api/managed-servers/{id}/enabled
@Summary Toggle managed-server enabled
@Description Brings the named managed server interface up or down (and persists the desired state).
@Tags managed-servers
@Accept json
@Produce json
@Security CookieAuth
@Param id path string true "Server id"
@Param body body EnabledToggleRequest true "Enabled flag"
@Success 200 {object} ServersAllResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers/{id}/enabled [post]
func (*ManagedServerHandler) SetPolicy ¶
func (h *ManagedServerHandler) SetPolicy(w http.ResponseWriter, r *http.Request, id string)
SetPolicy updates the ip hotspot policy for one managed server interface. POST /api/managed-servers/{id}/policy
@Summary Set managed-server IP policy
@Description Updates the IP hotspot policy bound to the managed server interface. The policy must exist (see /managed-servers/policies).
@Tags managed-servers
@Accept json
@Produce json
@Security CookieAuth
@Param id path string true "Server id"
@Param body body SetServerPolicyRequest true "Policy id (router-side)"
@Success 200 {object} ServersAllResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers/{id}/policy [post]
func (*ManagedServerHandler) SetServersHandler ¶
func (h *ManagedServerHandler) SetServersHandler(s *ServersHandler)
SetServersHandler sets the servers handler for shared SSE publishing.
func (*ManagedServerHandler) Stats ¶
func (h *ManagedServerHandler) Stats(w http.ResponseWriter, r *http.Request, id string)
Stats returns runtime statistics for one managed server's peers. GET /api/managed-servers/{id}/stats
@Summary Get managed-server peer stats
@Description Returns per-peer runtime stats (handshake, rx/tx) for the named managed server.
@Tags managed-servers
@Produce json
@Security CookieAuth
@Param id path string true "Server id"
@Success 200 {object} ManagedServerStatsResponse
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers/{id}/stats [get]
func (*ManagedServerHandler) Subtree ¶
func (h *ManagedServerHandler) Subtree(w http.ResponseWriter, r *http.Request)
Subtree dispatches every URL under /api/managed-servers/, splitting on '/' to extract the id and any further sub-path. See the documented route table in this package's package doc / Task 5 plan for the full mapping.
func (*ManagedServerHandler) SuggestAddress ¶
func (h *ManagedServerHandler) SuggestAddress(w http.ResponseWriter, r *http.Request)
SuggestAddress returns a free private /24 for the create-server UI. GET /api/managed-servers/suggest-address
@Summary Suggest managed-server address
@Description Returns a free private /24 (address, mask) for the create-server UI. Avoids collisions with already-used managed-server subnets.
@Tags managed-servers
@Produce json
@Security CookieAuth
@Success 200 {object} SuggestAddressResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers/suggest-address [get]
func (*ManagedServerHandler) TogglePeer ¶
func (h *ManagedServerHandler) TogglePeer(w http.ResponseWriter, r *http.Request, id, pubkey string)
TogglePeer enables or disables a peer. POST /api/managed-servers/{id}/peers/{pubkey}/toggle
@Summary Toggle managed-server peer enabled
@Description Enables or disables the peer identified by pubkey on the named managed server.
@Tags managed-servers
@Accept json
@Produce json
@Security CookieAuth
@Param id path string true "Server id"
@Param pubkey path string true "Peer public key (URL-encoded)"
@Param body body EnabledToggleRequest true "Enabled flag"
@Success 200 {object} ServersAllResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers/{id}/peers/{pubkey}/toggle [post]
func (*ManagedServerHandler) Update ¶
func (h *ManagedServerHandler) Update(w http.ResponseWriter, r *http.Request, id string)
Update updates a managed server's address and/or listen port. PUT /api/managed-servers/{id}
@Summary Update managed server
@Description Updates a managed server's address, listen port, name, and/or other top-level fields. Returns the fresh ServersSnapshot.
@Tags managed-servers
@Accept json
@Produce json
@Security CookieAuth
@Param id path string true "Server id"
@Param body body UpdateServerRequestDTO true "Update payload"
@Success 200 {object} ServersAllResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers/{id} [put]
func (*ManagedServerHandler) UpdatePeer ¶
func (h *ManagedServerHandler) UpdatePeer(w http.ResponseWriter, r *http.Request, id, pubkey string)
UpdatePeer updates an existing peer of a managed server. PUT /api/managed-servers/{id}/peers/{pubkey}
@Summary Update managed-server peer
@Description Updates fields (name, allowed-ips, ...) of the peer identified by pubkey on the named managed server.
@Tags managed-servers
@Accept json
@Produce json
@Security CookieAuth
@Param id path string true "Server id"
@Param pubkey path string true "Peer public key (URL-encoded)"
@Param body body UpdatePeerRequestDTO true "Peer update payload"
@Success 200 {object} ServersAllResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /managed-servers/{id}/peers/{pubkey} [put]
type ManagedServerImportEnvelope ¶
type ManagedServerImportEnvelope struct {
Success bool `json:"success" example:"true"`
Data ManagedServerRestoreResponse `json:"data"`
}
ManagedServerImportEnvelope is the wire shape of POST /api/managed/import and POST /api/managed/restore-drift.
type ManagedServerImportRequest ¶
type ManagedServerImportRequest struct {
ManagedServers []ManagedServerBackupDTO `json:"managedServers"`
Options RestoreOptionsDTO `json:"options"`
Version int `json:"version"`
Type string `json:"type"`
}
ManagedServerImportRequest is the body of POST /api/managed/import.
type ManagedServerResponse ¶
type ManagedServerResponse struct {
Success bool `json:"success" example:"true"`
Data ManagedServerDTO `json:"data"`
}
ManagedServerResponse is the envelope for GET /managed-server.
type ManagedServerRestoreDriftRequest ¶
type ManagedServerRestoreDriftRequest struct {
Options RestoreOptionsDTO `json:"options"`
}
ManagedServerRestoreDriftRequest is the body of POST /api/managed/restore-drift.
type ManagedServerRestoreResponse ¶
type ManagedServerRestoreResponse struct {
Outcomes []RestoreOutcomeDTO `json:"outcomes"`
}
ManagedServerRestoreResponse is the response of /import and /restore-drift.
type ManagedServerStatsDTO ¶
type ManagedServerStatsDTO struct {
Status string `json:"status" example:"up"`
Peers []ManagedPeerStatsDTO `json:"peers"`
}
ManagedServerStatsDTO mirrors frontend ManagedServerStats.
type ManagedServerStatsResponse ¶
type ManagedServerStatsResponse struct {
Success bool `json:"success" example:"true"`
Data ManagedServerStatsDTO `json:"data"`
}
ManagedServerStatsResponse is the envelope for GET /managed-servers/{id}/stats. Reuses ManagedServerStatsDTO from servers.go (also referenced by ServersAllData).
type ManagedServersListResponse ¶
type ManagedServersListResponse struct {
Success bool `json:"success" example:"true"`
Data []ManagedServerDTO `json:"data"`
}
ManagedServersListResponse is the envelope for GET /managed-servers.
type MonitoringCellDTO ¶
type MonitoringCellDTO struct {
TargetID string `json:"targetId" example:"target_google"`
TunnelID string `json:"tunnelId" example:"tun_abc123"`
LatencyMs *int `json:"latencyMs" swaggertype:"integer" example:"42"`
OK bool `json:"ok" example:"true"`
ActiveForRestart bool `json:"activeForRestart" example:"false"`
IsSelf bool `json:"isSelf" example:"false"`
Ts string `json:"ts" example:"2024-01-15T10:30:00Z"`
}
MonitoringCellDTO mirrors frontend MonitoringCell.
type MonitoringHandler ¶
type MonitoringHandler struct {
// contains filtered or unexported fields
}
MonitoringHandler exposes the monitoring matrix endpoints.
func NewMonitoringHandler ¶
func NewMonitoringHandler(svc *monitoring.Service) *MonitoringHandler
NewMonitoringHandler builds a handler with the given service. svc may be nil during partial bootstrap — handlers respond 503 until Start.
func (*MonitoringHandler) GetMatrix ¶
func (h *MonitoringHandler) GetMatrix(w http.ResponseWriter, r *http.Request)
GetMatrix returns the current matrix snapshot. GET /api/monitoring/matrix
@Summary Get monitoring matrix snapshot
@Description Returns the latest cross-tunnel × cross-target latency/loss matrix snapshot. Responds 503 until the monitoring service has finished bootstrap. Pass `?force=1` to invalidate the Clash cache and run a fresh probing tick before returning.
@Tags monitoring
@Produce json
@Security CookieAuth
@Param force query int false "Set to 1 to force-refresh ICMP/Clash data before snapshot read"
@Success 200 {object} MonitoringSnapshotResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 503 {object} APIErrorEnvelope
@Router /monitoring/matrix [get]
type MonitoringRefreshService ¶
MonitoringRefreshService defines the interface for forcing an immediate monitoring snapshot recalculation after settings mutations.
type MonitoringSnapshotData ¶
type MonitoringSnapshotData struct {
Targets []MonitoringTargetDTO `json:"targets"`
Tunnels []MonitoringTunnelDTO `json:"tunnels"`
Cells []MonitoringCellDTO `json:"cells"`
UpdatedAt string `json:"updatedAt" example:"2024-01-15T10:30:00Z"`
}
MonitoringSnapshotData mirrors frontend MonitoringSnapshot.
type MonitoringSnapshotResponse ¶
type MonitoringSnapshotResponse struct {
Success bool `json:"success" example:"true"`
Data MonitoringSnapshotData `json:"data"`
}
MonitoringSnapshotResponse is the envelope for GET /monitoring/matrix.
type MonitoringTargetDTO ¶
type MonitoringTargetDTO struct {
ID string `json:"id" example:"target_google"`
Host string `json:"host" example:"https://www.google.com"`
Name string `json:"name" example:"Google"`
}
MonitoringTargetDTO mirrors frontend MonitoringTarget.
type MonitoringTunnelDTO ¶
type MonitoringTunnelDTO struct {
ID string `json:"id" example:"tun_abc123"`
Name string `json:"name" example:"My VPN"`
IfaceName string `json:"ifaceName" example:"nwg0"`
PingcheckTarget string `json:"pingcheckTarget" example:"target_google"`
SelfTarget string `json:"selfTarget" example:"target_self_tun_abc123"`
SelfMethod string `json:"selfMethod" example:"http"`
}
MonitoringTunnelDTO mirrors frontend MonitoringTunnel.
type MoveRejectedToInfoRequest ¶
type MoveRejectedToInfoRequest struct {
MemberTag string `json:"memberTag"`
}
MoveRejectedToInfoRequest is the body for POST .../rejected/to-info.
type NDMSHandler ¶
type NDMSHandler struct {
// contains filtered or unexported fields
}
NDMSHandler exposes read-only NDMS status endpoints that are not scoped to a more specific handler (routing, tunnels, managed, etc.).
func NewNDMSHandler ¶
func NewNDMSHandler(save *ndmscommand.SaveCoordinator) *NDMSHandler
NewNDMSHandler constructs a handler backed by the live SaveCoordinator. The coordinator pointer must be non-nil; main.go builds it before the HTTP server starts.
func (*NDMSHandler) GetSaveStatus ¶
func (h *NDMSHandler) GetSaveStatus(w http.ResponseWriter, r *http.Request)
GetSaveStatus returns the current NDMS save-coordinator status as JSON. GET /api/ndms/save-status
@Summary NDMS save coordinator status
@Tags ndms
@Produce json
@Security CookieAuth
@Success 200 {object} SaveStatusDTO
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /ndms/save-status [get]
type NativePingCheckStatusDTO ¶
type NativePingCheckStatusDTO struct {
Exists bool `json:"exists" example:"true"`
Host string `json:"host" example:"https://www.google.com"`
Mode string `json:"mode" example:"connect"`
Interval int `json:"interval" example:"30"`
MaxFails int `json:"maxFails" example:"3"`
MinSuccess int `json:"minSuccess" example:"1"`
Timeout int `json:"timeout" example:"5"`
Restart bool `json:"restart" example:"true"`
Bound bool `json:"bound" example:"true"`
Status string `json:"status" example:"alive"`
FailCount int `json:"failCount" example:"0"`
SuccessCount int `json:"successCount" example:"120"`
}
NativePingCheckStatusDTO mirrors frontend NativePingCheckStatus.
type NativePingCheckStatusResponse ¶
type NativePingCheckStatusResponse struct {
Success bool `json:"success" example:"true"`
Data NativePingCheckStatusDTO `json:"data"`
}
NativePingCheckStatusResponse is the envelope for GET /tunnels/pingcheck.
type OkData ¶
type OkData struct {
Ok bool `json:"ok" example:"true"`
}
OkData is the {ok: true} confirmation payload returned by mutation endpoints that have no entity to send back.
type OkResponse ¶
OkResponse is the typed envelope for endpoints that return only a confirmation (success + ok). Use as @Success {object} OkResponse.
type OversizedTagDTO ¶
type OversizedTagDTO struct {
Name string `json:"name" example:"netflix"`
Count int `json:"count" example:"82000"`
File string `json:"file" example:"/opt/etc/hrneo/geosite.db"`
}
OversizedTagDTO mirrors hydraroute.OversizedTag.
type OversizedTagsData ¶
type OversizedTagsData struct {
Installed bool `json:"installed" example:"true"`
MaxElem int `json:"maxelem" example:"65536"`
Tags []OversizedTagDTO `json:"tags"`
}
OversizedTagsData reports geoip tags excluded by HrNeo together with the active IpsetMaxElem so the frontend can render the disabled-tags pane and enforce picker limits.
type OversizedTagsResponse ¶
type OversizedTagsResponse struct {
Success bool `json:"success" example:"true"`
Data OversizedTagsData `json:"data"`
}
OversizedTagsResponse is the envelope for GET /hydraroute/oversized-tags.
type PeerConfData ¶
type PeerConfData struct {
Conf string `json:"conf" example:"[Interface]\nPrivateKey = ..."`
}
PeerConfData carries a generated WireGuard client .conf as a string.
type PeerConfResponse ¶
type PeerConfResponse struct {
Success bool `json:"success" example:"true"`
Data PeerConfData `json:"data"`
}
PeerConfResponse is the envelope for GET /managed-servers/{id}/peers/{pubkey}/conf.
type PermitInterfaceRequest ¶
type PermitInterfaceRequest struct {
Name string `json:"name" example:"Policy0"`
Interface string `json:"interface" example:"Wireguard0"`
Order int `json:"order" example:"0"`
}
PermitInterfaceRequest is the body for POST /access-policies/permit.
type PingCheckDefaultsDTO ¶
type PingCheckDefaultsDTO struct {
Method string `json:"method" example:"http"`
Target string `json:"target" example:"8.8.8.8"`
Interval int `json:"interval" example:"30"`
DeadInterval int `json:"deadInterval" example:"120"`
FailThreshold int `json:"failThreshold" example:"3"`
}
PingCheckDefaultsDTO mirrors frontend PingCheckDefaults.
type PingCheckHandler ¶
type PingCheckHandler struct {
// contains filtered or unexported fields
}
PingCheckHandler handles ping check API endpoints.
func NewPingCheckHandler ¶
func NewPingCheckHandler(service PingCheckService, tunnels *storage.AWGTunnelStore, nwgOp *nwg.OperatorNativeWG, appLogger logging.AppLogger) *PingCheckHandler
NewPingCheckHandler creates a new ping check handler.
func (*PingCheckHandler) CheckNow ¶
func (h *PingCheckHandler) CheckNow(w http.ResponseWriter, r *http.Request)
CheckNow triggers an immediate check on all tunnels.
@Summary Trigger ping check now
@Tags pingcheck
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /pingcheck/check-now [post]
func (*PingCheckHandler) ClearLogs ¶
func (h *PingCheckHandler) ClearLogs(w http.ResponseWriter, r *http.Request)
ClearLogs removes all ping check log entries.
@Summary Clear ping check logs
@Tags pingcheck
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /pingcheck/logs/clear [post]
func (*PingCheckHandler) ConfigureTunnelPingCheck ¶
func (h *PingCheckHandler) ConfigureTunnelPingCheck(w http.ResponseWriter, r *http.Request)
ConfigureTunnelPingCheck creates/updates NDMS ping-check for a nativewg tunnel. POST /api/tunnels/pingcheck?id=xxx
@Summary Configure per-tunnel NDMS ping-check
@Tags pingcheck
@Accept json
@Produce json
@Security CookieAuth
@Param id query string true "Tunnel id"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /tunnels/pingcheck [post]
func (*PingCheckHandler) GetLogs ¶
func (h *PingCheckHandler) GetLogs(w http.ResponseWriter, r *http.Request)
GetLogs returns ping check logs.
@Summary Ping check logs
@Tags pingcheck
@Produce json
@Security CookieAuth
@Param tunnelId query string false "Filter by tunnel id"
@Success 200 {object} PingLogsResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /pingcheck/logs [get]
func (*PingCheckHandler) GetStatus ¶
func (h *PingCheckHandler) GetStatus(w http.ResponseWriter, r *http.Request)
GetStatus returns the current status of all monitored tunnels.
@Summary Ping check status
@Tags pingcheck
@Produce json
@Security CookieAuth
@Success 200 {object} PingCheckStatusResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /pingcheck/status [get]
func (*PingCheckHandler) GetTunnelPingCheckStatus ¶
func (h *PingCheckHandler) GetTunnelPingCheckStatus(w http.ResponseWriter, r *http.Request)
GetTunnelPingCheckStatus returns NDMS ping-check status for a single nativewg tunnel. GET /api/tunnels/pingcheck?id=xxx
@Summary Get per-tunnel NDMS ping-check
@Tags pingcheck
@Produce json
@Security CookieAuth
@Param id query string true "Tunnel id"
@Success 200 {object} NativePingCheckStatusResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /tunnels/pingcheck [get]
func (*PingCheckHandler) PublishSnapshot ¶
func (h *PingCheckHandler) PublishSnapshot()
PublishSnapshot publishes a resource:invalidated hint for pingcheck so subscribed polling stores refetch. The legacy `snapshot:pingcheck` event was removed (Task 12) — the frontend status list is now a polling store. Logs are still pushed via `pingcheck:log` stream, untouched.
func (*PingCheckHandler) RemoveTunnelPingCheck ¶
func (h *PingCheckHandler) RemoveTunnelPingCheck(w http.ResponseWriter, r *http.Request)
RemoveTunnelPingCheck removes NDMS ping-check for a nativewg tunnel. POST /api/tunnels/pingcheck/remove?id=xxx
@Summary Remove per-tunnel NDMS ping-check
@Tags pingcheck
@Produce json
@Security CookieAuth
@Param id query string true "Tunnel id"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /tunnels/pingcheck/remove [post]
func (*PingCheckHandler) SetEventBus ¶
func (h *PingCheckHandler) SetEventBus(bus *events.Bus)
SetEventBus sets the event bus for SSE invalidation hints.
func (*PingCheckHandler) SetOrchestrator ¶
func (h *PingCheckHandler) SetOrchestrator(orch *orchestrator.Orchestrator)
SetOrchestrator wires the orchestrator for in-memory state sync after ping-check enable/disable mutations. Without this the decide layer keeps a stale PingCheck.Enabled flag and fires spurious ActionRemovePingCheck on the next lifecycle event.
type PingCheckService ¶
type PingCheckService interface {
GetStatus() []pingcheck.TunnelStatus
GetLogs() []pingcheck.LogEntry
GetTunnelLogs(tunnelID string) []pingcheck.LogEntry
ClearLogs()
CheckAllNow()
IsEnabled() bool
StartMonitoringAllRunning()
StopMonitoringAll()
Stop()
// Per-tunnel monitoring control
StartMonitoring(tunnelID, tunnelName string, skipConfigure ...bool)
StopMonitoring(tunnelID string)
GetTunnelPingStatus(tunnelID string) pingcheck.TunnelPingInfo
}
PingCheckService defines the interface for ping check operations. Uses pingcheck types directly — no adapter needed.
type PingCheckSettingsDTO ¶
type PingCheckSettingsDTO struct {
Enabled bool `json:"enabled" example:"true"`
Defaults PingCheckDefaultsDTO `json:"defaults"`
}
PingCheckSettingsDTO mirrors frontend PingCheckSettings.
type PingCheckStatusData ¶
type PingCheckStatusData struct {
Enabled bool `json:"enabled" example:"true"`
Tunnels []TunnelPingStatusDTO `json:"tunnels"`
}
PingCheckStatusData mirrors frontend PingCheckStatus.
type PingCheckStatusResponse ¶
type PingCheckStatusResponse struct {
Success bool `json:"success" example:"true"`
Data PingCheckStatusData `json:"data"`
}
PingCheckStatusResponse is the envelope for GET /pingcheck/status.
type PingCheckToggleService ¶
type PingCheckToggleService interface {
StartMonitoringAllRunning()
StopMonitoringAll()
}
PingCheckToggleService defines the interface for ping check toggle operations.
type PingLogEntryDTO ¶
type PingLogEntryDTO struct {
Timestamp string `json:"timestamp" example:"2024-01-15T10:30:00Z"`
TunnelId string `json:"tunnelId" example:"tun_abc123"`
TunnelName string `json:"tunnelName" example:"My VPN"`
Success bool `json:"success" example:"true"`
Latency int `json:"latency" example:"35"`
Error string `json:"error" example:""`
FailCount int `json:"failCount" example:"0"`
Threshold int `json:"threshold" example:"3"`
StateChange string `json:"stateChange" example:""`
}
PingLogEntryDTO mirrors frontend PingLogEntry.
type PingLogsResponse ¶
type PingLogsResponse struct {
Success bool `json:"success" example:"true"`
Data []PingLogEntryDTO `json:"data"`
}
PingLogsResponse is the envelope for GET /pingcheck/logs.
type PoliciesListResponse ¶
type PoliciesListResponse struct {
Success bool `json:"success" example:"true"`
Data []PolicyOptionDTO `json:"data"`
}
PoliciesListResponse is the envelope for GET /managed-servers/policies.
type PolicyDeviceDTO ¶
type PolicyDeviceDTO struct {
MAC string `json:"mac" example:"aa:bb:cc:dd:ee:ff"`
IP string `json:"ip" example:"192.168.1.100"`
Name string `json:"name" example:"My Phone"`
Hostname string `json:"hostname" example:"my-phone"`
Active bool `json:"active" example:"true"`
Link string `json:"link" example:"WiFi"`
Policy string `json:"policy" example:"default"`
}
PolicyDeviceDTO mirrors frontend PolicyDevice.
type PolicyDevicesListResponse ¶
type PolicyDevicesListResponse struct {
Success bool `json:"success" example:"true"`
Data []PolicyDeviceDTO `json:"data"`
}
PolicyDevicesListResponse is the envelope for GET /access-policies/devices.
type PolicyGlobalInterfaceDTO ¶
type PolicyGlobalInterfaceDTO struct {
Name string `json:"name" example:"nwg0"`
Label string `json:"label" example:"My VPN"`
Up bool `json:"up" example:"true"`
}
PolicyGlobalInterfaceDTO mirrors frontend PolicyGlobalInterface.
type PolicyInterfacesListResponse ¶
type PolicyInterfacesListResponse struct {
Success bool `json:"success" example:"true"`
Data []PolicyGlobalInterfaceDTO `json:"data"`
}
PolicyInterfacesListResponse is the envelope for GET /access-policies/interfaces.
type PolicyOptionDTO ¶
type PolicyOptionDTO struct {
ID string `json:"id" example:"Policy0"`
Description string `json:"description" example:"Default policy"`
}
PolicyOptionDTO mirrors managed.PolicyOption (router IP Policy profile entry).
type PolicyOrderData ¶
type PolicyOrderData struct {
Order []string `json:"order" example:"default"`
}
PolicyOrderData reports the current HrNeo policy order.
type PolicyOrderResponse ¶
type PolicyOrderResponse struct {
Success bool `json:"success" example:"true"`
Data PolicyOrderData `json:"data"`
}
PolicyOrderResponse is the envelope for POST /hydraroute/policy-order.
type PresetsHandler ¶
type PresetsHandler struct {
// contains filtered or unexported fields
}
PresetsHandler serves the unified preset catalog (read-only in U0).
func NewPresetsHandler ¶
func NewPresetsHandler(catalog *presets.Catalog) *PresetsHandler
func (*PresetsHandler) List ¶
func (h *PresetsHandler) List(w http.ResponseWriter, r *http.Request)
List returns the merged preset catalog.
@Summary List unified presets
@Tags presets
@Produce json
@Success 200 {object} PresetsListResponse
@Router /presets [get]
type PresetsListResponse ¶
PresetsListResponse is the envelope payload for GET /presets.
type PreviewURLRequest ¶
type PreviewURLRequest struct {
URL string `json:"url" example:"https://example.com/subscriptions/demo.txt"`
Headers []SubscriptionHeader `json:"headers"`
}
PreviewURLRequest is the body for POST /api/singbox/subscriptions/preview. Read-only fetch + parse of a subscription URL without creating anything.
type ProxyConfigResponse ¶
type ProxyConfigResponse struct {
Success bool `json:"success" example:"true"`
Data DeviceProxyConfigData `json:"data"`
}
ProxyConfigResponse is the envelope for GET /proxy/config.
type ProxyInstanceResponse ¶
type ProxyInstanceResponse struct {
Success bool `json:"success" example:"true"`
Data DeviceProxyInstanceData `json:"data"`
}
ProxyInstanceResponse is the envelope for GET/PUT /proxy/instance.
type ProxyInstancesResponse ¶
type ProxyInstancesResponse struct {
Success bool `json:"success" example:"true"`
Data []DeviceProxyInstanceData `json:"data"`
}
ProxyInstancesResponse is the envelope for GET /proxy/instances.
type ProxyListenChoicesData ¶
type ProxyListenChoicesData struct {
LanIP string `json:"lanIP" example:"192.168.1.1"`
SingboxRunning bool `json:"singboxRunning" example:"true"`
}
ProxyListenChoicesData mirrors the listen-choices payload.
type ProxyListenChoicesResponse ¶
type ProxyListenChoicesResponse struct {
Success bool `json:"success" example:"true"`
Data ProxyListenChoicesData `json:"data"`
}
ProxyListenChoicesResponse is the envelope for GET /proxy/listen-choices.
type ProxyOutboundsResponse ¶
type ProxyOutboundsResponse struct {
Success bool `json:"success" example:"true"`
Data []DeviceProxyOutboundDTO `json:"data"`
}
ProxyOutboundsResponse is the envelope for GET /proxy/outbounds.
type ProxyRuntimeResponse ¶
type ProxyRuntimeResponse struct {
Success bool `json:"success" example:"true"`
Data DeviceProxyRuntimeData `json:"data"`
}
ProxyRuntimeResponse is the envelope for GET /proxy/runtime.
type RemoveInfoItemRequest ¶
type RemoveInfoItemRequest struct {
ItemID string `json:"itemId"`
}
RemoveInfoItemRequest is the body for POST .../info/remove.
type RemoveMemberRequest ¶
type RemoveMemberRequest struct {
MemberTag string `json:"memberTag" example:"sub-demo-003"`
}
RemoveMemberRequest is the body for POST /api/singbox/subscriptions/members/remove. Removing the last member tears the whole subscription down (no meaningful empty subscription); the response carries deleted=true in that case so the UI can navigate away.
type RemoveMemberResponseData ¶
type RemoveMemberResponseData struct {
Deleted bool `json:"deleted" example:"false"`
Subscription *SubscriptionDTO `json:"subscription,omitempty"`
}
RemoveMemberResponseData is the data envelope for remove-member.
type ResolveHandler ¶
type ResolveHandler struct{}
func NewResolveHandler ¶
func NewResolveHandler() *ResolveHandler
func (*ResolveHandler) Resolve ¶
func (h *ResolveHandler) Resolve(w http.ResponseWriter, r *http.Request)
Resolve performs a DNS lookup (IPv4 only) for routing search.
@Summary Resolve domain
@Tags routing
@Produce json
@Security CookieAuth
@Param domain query string true "Hostname to resolve"
@Success 200 {object} ResolveResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /routing/resolve [get]
type ResolveResponse ¶
type ResolveResponse struct {
Domain string `json:"domain"`
IPs []string `json:"ips"`
Error string `json:"error,omitempty"`
}
ResolveResponse is the JSON body for GET /api/routing/resolve.
type RestoreMembersRequest ¶
type RestoreMembersRequest struct {
MemberTags []string `json:"memberTags" example:"sub-demo-002"`
}
RestoreMembersRequest is the body for POST /api/singbox/subscriptions/members/restore.
type RestoreOptionsDTO ¶
type RestoreOptionsDTO struct {
AllowRenumber bool `json:"allowRenumber" example:"false"`
}
RestoreOptionsDTO mirrors managed.RestoreOptions on the wire. Defined in api/ so swag resolves it without crossing package boundaries.
type RestoreOutcomeDTO ¶
type RestoreOutcomeDTO struct {
Name string `json:"name" example:"Wireguard1"`
NewName string `json:"newName,omitempty" example:"Wireguard2"`
Action string `json:"action" example:"created"`
AddedPeers int `json:"addedPeers,omitempty" example:"2"`
Conflicts []string `json:"conflicts,omitempty"`
Error string `json:"error,omitempty"`
}
RestoreOutcomeDTO mirrors managed.RestoreOutcome on the wire.
type RouterDetails ¶
type RouterDetails = routerinfo.RouterDetails
RouterDetails contains extended router metadata derived from NDMS/RCI and local procfs.
type RouterInterfaceDTO ¶
type RouterInterfaceDTO struct {
Name string `json:"name" example:"br0"`
Label string `json:"label" example:"Home Network"`
Up bool `json:"up" example:"true"`
}
RouterInterfaceDTO mirrors frontend RouterInterface.
type RouterStagingStatusResponse ¶
type RouterStagingStatusResponse struct {
HasDraft bool `json:"hasDraft"`
DraftedAt *time.Time `json:"draftedAt,omitempty"`
Validation *RouterValidationDTO `json:"validation,omitempty"`
}
RouterStagingStatusResponse is the body of GET /api/singbox/router/staging. HasDraft=false means DraftedAt and Validation are absent.
type RouterStagingValidationError ¶
type RouterStagingValidationError struct {
Validation *RouterValidationDTO `json:"validation,omitempty"`
SbCheck string `json:"sbCheck,omitempty"`
}
RouterStagingValidationError is the body of 422 responses from /staging/apply. Either Validation or SbCheck is populated (exclusive).
type RouterValidationDTO ¶
type RouterValidationDTO struct {
Errors []RouterValidationErrorDTO `json:"errors"`
}
RouterValidationDTO carries a structured list of cross-slot validation errors. Used by the staging-status payload (preview) and by 422 responses from /staging/apply.
type RouterValidationErrorDTO ¶
type RouterValidationErrorDTO struct {
Slot string `json:"slot"`
Kind string `json:"kind"`
Tag string `json:"tag,omitempty"`
InRule string `json:"inRule,omitempty"`
Message string `json:"message"`
}
RouterValidationErrorDTO mirrors orchestrator.ValidationError.
type RoutingHandler ¶
type RoutingHandler struct {
// contains filtered or unexported fields
}
RoutingHandler handles routing API endpoints.
func NewRoutingHandler ¶
func NewRoutingHandler(catalog routing.Catalog, queries *ndmsquery.Queries) *RoutingHandler
NewRoutingHandler creates a new routing handler.
func (*RoutingHandler) Refresh ¶
func (h *RoutingHandler) Refresh(w http.ResponseWriter, r *http.Request)
Refresh drops every NDMS list cache that feeds the routing sections, then posts resource:invalidated hints so every routing polling store refetches on the next tick (or immediately if subscribed). Returns the Missing list from a freshly-built snapshot so the caller can tell whether the retry succeeded. POST /api/routing/refresh
@Summary Invalidate routing caches
@Tags routing
@Produce json
@Security CookieAuth
@Success 200 {object} RoutingRefreshResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /routing/refresh [post]
func (*RoutingHandler) SetEventBus ¶
func (h *RoutingHandler) SetEventBus(bus *events.Bus)
SetEventBus wires the SSE bus so refresh can rebroadcast a fresh snapshot to every connected client after invalidating NDMS caches.
func (*RoutingHandler) Tunnels ¶
func (h *RoutingHandler) Tunnels(w http.ResponseWriter, r *http.Request)
Tunnels returns available tunnels for routing dropdowns. GET /api/routing/tunnels
@Summary Routing tunnel catalog
@Tags routing
@Produce json
@Security CookieAuth
@Success 200 {array} object
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /routing/tunnels [get]
type RoutingRefreshData ¶
type RoutingRefreshData struct {
Missing []string `json:"missing" example:""`
}
RoutingRefreshData is the payload for POST /routing/refresh.
type RoutingRefreshResponse ¶
type RoutingRefreshResponse struct {
Success bool `json:"success" example:"true"`
Data RoutingRefreshData `json:"data"`
}
RoutingRefreshResponse is the envelope for POST /routing/refresh.
type RoutingTunnelDTO ¶
type RoutingTunnelDTO struct {
ID string `json:"id" example:"tun_abc123"`
Name string `json:"name" example:"My VPN"`
Iface string `json:"iface,omitempty" example:"nwg0"`
Type string `json:"type" example:"managed"`
Status string `json:"status" example:"connected"`
Available bool `json:"available" example:"true"`
}
RoutingTunnelDTO mirrors frontend RoutingTunnel.
type RoutingTunnelsResponse ¶
type RoutingTunnelsResponse struct {
Success bool `json:"success" example:"true"`
Data []RoutingTunnelDTO `json:"data"`
}
RoutingTunnelsResponse is the envelope for GET /routing/tunnels.
type SaveStatusDTO ¶
type SaveStatusDTO struct {
State string `json:"state"`
LastError string `json:"lastError,omitempty"`
LastSaveAt time.Time `json:"lastSaveAt,omitempty"`
PendingCount int `json:"pendingCount"`
}
SaveStatusDTO is the wire shape returned by GET /api/ndms/save-status. State is one of: "idle" | "pending" | "saving" | "error" | "failed". Mirrors the shape UI consumers previously read from the SSE event bus so the polling store keeps the same keys.
type ServerAddPeerRequestDTO ¶
type ServerAddPeerRequestDTO struct {
Description string `json:"description" example:"My Phone"`
TunnelIP string `json:"tunnelIP" example:"10.0.14.2/32"`
}
ServerAddPeerRequestDTO is the body for POST /servers/{name}/peers.
type ServerConfigResponse ¶
type ServerConfigResponse struct {
Success bool `json:"success" example:"true"`
Data WireguardServerConfigDTO `json:"data"`
}
ServerConfigResponse is the envelope for GET /servers/config.
type ServerSettingsDTO ¶
type ServerSettingsDTO struct {
Port int `json:"port" example:"8080"`
Interface string `json:"interface" example:""`
}
ServerSettingsDTO mirrors frontend ServerSettings.
type ServerUpdatePeerRequestDTO ¶
type ServerUpdatePeerRequestDTO struct {
Description string `json:"description" example:"My Phone"`
TunnelIP string `json:"tunnelIP" example:"10.0.14.2/32"`
}
ServerUpdatePeerRequestDTO is the body for PUT /servers/{name}/peers/{pubkey}.
type ServersAllData ¶
type ServersAllData struct {
Servers []WireguardServerDTO `json:"servers"`
ManagedStats *ManagedServerStatsDTO `json:"managedStats"`
WANIP string `json:"wanIP" example:"203.0.113.42"`
}
ServersAllData is the composite payload for GET /servers/all.
type ServersAllResponse ¶
type ServersAllResponse struct {
Success bool `json:"success" example:"true"`
Data ServersAllData `json:"data"`
}
ServersAllResponse is the envelope for GET /servers/all.
type ServersHandler ¶
type ServersHandler struct {
// contains filtered or unexported fields
}
ServersHandler handles VPN server interface operations. Frontend now polls GET /api/servers/all; this handler only emits resource:invalidated hints on mark/unmark and poller metrics ticks so subscribers refetch immediately instead of waiting for the next poll.
func NewServersHandler ¶
func NewServersHandler(queries *query.Queries, settings *storage.SettingsStore, awgStore *storage.AWGTunnelStore, appLogger logging.AppLogger) *ServersHandler
NewServersHandler creates a new servers handler.
func (*ServersHandler) AddServerPeer ¶
func (h *ServersHandler) AddServerPeer(w http.ResponseWriter, r *http.Request, name string)
AddServerPeer adds a peer to a built-in/marked WireGuard server. POST /api/servers/{name}/peers
@Summary Add server peer
@Description Generates a keypair and registers a new peer on the named WireGuard server. Returns the fresh servers snapshot.
@Tags servers
@Accept json
@Produce json
@Security CookieAuth
@Param name path string true "Interface name (e.g. Wireguard0)"
@Param body body ServerAddPeerRequestDTO true "Peer description and tunnel IP"
@Success 200 {object} ServersAllResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /servers/{name}/peers [post]
func (*ServersHandler) Config ¶
func (h *ServersHandler) Config(w http.ResponseWriter, r *http.Request)
Config returns RC configuration for .conf generation. GET /api/servers/config?name=Wireguard0
func (*ServersHandler) DeleteServerPeer ¶
func (h *ServersHandler) DeleteServerPeer(w http.ResponseWriter, r *http.Request, name, pubkey string)
DeleteServerPeer removes a peer from a WireGuard server. DELETE /api/servers/{name}/peers/{pubkey}
@Summary Delete server peer
@Description Removes the peer with the given public key from the named WireGuard server. Returns the fresh servers snapshot.
@Tags servers
@Produce json
@Security CookieAuth
@Param name path string true "Interface name (e.g. Wireguard0)"
@Param pubkey path string true "Peer public key"
@Success 200 {object} ServersAllResponse
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /servers/{name}/peers/{pubkey} [delete]
func (*ServersHandler) Get ¶
func (h *ServersHandler) Get(w http.ResponseWriter, r *http.Request)
Get returns a single server with all peers. GET /api/servers/get?name=Wireguard0
func (*ServersHandler) GetAll ¶
func (h *ServersHandler) GetAll(w http.ResponseWriter, r *http.Request)
GetAll returns the composite servers snapshot (list + managed + stats + wanIP). Replaces the snapshot:servers SSE event — the frontend polls this. GET /api/servers/all
@Summary Get all servers snapshot
@Description Returns the composite servers snapshot: WireGuard servers list, managed server, stats and WAN IP.
@Tags servers
@Produce json
@Security CookieAuth
@Success 200 {object} ServersAllResponse
@Failure 500 {object} APIErrorEnvelope
@Router /servers/all [get]
func (*ServersHandler) List ¶
func (h *ServersHandler) List(w http.ResponseWriter, r *http.Request)
List returns all server WireGuard interfaces (built-in VPN Server + user-marked). GET /api/servers
func (*ServersHandler) Mark ¶
func (h *ServersHandler) Mark(w http.ResponseWriter, r *http.Request)
Mark handles mark/unmark operations for server interfaces. POST /api/servers/mark?name=Wireguard0 — mark as server DELETE /api/servers/mark?name=Wireguard0 — unmark (return to tunnels) Both return the fresh ServersSnapshot as body.
@Summary Mark/unmark interface as server
@Description POST marks the named WG interface as a server (visible under Servers, hidden from Tunnels). DELETE unmarks (returns it to the Tunnels list). Both return the fresh ServersSnapshot.
@Tags servers
@Produce json
@Security CookieAuth
@Param name query string true "Interface name (e.g. Wireguard0)"
@Success 200 {object} ServersAllResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /servers/mark [post]
@Router /servers/mark [delete]
func (*ServersHandler) Marked ¶
func (h *ServersHandler) Marked(w http.ResponseWriter, r *http.Request)
Marked returns the list of server interface IDs. GET /api/servers/marked
@Summary Get marked server interfaces
@Description Returns the list of interface IDs that have been marked as servers.
@Tags servers
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /servers/marked [get]
func (*ServersHandler) PublishServerSnapshot ¶
func (h *ServersHandler) PublishServerSnapshot(ctx context.Context)
PublishServerSnapshot broadcasts a resource:invalidated hint. Kept as a method on *ServersHandler because ndms/metrics.Poller calls it through the ServerSnapshotPublisher interface.
func (*ServersHandler) Restart ¶
func (h *ServersHandler) Restart(w http.ResponseWriter, r *http.Request)
Restart accepts a restart/start command for a built-in/marked WireGuard server. POST /api/servers/restart?name=Wireguard0
@Summary Restart or start WireGuard server
@Description If the server interface is up, restarts it with down -> pause -> up. If it is down, starts it. The command is accepted quickly and executed in background so a client connected through this server does not cancel the operation.
@Tags servers
@Produce json
@Security CookieAuth
@Param name query string true "Interface name"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 405 {object} APIErrorEnvelope
@Router /servers/restart [post]
func (*ServersHandler) ServerPeerConf ¶
func (h *ServersHandler) ServerPeerConf(w http.ResponseWriter, r *http.Request, name, pubkey string)
ServerPeerConf returns the downloadable WireGuard .conf for a peer. GET /api/servers/{name}/peers/{pubkey}/conf
@Summary Get server peer config
@Description Generates the WireGuard client .conf for the peer. Only available when the peer's private key was created via AWG Manager and is stored locally.
@Tags servers
@Produce json
@Security CookieAuth
@Param name path string true "Interface name (e.g. Wireguard0)"
@Param pubkey path string true "Peer public key"
@Success 200 {object} map[string]string
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /servers/{name}/peers/{pubkey}/conf [get]
func (*ServersHandler) SetCommands ¶
func (h *ServersHandler) SetCommands(commands *ndmscommand.Commands)
SetCommands wires NDMS interface commands used by server up/down/restart controls. Kept as a setter so tests using NewServersHandler do not need to construct the full command registry.
func (*ServersHandler) SetEnabled ¶
func (h *ServersHandler) SetEnabled(w http.ResponseWriter, r *http.Request)
SetEnabled enables or disables a built-in/marked WireGuard server interface. POST /api/servers/enabled?name=Wireguard0
@Summary Toggle WireGuard server enabled state
@Description Brings a built-in or marked WireGuard server interface up or down.
@Tags servers
@Accept json
@Produce json
@Security CookieAuth
@Param name query string true "Interface name"
@Param body body serverEnabledRequest true "Enabled flag"
@Success 200 {object} ServersAllResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 405 {object} APIErrorEnvelope
@Router /servers/enabled [post]
func (*ServersHandler) SetEndpoint ¶
func (h *ServersHandler) SetEndpoint(w http.ResponseWriter, r *http.Request, name string)
SetEndpoint stores the connect host used in generated client .conf files. POST /api/servers/{name}/endpoint
@Summary Set server client endpoint host
@Description Stores the IP or domain embedded in generated client configs. Empty clears the override and falls back to WAN IP. Returns the fresh servers snapshot.
@Tags servers
@Accept json
@Produce json
@Security CookieAuth
@Param name path string true "Interface name (e.g. Wireguard0)"
@Param body body SetServerEndpointRequest true "Endpoint host"
@Success 200 {object} ServersAllResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /servers/{name}/endpoint [post]
func (*ServersHandler) SetEventBus ¶
func (h *ServersHandler) SetEventBus(bus *events.Bus)
SetEventBus sets the event bus used for SSE publishing.
func (*ServersHandler) SetManagedHandler ¶
func (h *ServersHandler) SetManagedHandler(m *ManagedServerHandler)
SetManagedHandler sets the managed server handler for shared publishing.
func (*ServersHandler) SetManagedService ¶
func (h *ServersHandler) SetManagedService(svc *managed.Service)
SetManagedService wires managed.Service for system-server NAT/policy RCI.
func (*ServersHandler) SetNAT ¶
func (h *ServersHandler) SetNAT(w http.ResponseWriter, r *http.Request, name string)
SetNAT sets the NAT mode on a built-in/marked WireGuard server. POST /api/servers/{name}/nat
@Summary Set server NAT mode
@Description Sets the NAT mode (full / internet-only / none) on the named WireGuard server via NDMS. Returns the fresh servers snapshot.
@Tags servers
@Accept json
@Produce json
@Security CookieAuth
@Param name path string true "Interface name (e.g. Wireguard0)"
@Param body body SetNATModeRequest true "NAT mode"
@Success 200 {object} ServersAllResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /servers/{name}/nat [post]
func (*ServersHandler) SetPolicy ¶
func (h *ServersHandler) SetPolicy(w http.ResponseWriter, r *http.Request, name string)
SetPolicy sets the ip hotspot policy on a built-in/marked WireGuard server. POST /api/servers/{name}/policy
@Summary Set server access policy
@Description Binds the named WireGuard server interface to an NDMS hotspot access policy (or "none"). Returns the fresh servers snapshot.
@Tags servers
@Accept json
@Produce json
@Security CookieAuth
@Param name path string true "Interface name (e.g. Wireguard0)"
@Param body body SetServerPolicyRequest true "Policy id (router-side) or 'none'"
@Success 200 {object} ServersAllResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /servers/{name}/policy [post]
func (*ServersHandler) Subtree ¶
func (h *ServersHandler) Subtree(w http.ResponseWriter, r *http.Request)
Subtree dispatches /api/servers/{name}/... operations.
func (*ServersHandler) ToggleServerPeer ¶
func (h *ServersHandler) ToggleServerPeer(w http.ResponseWriter, r *http.Request, name, pubkey string)
ToggleServerPeer enables or disables a peer. POST /api/servers/{name}/peers/{pubkey}/toggle
@Summary Toggle server peer
@Description Enables or disables (connect on/off) the peer on the named WireGuard server. Returns the fresh servers snapshot.
@Tags servers
@Accept json
@Produce json
@Security CookieAuth
@Param name path string true "Interface name (e.g. Wireguard0)"
@Param pubkey path string true "Peer public key"
@Param body body EnabledToggleRequest true "Enabled flag"
@Success 200 {object} ServersAllResponse
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /servers/{name}/peers/{pubkey}/toggle [post]
func (*ServersHandler) UpdateServerPeer ¶
func (h *ServersHandler) UpdateServerPeer(w http.ResponseWriter, r *http.Request, name, pubkey string)
UpdateServerPeer updates a peer's tunnel IP and/or description. PUT /api/servers/{name}/peers/{pubkey}
@Summary Update server peer
@Description Changes a peer's allowed-IP and/or description on the named WireGuard server. Returns the fresh servers snapshot.
@Tags servers
@Accept json
@Produce json
@Security CookieAuth
@Param name path string true "Interface name (e.g. Wireguard0)"
@Param pubkey path string true "Peer public key"
@Param body body ServerUpdatePeerRequestDTO true "New description and tunnel IP"
@Success 200 {object} ServersAllResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /servers/{name}/peers/{pubkey} [put]
func (*ServersHandler) WANIP ¶
func (h *ServersHandler) WANIP(w http.ResponseWriter, r *http.Request)
WANIP returns the external WAN IP for .conf generation. GET /api/servers/wan-ip
@Summary Get WAN IP
@Description Returns the router's external WAN IP address.
@Tags servers
@Produce json
@Security CookieAuth
@Success 200 {object} WANIPResponse
@Failure 500 {object} APIErrorEnvelope
@Router /servers/wan-ip [get]
type SetDescriptionRequest ¶
type SetDescriptionRequest struct {
Name string `json:"name" example:"Policy0"`
Description string `json:"description" example:"My VPN policy"`
}
SetDescriptionRequest is the body for POST /access-policies/description.
type SetInterfaceUpRequest ¶
type SetInterfaceUpRequest struct {
Name string `json:"name" example:"Wireguard0"`
Up bool `json:"up" example:"true"`
}
SetInterfaceUpRequest is the body for POST /access-policies/interface-up.
type SetLANSegmentsRequest ¶
type SetLANSegmentsRequest struct {
Segments []string `json:"segments"`
}
SetLANSegmentsRequest is the body for POST /managed-servers/{id}/lan-segments.
type SetNATModeRequest ¶
type SetNATModeRequest struct {
Mode string `json:"mode,omitempty" example:"internet-only" enums:"full,internet-only,none"`
Enabled *bool `json:"enabled,omitempty" example:"true"` // backward-compat: если mode пуст
}
SetNATModeRequest is the body for POST /managed-servers/{id}/nat.
type SetPolicyOrderRequest ¶
type SetPolicyOrderRequest struct {
Order []string `json:"order" example:"default"`
}
SetPolicyOrderRequest is the body for POST /hydraroute/policy-order.
type SetServerEndpointRequest ¶
type SetServerEndpointRequest struct {
Endpoint string `json:"endpoint" example:"203.0.113.42"`
}
SetServerEndpointRequest is the body for POST /servers/{name}/endpoint.
type SetServerPolicyRequest ¶
type SetServerPolicyRequest struct {
Policy string `json:"policy" example:"Policy0"`
}
SetServerPolicyRequest is the body for POST /managed-servers/{id}/policy.
type SetStandaloneRequest ¶
type SetStandaloneRequest struct {
Name string `json:"name" example:"Policy0"`
Enabled bool `json:"enabled" example:"true"`
}
SetStandaloneRequest is the body for POST /access-policies/standalone.
type SettingsData ¶
type SettingsData struct {
SchemaVersion int `json:"schemaVersion" example:"16"`
AuthEnabled bool `json:"authEnabled" example:"false"`
Server ServerSettingsDTO `json:"server"`
PingCheck PingCheckSettingsDTO `json:"pingCheck"`
Logging LoggingSettingsDTO `json:"logging"`
MonitoringExcludedTunnels []string `json:"monitoringExcludedTunnels,omitempty" example:"tn-1,sys-2"`
DisableMemorySaving bool `json:"disableMemorySaving" example:"false"`
Updates UpdateSettingsDTO `json:"updates"`
Download DownloadSettingsDTO `json:"download"`
DnsRoute DNSRouteSettingsDTO `json:"dnsRoute"`
GeoFile GeoFileSettingsDTO `json:"geoFile"`
ConnectivityCheckURL string `json:"connectivityCheckUrl" example:"http://connectivitycheck.gstatic.com/generate_204"`
// UsageLevel controls which UI sections are visible to the user.
// Filtering is frontend-only — the API does not enforce it.
// enums: expert,advanced,basic
// First enum is the prism mock default (prism picks the first
// enum value over the example tag); putting `expert` first means
// dev:mock surfaces all advanced UI without manual toggling.
UsageLevel string `json:"usageLevel" example:"expert" enums:"expert,advanced,basic"`
}
SettingsData is the payload for GET /settings/get.
type SettingsHandler ¶
type SettingsHandler struct {
// contains filtered or unexported fields
}
SettingsHandler handles settings API endpoints.
func NewSettingsHandler ¶
func NewSettingsHandler(store *storage.SettingsStore, appLogger logging.AppLogger) *SettingsHandler
NewSettingsHandler creates a new settings handler.
func (*SettingsHandler) Get ¶
func (h *SettingsHandler) Get(w http.ResponseWriter, r *http.Request)
Get returns current settings.
@Summary Get settings
@Description Returns the full Settings object (server, pingCheck, logging, dnsRoute, managed, apiKey, ...).
@Tags settings
@Produce json
@Security CookieAuth
@Success 200 {object} SettingsResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /settings/get [get]
func (*SettingsHandler) RegenerateApiKey ¶
func (h *SettingsHandler) RegenerateApiKey(w http.ResponseWriter, r *http.Request)
RegenerateApiKey generates a fresh UUID v4 server-side, persists it into Settings.ApiKey, and returns the updated Settings. Lives on the backend (not in browser via crypto.randomUUID) because the UI is served over plain HTTP and the WebCrypto API is unavailable in non-secure contexts.
@Summary Regenerate API key
@Description Generates a fresh UUID v4 via crypto/rand, stores it into Settings.ApiKey, and returns the updated Settings. The new key takes effect immediately as a `Authorization: Bearer <key>` substitute for the session cookie.
@Tags settings
@Produce json
@Security CookieAuth
@Success 200 {object} SettingsResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /settings/regenerate-api-key [post]
func (*SettingsHandler) SetApplyLoggingSettings ¶
func (h *SettingsHandler) SetApplyLoggingSettings(fn func())
SetApplyLoggingSettings sets the callback that re-applies logging settings to the live buffers (MaxAge, MaxEntries) after a successful settings update. Called once per Update with no arguments — the callback re-reads the settings store itself.
func (*SettingsHandler) SetApplySingboxLogSettings ¶
func (h *SettingsHandler) SetApplySingboxLogSettings(fn func() error)
SetApplySingboxLogSettings sets callback that re-applies sing-box log-level into 00-base.json and triggers orchestrator-driven reload.
func (*SettingsHandler) SetDownloadService ¶
func (h *SettingsHandler) SetDownloadService(svc *downloader.Service)
func (*SettingsHandler) SetEventBus ¶
func (h *SettingsHandler) SetEventBus(bus *events.Bus)
SetEventBus wires the SSE bus so settings mutations broadcast a resource:invalidated hint to all connected clients.
func (*SettingsHandler) SetLogsSnapshot ¶
func (h *SettingsHandler) SetLogsSnapshot(fn func())
SetLogsSnapshot sets the function that publishes a logs snapshot.
func (*SettingsHandler) SetMonitoringService ¶
func (h *SettingsHandler) SetMonitoringService(svc MonitoringRefreshService)
SetMonitoringService sets the monitoring service for forced snapshot refresh after settings changes that affect matrix composition.
func (*SettingsHandler) SetPingCheckService ¶
func (h *SettingsHandler) SetPingCheckService(svc PingCheckToggleService)
SetPingCheckService sets the ping check service for toggle operations.
func (*SettingsHandler) SetPingCheckSnapshot ¶
func (h *SettingsHandler) SetPingCheckSnapshot(fn func())
SetPingCheckSnapshot sets the function that publishes a pingcheck snapshot.
func (*SettingsHandler) SetTunnelStore ¶
func (h *SettingsHandler) SetTunnelStore(tunnels *storage.AWGTunnelStore)
SetTunnelStore sets the tunnel store for ping check toggle logic.
func (*SettingsHandler) Update ¶
func (h *SettingsHandler) Update(w http.ResponseWriter, r *http.Request)
Update saves settings.
@Summary Update settings
@Description Persists Settings via patch semantics: any field omitted from the payload is preserved, including top-level bool flags. Send only the fields you want to change, or send the full Settings object to update everything atomically. ApiKey preserved when omitted (rotate via /settings/regenerate-api-key).
@Tags settings
@Accept json
@Produce json
@Security CookieAuth
@Param body body SettingsData true "Settings patch — any subset of fields"
@Success 200 {object} SettingsResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /settings/update [post]
type SettingsProvider ¶
SettingsProvider provides access to settings.
type SettingsResponse ¶
type SettingsResponse struct {
Success bool `json:"success" example:"true"`
Data SettingsData `json:"data"`
}
SettingsResponse is the envelope for GET /settings/get.
type SignatureCaptureData ¶
type SignatureCaptureData struct {
OK bool `json:"ok" example:"true"`
Source string `json:"source" example:"Wireguard0"`
Packets SignaturePacketsDTO `json:"packets"`
Warning string `json:"warning,omitempty" example:""`
}
SignatureCaptureData mirrors frontend SignatureCaptureResult.
type SignatureCaptureResponse ¶
type SignatureCaptureResponse struct {
Success bool `json:"success" example:"true"`
Data SignatureCaptureData `json:"data"`
}
SignatureCaptureResponse is the envelope for GET /signature/capture.
type SignatureHandler ¶
type SignatureHandler struct{}
func NewSignatureHandler ¶
func NewSignatureHandler() *SignatureHandler
func (*SignatureHandler) Capture ¶
func (h *SignatureHandler) Capture(w http.ResponseWriter, r *http.Request)
Capture runs TLS certificate capture for a domain.
@Summary Signature capture
@Tags signature
@Produce json
@Security CookieAuth
@Param domain query string true "Domain name"
@Success 200 {object} SignatureCaptureResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /signature/capture [get]
type SignaturePacketsDTO ¶
type SignaturePacketsDTO struct {
I1 string `json:"i1" example:"0a1b2c3d"`
I2 string `json:"i2" example:"4e5f6a7b"`
I3 string `json:"i3" example:"8c9d0e1f"`
I4 string `json:"i4" example:"2a3b4c5d"`
I5 string `json:"i5" example:"6e7f8a9b"`
}
SignaturePacketsDTO is the packets field in SignatureCaptureResult.
type SingboxConfigHandler ¶
type SingboxConfigHandler struct {
// contains filtered or unexported fields
}
SingboxConfigHandler exposes a read-only preview of the merged sing-box configuration. The orchestrator's ConfigDir is injected via configDirFn so tests can swap a tmp dir without dragging in the orchestrator.
func NewSingboxConfigHandler ¶
func NewSingboxConfigHandler(configDirFn func() string) *SingboxConfigHandler
NewSingboxConfigHandler constructs the handler.
func (*SingboxConfigHandler) Preview ¶
func (h *SingboxConfigHandler) Preview(w http.ResponseWriter, r *http.Request)
Preview returns the read-only merged sing-box configuration.
@Summary Get merged sing-box configuration preview
@Description Returns the read-only pretty-printed JSON that sing-box loads when started with `-C config.d/` — every active slot file concatenated in lexicographic order, with arrays merged and tag collisions surfaced as errors.
@Tags singbox
@Produce json
@Security CookieAuth
@Success 200 {object} OkResponse{data=SingboxConfigPreviewResponse}
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/config-preview [get]
type SingboxConfigPreviewResponse ¶
type SingboxConfigPreviewResponse struct {
JSON string `json:"json"`
}
SingboxConfigPreviewResponse is the typed payload of GET /api/singbox/config-preview. The JSON field is a pretty-printed merge of every active config.d/*.json — exactly what sing-box loads when started with `-C config.d/`.
type SingboxConnectionsClientsData ¶
SingboxConnectionsClientsData mirrors frontend ClientsByIP map.
type SingboxConnectionsClientsResponse ¶
type SingboxConnectionsClientsResponse struct {
Success bool `json:"success" example:"true"`
Data SingboxConnectionsClientsData `json:"data"`
}
SingboxConnectionsClientsResponse is the envelope for GET /singbox/connections/clients.
type SingboxConnectionsHandler ¶
type SingboxConnectionsHandler struct {
// contains filtered or unexported fields
}
SingboxConnectionsHandler serves the narrow IP→display-name lookup used by the Connections monitor sub-tab to enrich Clash connection rows.
func NewSingboxConnectionsHandler ¶
func NewSingboxConnectionsHandler(hotspot HotspotLister) *SingboxConnectionsHandler
NewSingboxConnectionsHandler builds the handler. hotspot may be nil during partial bootstrap — handler responds 503 until wired.
func (*SingboxConnectionsHandler) Clients ¶
func (h *SingboxConnectionsHandler) Clients(w http.ResponseWriter, r *http.Request)
Clients returns IP→display-name from the NDMS hotspot cache.
@Summary IP → display-name map for sing-box connections
@Description Returns the current NDMS hotspot mapping of source IPs to device display names. Cached upstream (TTL 30s). On any error returns 200 with an empty map (best-effort) so the UI keeps working with raw IPs.
@Tags singbox
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxConnectionsClientsResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 503 {object} APIErrorEnvelope
@Router /singbox/connections/clients [get]
type SingboxControlRequest ¶
type SingboxControlRequest struct {
Action string `json:"action" example:"start" enums:"start,stop,restart"`
}
SingboxControlRequest is the body for POST /singbox/control.
type SingboxDNSGlobalsData ¶
type SingboxDNSGlobalsData struct {
Final string `json:"final" example:"cloudflare"`
Strategy string `json:"strategy" example:"prefer_ipv4"`
}
SingboxDNSGlobalsData carries the global DNS settings exposed by GET/PUT /singbox/router/dns/globals. Reused as the request body type.
type SingboxDNSGlobalsResponse ¶
type SingboxDNSGlobalsResponse struct {
Success bool `json:"success" example:"true"`
Data SingboxDNSGlobalsData `json:"data"`
}
SingboxDNSGlobalsResponse is the envelope for GET/PUT /singbox/router/dns/globals.
type SingboxDNSRewriteDTO ¶
type SingboxDNSRewriteDTO struct {
Pattern string `json:"pattern" example:"finland10*.discord.media"`
IPs []string `json:"ips" example:"104.25.158.178"`
}
SingboxDNSRewriteDTO mirrors dnsrewrite.DNSRewrite — a glob domain pattern rewritten to one or more IPs.
type SingboxDNSRewriteDeleteRequest ¶
type SingboxDNSRewriteDeleteRequest struct {
Index int `json:"index" example:"0"`
}
SingboxDNSRewriteDeleteRequest is the body for POST /singbox/router/dns/rewrites/delete.
type SingboxDNSRewriteMoveRequest ¶
type SingboxDNSRewriteMoveRequest struct {
From int `json:"from" example:"3"`
To int `json:"to" example:"0"`
}
SingboxDNSRewriteMoveRequest is the body for POST /singbox/router/dns/rewrites/move.
type SingboxDNSRewriteUpdateRequest ¶
type SingboxDNSRewriteUpdateRequest struct {
Index int `json:"index" example:"0"`
Rewrite SingboxDNSRewriteDTO `json:"rewrite"`
}
SingboxDNSRewriteUpdateRequest is the body for POST /singbox/router/dns/rewrites/update.
type SingboxDNSRewritesListResponse ¶
type SingboxDNSRewritesListResponse struct {
Success bool `json:"success" example:"true"`
Data []SingboxDNSRewriteDTO `json:"data"`
}
SingboxDNSRewritesListResponse is the envelope for GET /singbox/router/dns/rewrites/list.
type SingboxDNSRuleDTO ¶
type SingboxDNSRuleDTO struct {
RuleSet []string `json:"rule_set,omitempty" example:"geosite-cn"`
DomainSuffix []string `json:"domain_suffix,omitempty" example:".example.com"`
Domain []string `json:"domain,omitempty" example:"example.com"`
DomainKeyword []string `json:"domain_keyword,omitempty" example:"google"`
QueryType []string `json:"query_type,omitempty" example:"A"`
Server string `json:"server,omitempty" example:"cloudflare"`
Action string `json:"action,omitempty" example:"route"`
}
SingboxDNSRuleDTO mirrors router.DNSRule.
type SingboxDNSRuleDeleteRequest ¶
type SingboxDNSRuleDeleteRequest struct {
Index int `json:"index" example:"0"`
}
SingboxDNSRuleDeleteRequest is the body for POST /singbox/router/dns/rules/delete.
type SingboxDNSRuleMoveRequest ¶
type SingboxDNSRuleMoveRequest struct {
From int `json:"from" example:"3"`
To int `json:"to" example:"0"`
}
SingboxDNSRuleMoveRequest is the body for POST /singbox/router/dns/rules/move.
type SingboxDNSRuleUpdateRequest ¶
type SingboxDNSRuleUpdateRequest struct {
Index int `json:"index" example:"0"`
Rule SingboxDNSRuleDTO `json:"rule"`
}
SingboxDNSRuleUpdateRequest is the body for POST /singbox/router/dns/rules/update.
type SingboxDNSRulesListResponse ¶
type SingboxDNSRulesListResponse struct {
Success bool `json:"success" example:"true"`
Data []SingboxDNSRuleDTO `json:"data"`
}
SingboxDNSRulesListResponse is the envelope for GET /singbox/router/dns/rules/list.
type SingboxDNSServerDTO ¶
type SingboxDNSServerDTO struct {
Tag string `json:"tag" example:"cloudflare"`
Type string `json:"type" example:"udp"`
Server string `json:"server" example:"1.1.1.1"`
ServerPort int `json:"server_port,omitempty" example:"53"`
Path string `json:"path,omitempty" example:"/dns-query"`
Detour string `json:"detour,omitempty" example:"direct"`
Strategy string `json:"domain_strategy,omitempty" example:"prefer_ipv4"`
DomainResolver *SingboxDomainResolverDTO `json:"domain_resolver,omitempty"`
}
SingboxDNSServerDTO mirrors router.DNSServer.
type SingboxDNSServerDeleteRequest ¶
type SingboxDNSServerDeleteRequest struct {
Tag string `json:"tag" example:"cloudflare"`
Force bool `json:"force" example:"false"`
}
SingboxDNSServerDeleteRequest is the body for POST /singbox/router/dns/servers/delete. force=true overrides the "still referenced by a rule" guard.
type SingboxDNSServerMoveRequest ¶
type SingboxDNSServerMoveRequest struct {
From int `json:"from" example:"3"`
To int `json:"to" example:"0"`
}
SingboxDNSServerMoveRequest is the body for POST /singbox/router/dns/servers/move.
type SingboxDNSServerUpdateRequest ¶
type SingboxDNSServerUpdateRequest struct {
Tag string `json:"tag" example:"cloudflare"`
Server SingboxDNSServerDTO `json:"server"`
}
SingboxDNSServerUpdateRequest is the body for POST /singbox/router/dns/servers/update.
type SingboxDNSServersListResponse ¶
type SingboxDNSServersListResponse struct {
Success bool `json:"success" example:"true"`
Data []SingboxDNSServerDTO `json:"data"`
}
SingboxDNSServersListResponse is the envelope for GET /singbox/router/dns/servers/list.
type SingboxDomainResolverDTO ¶
type SingboxDomainResolverDTO struct {
Server string `json:"server,omitempty" example:"local"`
Strategy string `json:"strategy,omitempty" example:"ipv4_only"`
}
SingboxDomainResolverDTO mirrors router.DomainResolver, the optional nested resolver descriptor on a DNS server.
type SingboxFakeIPConfigHandler ¶
type SingboxFakeIPConfigHandler struct {
// contains filtered or unexported fields
}
SingboxFakeIPConfigHandler exposes the FakeIPConfigService CRUD surface (SlotFakeIP) as REST endpoints under /api/singbox/fakeip/config/... It is a pure mechanical mirror of SingboxRouterHandler: same DTO shapes, same error mapping, same nil-array guards, different path prefix and FakeIP-prefixed service calls.
func NewSingboxFakeIPConfigHandler ¶
func NewSingboxFakeIPConfigHandler(svc router.FakeIPConfigService, appLogger logging.AppLogger) *SingboxFakeIPConfigHandler
NewSingboxFakeIPConfigHandler constructs a handler backed by svc. appLogger may be nil — the scoped logger is nil-safe.
func (*SingboxFakeIPConfigHandler) AddDNSRule ¶
func (h *SingboxFakeIPConfigHandler) AddDNSRule(w http.ResponseWriter, r *http.Request)
AddDNSRule appends a new DNS routing rule to the fakeip-tun slot.
@Summary Add fakeip-config DNS rule
@Description Appends a new DNS routing rule. The rule's server tag must already exist (fakeip-tun slot).
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSRuleDTO true "DNS routing rule"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/dns/rules/add [post]
func (*SingboxFakeIPConfigHandler) AddDNSServer ¶
func (h *SingboxFakeIPConfigHandler) AddDNSServer(w http.ResponseWriter, r *http.Request)
AddDNSServer registers a new DNS upstream in the fakeip-tun slot.
@Summary Add fakeip-config DNS server
@Description Registers a new DNS upstream (tag must be unique) in the fakeip-tun slot.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSServerDTO true "DNS server descriptor"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/dns/servers/add [post]
func (*SingboxFakeIPConfigHandler) AddOutbound ¶
func (h *SingboxFakeIPConfigHandler) AddOutbound(w http.ResponseWriter, r *http.Request)
AddOutbound creates a new composite outbound in the fakeip-tun slot.
@Summary Add fakeip-config outbound
@Description Creates a new composite outbound in the fakeip-tun slot.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterOutboundDTO true "Composite outbound payload"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/outbounds/add [post]
func (*SingboxFakeIPConfigHandler) AddRule ¶
func (h *SingboxFakeIPConfigHandler) AddRule(w http.ResponseWriter, r *http.Request)
AddRule appends a new routing rule to the fakeip-tun slot.
@Summary Add fakeip-config route rule
@Description Appends a new routing rule to the fakeip-tun slot.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterRuleDTO true "Routing rule payload"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/rules/add [post]
func (*SingboxFakeIPConfigHandler) AddRuleSet ¶
func (h *SingboxFakeIPConfigHandler) AddRuleSet(w http.ResponseWriter, r *http.Request)
AddRuleSet registers a new ruleset in the fakeip-tun slot.
@Summary Add fakeip-config ruleset
@Description Registers a new ruleset in the fakeip-tun slot.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterRuleSetDTO true "RuleSet payload"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/rulesets/add [post]
func (*SingboxFakeIPConfigHandler) DeleteDNSRule ¶
func (h *SingboxFakeIPConfigHandler) DeleteDNSRule(w http.ResponseWriter, r *http.Request)
DeleteDNSRule removes the DNS rule at the given index (fakeip-tun slot).
@Summary Delete fakeip-config DNS rule
@Description Removes the DNS rule at the given index (0-based priority slot) from the fakeip-tun slot.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSRuleDeleteRequest true "Index of the rule to remove"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/dns/rules/delete [post]
func (*SingboxFakeIPConfigHandler) DeleteDNSServer ¶
func (h *SingboxFakeIPConfigHandler) DeleteDNSServer(w http.ResponseWriter, r *http.Request)
DeleteDNSServer removes the DNS upstream identified by tag from the fakeip-tun slot.
@Summary Delete fakeip-config DNS server
@Description Removes the DNS upstream identified by tag. Engine-locked servers ("real", fakeip-type) are rejected with 400. Pass force=true to bypass the reference guard.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSServerDeleteRequest true "Tag + optional force flag"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 409 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/dns/servers/delete [post]
func (*SingboxFakeIPConfigHandler) DeleteOutbound ¶
func (h *SingboxFakeIPConfigHandler) DeleteOutbound(w http.ResponseWriter, r *http.Request)
DeleteOutbound removes the composite outbound identified by tag (fakeip-tun slot).
@Summary Delete fakeip-config outbound
@Description Removes the composite outbound identified by tag from the fakeip-tun slot.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterOutboundDeleteRequest true "Tag + optional force flag"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 409 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/outbounds/delete [post]
func (*SingboxFakeIPConfigHandler) DeleteRule ¶
func (h *SingboxFakeIPConfigHandler) DeleteRule(w http.ResponseWriter, r *http.Request)
DeleteRule removes the route rule at the given index (fakeip-tun slot).
@Summary Delete fakeip-config route rule
@Description Removes the route rule at the given index (0-based) from the fakeip-tun slot.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterRuleDeleteRequest true "Index of the rule to remove"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/rules/delete [post]
func (*SingboxFakeIPConfigHandler) DeleteRuleSet ¶
func (h *SingboxFakeIPConfigHandler) DeleteRuleSet(w http.ResponseWriter, r *http.Request)
DeleteRuleSet removes the ruleset identified by tag from the fakeip-tun slot.
@Summary Delete fakeip-config ruleset
@Description Removes the ruleset identified by tag from the fakeip-tun slot. Refuses if referenced; pass force=true to override.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterRuleSetDeleteRequest true "Tag + optional force flag"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 409 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/rulesets/delete [post]
func (*SingboxFakeIPConfigHandler) GetDNSGlobals ¶
func (h *SingboxFakeIPConfigHandler) GetDNSGlobals(w http.ResponseWriter, r *http.Request)
GetDNSGlobals returns the global DNS final/strategy fields (fakeip-tun slot).
@Summary Get fakeip-config DNS globals
@Description Returns the global DNS settings (final, strategy) for the fakeip-tun slot.
@Tags singbox-fakeip
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxDNSGlobalsResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/dns/globals [get]
func (*SingboxFakeIPConfigHandler) ListDNSRules ¶
func (h *SingboxFakeIPConfigHandler) ListDNSRules(w http.ResponseWriter, r *http.Request)
ListDNSRules returns all DNS routing rules in priority order (fakeip-tun slot).
@Summary List fakeip-config DNS rules
@Description Returns all DNS routing rules in priority (top-first) order for the fakeip-tun slot. Always a JSON array, never null.
@Tags singbox-fakeip
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxDNSRulesListResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/dns/rules/list [get]
func (*SingboxFakeIPConfigHandler) ListDNSServers ¶
func (h *SingboxFakeIPConfigHandler) ListDNSServers(w http.ResponseWriter, r *http.Request)
ListDNSServers returns all configured DNS servers in the fakeip-tun slot.
@Summary List fakeip-config DNS servers
@Description Returns all configured DNS upstreams for the fakeip-tun slot. Always a JSON array, never null.
@Tags singbox-fakeip
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxDNSServersListResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/dns/servers/list [get]
func (*SingboxFakeIPConfigHandler) ListOutbounds ¶
func (h *SingboxFakeIPConfigHandler) ListOutbounds(w http.ResponseWriter, r *http.Request)
ListOutbounds returns all composite outbounds in the fakeip-tun slot.
@Summary List fakeip-config outbounds
@Description Returns all composite outbounds (selectors/urltests) in the fakeip-tun slot.
@Tags singbox-fakeip
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxRouterOutboundsListResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/outbounds/list [get]
func (*SingboxFakeIPConfigHandler) ListRuleSets ¶
func (h *SingboxFakeIPConfigHandler) ListRuleSets(w http.ResponseWriter, r *http.Request)
ListRuleSets returns all configured rulesets in the fakeip-tun slot.
@Summary List fakeip-config rulesets
@Description Returns all configured rulesets in the fakeip-tun slot.
@Tags singbox-fakeip
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxRouterRuleSetsListResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/rulesets/list [get]
func (*SingboxFakeIPConfigHandler) ListRules ¶
func (h *SingboxFakeIPConfigHandler) ListRules(w http.ResponseWriter, r *http.Request)
ListRules returns all routing rules in priority order (fakeip-tun slot).
@Summary List fakeip-config route rules
@Description Returns all routing rules in priority (top-first) order for the fakeip-tun slot.
@Tags singbox-fakeip
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxRouterRulesListResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/rules/list [get]
func (*SingboxFakeIPConfigHandler) MoveDNSRule ¶
func (h *SingboxFakeIPConfigHandler) MoveDNSRule(w http.ResponseWriter, r *http.Request)
MoveDNSRule moves a DNS rule from one priority slot to another (fakeip-tun slot).
@Summary Move fakeip-config DNS rule
@Description Moves the DNS rule from index `from` to index `to` (both 0-based) in the fakeip-tun slot.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSRuleMoveRequest true "From-index and to-index"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/dns/rules/move [post]
func (*SingboxFakeIPConfigHandler) MoveDNSServer ¶
func (h *SingboxFakeIPConfigHandler) MoveDNSServer(w http.ResponseWriter, r *http.Request)
MoveDNSServer reorders a DNS server from one slot to another.
@Summary Move fakeip-config DNS server
@Description Moves the DNS server from index `from` to index `to` (both 0-based) in the fakeip-tun slot.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSServerMoveRequest true "From-index and to-index"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/dns/servers/move [post]
func (*SingboxFakeIPConfigHandler) MoveRule ¶
func (h *SingboxFakeIPConfigHandler) MoveRule(w http.ResponseWriter, r *http.Request)
MoveRule moves a route rule from one priority slot to another (fakeip-tun slot).
@Summary Move fakeip-config route rule
@Description Moves the route rule from index `from` to index `to` (both 0-based) in the fakeip-tun slot.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterRuleMoveRequest true "From-index and to-index"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/rules/move [post]
func (*SingboxFakeIPConfigHandler) PutDNSGlobals ¶
func (h *SingboxFakeIPConfigHandler) PutDNSGlobals(w http.ResponseWriter, r *http.Request)
PutDNSGlobals persists global DNS final/strategy fields (fakeip-tun slot).
@Summary Update fakeip-config DNS globals
@Description Persists the global DNS settings (final, strategy) for the fakeip-tun slot.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSGlobalsData true "final + strategy"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/dns/globals [post]
@Router /singbox/fakeip/config/dns/globals [put]
func (*SingboxFakeIPConfigHandler) SetRouteFinal ¶
func (h *SingboxFakeIPConfigHandler) SetRouteFinal(w http.ResponseWriter, r *http.Request)
SetRouteFinal sets route.final on the fakeip-tun slot.
@Summary Set fakeip-config route.final
@Description Sets route.final on the fakeip-tun slot. The tag must reference a known outbound.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterRouteFinalRequest true "New final outbound tag"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/route/final [post]
func (*SingboxFakeIPConfigHandler) UpdateDNSRule ¶
func (h *SingboxFakeIPConfigHandler) UpdateDNSRule(w http.ResponseWriter, r *http.Request)
UpdateDNSRule replaces the DNS rule at the given index (fakeip-tun slot).
@Summary Update fakeip-config DNS rule
@Description Replaces the DNS rule at the given index (0-based priority slot) in the fakeip-tun slot.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSRuleUpdateRequest true "Index + replacement rule"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/dns/rules/update [post]
func (*SingboxFakeIPConfigHandler) UpdateDNSServer ¶
func (h *SingboxFakeIPConfigHandler) UpdateDNSServer(w http.ResponseWriter, r *http.Request)
UpdateDNSServer replaces the DNS upstream identified by tag in the fakeip-tun slot.
@Summary Update fakeip-config DNS server
@Description Replaces the DNS upstream identified by tag with the provided one (fakeip-tun slot).
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSServerUpdateRequest true "Tag + replacement server"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/dns/servers/update [post]
func (*SingboxFakeIPConfigHandler) UpdateOutbound ¶
func (h *SingboxFakeIPConfigHandler) UpdateOutbound(w http.ResponseWriter, r *http.Request)
UpdateOutbound replaces the composite outbound identified by tag (fakeip-tun slot).
@Summary Update fakeip-config outbound
@Description Replaces the composite outbound identified by tag in the fakeip-tun slot.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterOutboundUpdateRequest true "Tag + replacement outbound"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/outbounds/update [post]
func (*SingboxFakeIPConfigHandler) UpdateRule ¶
func (h *SingboxFakeIPConfigHandler) UpdateRule(w http.ResponseWriter, r *http.Request)
UpdateRule replaces a route rule at the given index (fakeip-tun slot).
@Summary Update fakeip-config route rule
@Description Replaces the route rule at index with the provided one (fakeip-tun slot).
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterRuleUpdateRequest true "Index + replacement rule"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/rules/update [post]
func (*SingboxFakeIPConfigHandler) UpdateRuleSet ¶
func (h *SingboxFakeIPConfigHandler) UpdateRuleSet(w http.ResponseWriter, r *http.Request)
UpdateRuleSet replaces the ruleset identified by tag in the fakeip-tun slot.
@Summary Update fakeip-config ruleset
@Description Replaces the ruleset identified by tag in the fakeip-tun slot.
@Tags singbox-fakeip
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterRuleSetUpdateRequest true "Tag + new RuleSet payload"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/fakeip/config/rulesets/update [post]
type SingboxHandler ¶
type SingboxHandler struct {
// contains filtered or unexported fields
}
SingboxHandler serves /api/singbox/* routes.
func NewSingboxHandler ¶
func NewSingboxHandler(op *singbox.Operator, bus *events.Bus, dc *singbox.DelayChecker, ts *testing.Service, appLogger ...logging.AppLogger) *SingboxHandler
NewSingboxHandler creates a new singbox handler.
func (*SingboxHandler) AddTunnels ¶
func (h *SingboxHandler) AddTunnels(w http.ResponseWriter, r *http.Request)
AddTunnels handles POST /api/singbox/tunnels. Body: {"links": "vless://...\nhy2://..."}. Returns imported tunnels and per-line errors.
@Summary Add sing-box tunnel(s)
@Tags singbox
@Accept json
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/tunnels [post]
func (*SingboxHandler) CheckConnectivity ¶
func (h *SingboxHandler) CheckConnectivity(w http.ResponseWriter, r *http.Request)
CheckConnectivity performs connectivity test through a sing-box tunnel.
@Summary Sing-box tunnel connectivity test
@Description Tests connectivity through a sing-box tunnel. Provide either `tag` (resolved to tunnel kernel interface) or `iface` (direct kernel interface override, useful for subscription tests).
@Tags singbox
@Produce json
@Security CookieAuth
@Param tag query string false "Tunnel tag (required when iface is not set)"
@Param iface query string false "Kernel interface override (e.g. t2s12)"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/tunnels/test/connectivity [get]
func (*SingboxHandler) CheckIP ¶
func (h *SingboxHandler) CheckIP(w http.ResponseWriter, r *http.Request)
CheckIP tests IP through a sing-box tunnel.
@Summary Sing-box tunnel IP test
@Description Resolves current external IP through a sing-box tunnel. Provide either `tag` (resolved to tunnel kernel interface) or `iface` (direct kernel interface override, useful for subscription tests). Optional `service` overrides IP-check endpoint.
@Tags singbox
@Produce json
@Security CookieAuth
@Param tag query string false "Tunnel tag (required when iface is not set)"
@Param iface query string false "Kernel interface override (e.g. t2s12)"
@Param service query string false "Custom IP-check service URL"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/tunnels/test/ip [get]
func (*SingboxHandler) Control ¶
func (h *SingboxHandler) Control(w http.ResponseWriter, r *http.Request)
Control handles POST /api/singbox/control. Body: {"action": "start"|"stop"|"restart"}. Returns the fresh status so the client can update its cache. Mirrors the shape of /api/system/hydraroute-control.
@Summary Control sing-box process
@Description Starts, stops, or restarts the sing-box engine. Returns the fresh status snapshot. Mirrors /system/hydraroute-control.
@Tags singbox
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxControlRequest true "Action to perform"
@Success 200 {object} SingboxStatusResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/control [post]
func (*SingboxHandler) DelayCheck ¶
func (h *SingboxHandler) DelayCheck(w http.ResponseWriter, r *http.Request)
DelayCheck handles POST /api/singbox/tunnels/delay-check?tag=X.
@Summary Sing-box delay check
@Tags singbox
@Produce json
@Security CookieAuth
@Param tag query string true "Tunnel tag"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/tunnels/delay-check [post]
func (*SingboxHandler) DeleteTunnel ¶
func (h *SingboxHandler) DeleteTunnel(w http.ResponseWriter, r *http.Request)
DeleteTunnel handles DELETE /api/singbox/tunnels?tag={tag}.
@Summary Delete sing-box tunnel
@Tags singbox
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/tunnels [delete]
func (*SingboxHandler) ExportShareLink ¶
func (h *SingboxHandler) ExportShareLink(w http.ResponseWriter, r *http.Request)
ExportShareLink handles POST /api/singbox/tunnels/share-link. Body: {"outbound":{...},"label":"optional fragment"}.
@Summary Export sing-box tunnel as share-link
@Tags singbox
@Accept json
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/tunnels/share-link [post]
func (*SingboxHandler) GetTunnel ¶
func (h *SingboxHandler) GetTunnel(w http.ResponseWriter, r *http.Request)
GetTunnel handles GET /api/singbox/tunnels?tag={tag}.
func (*SingboxHandler) Install ¶
func (h *SingboxHandler) Install(w http.ResponseWriter, r *http.Request)
Install handles POST /api/singbox/install. Returns the fresh status so the client can update cache without refetch. Also publishes a resource:invalidated hint so other tabs/subscribers refresh.
@Summary Install sing-box
@Tags singbox
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/install [post]
func (*SingboxHandler) ListTunnels ¶
func (h *SingboxHandler) ListTunnels(w http.ResponseWriter, r *http.Request)
ListTunnels handles GET /api/singbox/tunnels. Returns all tunnels enriched with per-tunnel connectivity from the Clash API.
func (*SingboxHandler) RenameTunnel ¶
func (h *SingboxHandler) RenameTunnel(w http.ResponseWriter, r *http.Request)
RenameTunnel handles PATCH /api/singbox/tunnels/rename. Body: {"oldTag":"old","newTag":"new"}.
func (*SingboxHandler) ServeGETTunnels ¶
func (h *SingboxHandler) ServeGETTunnels(w http.ResponseWriter, r *http.Request)
ServeGETTunnels handles GET /api/singbox/tunnels: list all tunnels, or single tunnel when query tag is set.
@Summary List or get sing-box tunnel(s)
@Tags singbox
@Produce json
@Security CookieAuth
@Param tag query string false "When set, returns single tunnel"
@Success 200 {object} SingboxTunnelsResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/tunnels [get]
func (*SingboxHandler) SetNDMSProxyMigrator ¶
func (h *SingboxHandler) SetNDMSProxyMigrator(m *singbox.Migrator, settings ndmsProxyToggler)
SetNDMSProxyMigrator подключает мигратор и getter настроек после конструкции (избегаем circular construction между SettingsStore и SingboxHandler). Без них endpoint ToggleNDMSProxy возвращает 500.
func (*SingboxHandler) SetOutboundRefCheckers ¶
func (h *SingboxHandler) SetOutboundRefCheckers(dp tunnelservice.DeviceProxyRefChecker, r tunnelservice.RouterRefChecker)
SetOutboundRefCheckers wires device-proxy and router reference guards for sing-box tunnel deletion (refuse when tag is still in a composite/rule).
func (*SingboxHandler) SetSettingsStore ¶
func (h *SingboxHandler) SetSettingsStore(settings *storage.SettingsStore)
SetSettingsStore wires global settings for connectivity checks.
func (*SingboxHandler) SpeedTestStream ¶
func (h *SingboxHandler) SpeedTestStream(w http.ResponseWriter, r *http.Request)
SpeedTestStream handles GET /api/singbox/tunnels/test/speed/stream?tag=X&server=Y&port=Z. Runs download then upload sequentially, keyed by sing-box tunnel tag. Streams events via SSE: phase, interval, result, done, error.
Optional `iface` query param overrides the tag→interface resolution (subscription cards use it to test the composite NDMS Proxy interface directly). When NDMS Proxy is globally disabled the override is rejected with 412 PROXY_DISABLED — the t2sN/ProxyN composite interface no longer exists, so iperf against it would silently fail or hang.
@Summary Sing-box tunnel speed test stream
@Tags singbox
@Produce text/event-stream
@Security CookieAuth
@Param tag query string true "Sing-box outbound tag"
@Param server query string true "iperf3 server host"
@Param port query int true "iperf3 server port"
@Param iface query string false "Kernel interface override (NDMS Proxy must be enabled)"
@Success 200 {string} string "SSE stream"
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope "Tunnel tag not found"
@Failure 412 {object} APIErrorEnvelope "NDMS Proxy disabled — iface override unavailable"
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/tunnels/test/speed/stream [get]
func (*SingboxHandler) Status ¶
func (h *SingboxHandler) Status(w http.ResponseWriter, r *http.Request)
Status handles GET /api/singbox/status.
@Summary Sing-box status
@Tags singbox
@Description Available when sing-box integration is enabled in the build.
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxStatusResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/status [get]
func (*SingboxHandler) ToggleNDMSProxy ¶
func (h *SingboxHandler) ToggleNDMSProxy(w http.ResponseWriter, r *http.Request)
ToggleNDMSProxy handles POST /api/singbox/ndms-proxy. Переключает создание NDMS Proxy интерфейсов для sing-box туннелей. Idempotent: повторный вызов с тем же значением — 200 OK без миграции. 412 при enabled=true если NDMS-компонент 'proxy' не установлен.
@Summary Toggle NDMS Proxy creation for sing-box tunnels
@Tags singbox
@Accept json
@Produce json
@Security CookieAuth
@Param body body ToggleNDMSProxyRequest true "Toggle value"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 412 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/ndms-proxy [post]
func (*SingboxHandler) Update ¶
func (h *SingboxHandler) Update(w http.ResponseWriter, r *http.Request)
Update handles POST /api/singbox/update. Replaces the installed managed sing-box binary with the version this awg-manager build is pinned to. No-op when versions match. Returns the fresh status so the client can clear its update prompt without a separate refetch.
@Summary Update managed sing-box binary
@Description Replaces the currently-installed managed sing-box with the version this awg-manager build is pinned to. No-op when versions match.
@Tags singbox
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxStatusResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/update [post]
func (*SingboxHandler) UpdateTunnel ¶
func (h *SingboxHandler) UpdateTunnel(w http.ResponseWriter, r *http.Request)
UpdateTunnel handles PUT /api/singbox/tunnels?tag={tag}. Body: {"outbound": {...}}.
@Summary Update sing-box tunnel
@Tags singbox
@Accept json
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/tunnels [put]
type SingboxPresenceProbe ¶
type SingboxPresenceProbe interface {
IsPresent() bool
}
SingboxPresenceProbe reports whether the managed sing-box binary is available on disk. Subscriptions register an NDMS Proxy interface pointing at sing-box's inbound listener, so creating one without sing-box installed leaves the Proxy slot pointing at nothing.
type SingboxProxiesHandler ¶
type SingboxProxiesHandler struct {
// contains filtered or unexported fields
}
SingboxProxiesHandler exposes runtime controls for sing-box composite outbounds by relaying typed requests to the upstream Clash API.
Dependencies are injected as functions so tests can swap them for httptest fakes:
- clashBaseURL → returns the URL prefix to call (e.g. "http://127.0.0.1:9090") — same target the existing ClashProxy uses.
- knownComposites → returns the set of composite tags we own (computed from 20-router.json). The List response is filtered to this set so Clash builtins (DIRECT, GLOBAL, etc.) and member outbounds don't leak into the UI.
func NewSingboxProxiesHandler ¶
func NewSingboxProxiesHandler(clashBaseURL func() string, knownComposites func() map[string]struct{}, httpClient *http.Client) *SingboxProxiesHandler
NewSingboxProxiesHandler constructs the handler. httpClient may be nil; in production callers pass an http.Client tuned for the local loopback (short timeout, no keepalive).
func (*SingboxProxiesHandler) List ¶
func (h *SingboxProxiesHandler) List(w http.ResponseWriter, r *http.Request)
List godoc
@Summary List sing-box composite proxy groups with live state
@Description Returns selector/urltest/loadbalance groups managed by this router with their currently active member and per-member last latency. Filtered to groups defined in 20-router.json — Clash builtins (DIRECT, GLOBAL, REJECT) are excluded.
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} OkResponse{data=SingboxProxiesListResponse}
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/proxies/list [get]
func (*SingboxProxiesHandler) Select ¶
func (h *SingboxProxiesHandler) Select(w http.ResponseWriter, r *http.Request)
Select godoc
@Summary Switch active member of a sing-box selector group
@Description Sets the active member of a Clash-managed `selector` outbound. URLTest / loadbalance groups are read-only and return 400.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxProxiesSelectRequest true "Group and member tags"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 405 {object} APIErrorEnvelope
@Failure 502 {object} APIErrorEnvelope
@Router /singbox/router/proxies/select [post]
func (*SingboxProxiesHandler) Test ¶
func (h *SingboxProxiesHandler) Test(w http.ResponseWriter, r *http.Request)
Test godoc
@Summary Force latency test for all members of a composite group
@Description Calls Clash `/group/<name>/delay`, returning the per-member delay map. Members that timed out come back with 0.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxProxiesTestRequest true "Group and optional URL/timeout"
@Success 200 {object} OkResponse{data=SingboxProxiesTestResponse}
@Failure 400 {object} APIErrorEnvelope
@Failure 405 {object} APIErrorEnvelope
@Failure 502 {object} APIErrorEnvelope
@Router /singbox/router/proxies/test [post]
type SingboxProxiesListResponse ¶
type SingboxProxiesListResponse struct {
Groups []SingboxProxyGroup `json:"groups"`
}
SingboxProxiesListResponse is the envelope payload for GET /list.
type SingboxProxiesSelectRequest ¶
type SingboxProxiesSelectRequest struct {
Group string `json:"group" example:"veesp-fast"`
Member string `json:"member" example:"vless-1"`
}
SingboxProxiesSelectRequest is the body for POST /select.
type SingboxProxiesTestRequest ¶
type SingboxProxiesTestRequest struct {
Group string `json:"group"`
URL string `json:"url,omitempty"`
Timeout int `json:"timeout,omitempty"`
}
SingboxProxiesTestRequest is the body for POST /test.
type SingboxProxiesTestResponse ¶
SingboxProxiesTestResponse — memberTag → delay (ms); 0 = unreachable.
type SingboxProxyGroup ¶
type SingboxProxyGroup struct {
Tag string `json:"tag"`
Type string `json:"type"`
Now string `json:"now"`
Members []SingboxProxyMember `json:"members"`
}
SingboxProxyGroup is one composite outbound (selector / urltest / loadbalance) with its current state.
type SingboxProxyMember ¶
type SingboxProxyMember struct {
Tag string `json:"tag"`
Type string `json:"type"`
LastDelay int `json:"lastDelay,omitempty"`
}
SingboxProxyMember is one member outbound surfaced to the UI for a composite group. LastDelay is sourced from Clash's history[] tail; 0 means "no test recorded" or "last test failed" — UI treats both the same.
type SingboxRouterApplyPresetRequest ¶
type SingboxRouterApplyPresetRequest struct {
ID string `json:"id" example:"china-direct"`
Outbound string `json:"outbound" example:"awg-vpn0"`
}
SingboxRouterApplyPresetRequest is the body for POST /singbox/router/presets/apply.
type SingboxRouterBindDeviceRequest ¶
type SingboxRouterBindDeviceRequest struct {
MAC string `json:"mac" example:"aa:bb:cc:dd:ee:ff"`
PolicyName string `json:"policyName" example:"Policy0"`
}
SingboxRouterBindDeviceRequest is the body for POST /singbox/router/policy-devices/bind.
type SingboxRouterCreatePolicyRequest ¶
type SingboxRouterCreatePolicyRequest struct {
Description string `json:"description" example:"My VPN policy"`
}
SingboxRouterCreatePolicyRequest is the body for POST /singbox/router/policies.
type SingboxRouterDatRuleSetURLData ¶
type SingboxRouterDatRuleSetURLData struct {
URL string `json:"url" example:"http://127.0.0.1:2222/api/singbox/router/rulesets/dat-srs?kind=geosite&tag=GOOGLE&token=..."`
}
SingboxRouterDatRuleSetURLData is the payload for GET /singbox/router/rulesets/dat-url.
type SingboxRouterDatRuleSetURLResponse ¶
type SingboxRouterDatRuleSetURLResponse struct {
Success bool `json:"success" example:"true"`
Data SingboxRouterDatRuleSetURLData `json:"data"`
}
SingboxRouterDatRuleSetURLResponse is the envelope for dat rule-set URL metadata.
type SingboxRouterHandler ¶
type SingboxRouterHandler struct {
// contains filtered or unexported fields
}
func NewSingboxRouterHandler ¶
func NewSingboxRouterHandler(svc router.Service, appLogger logging.AppLogger) *SingboxRouterHandler
func (*SingboxRouterHandler) AddDNSRule ¶
func (h *SingboxRouterHandler) AddDNSRule(w http.ResponseWriter, r *http.Request)
AddDNSRule appends a new DNS routing rule.
@Summary Add singbox-router DNS rule
@Description Appends a new DNS routing rule. The rule's server tag must already exist.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSRuleDTO true "DNS routing rule"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/rules/add [post]
func (*SingboxRouterHandler) AddDNSServer ¶
func (h *SingboxRouterHandler) AddDNSServer(w http.ResponseWriter, r *http.Request)
AddDNSServer registers a new DNS upstream.
@Summary Add singbox-router DNS server
@Description Registers a new DNS upstream (tag must be unique).
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSServerDTO true "DNS server descriptor"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/servers/add [post]
func (*SingboxRouterHandler) AddOutbound ¶
func (h *SingboxRouterHandler) AddOutbound(w http.ResponseWriter, r *http.Request)
AddOutbound creates a new composite outbound.
@Summary Add singbox-router outbound
@Description Creates a new composite outbound. The base outbounds it references must already exist.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterOutboundDTO true "Composite outbound payload"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/outbounds/add [post]
func (*SingboxRouterHandler) AddRule ¶
func (h *SingboxRouterHandler) AddRule(w http.ResponseWriter, r *http.Request)
AddRule appends a new singbox-router routing rule.
@Summary Add singbox-router rule
@Description Appends a new routing rule. Rule conditions reference rulesets/outbounds that must already exist.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterRuleDTO true "Routing rule payload"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/rules/add [post]
func (*SingboxRouterHandler) AddRuleSet ¶
func (h *SingboxRouterHandler) AddRuleSet(w http.ResponseWriter, r *http.Request)
AddRuleSet registers a new ruleset (downloads if remote).
@Summary Add singbox-router ruleset
@Description Registers a new ruleset. For remote rulesets the file is downloaded synchronously.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterRuleSetDTO true "RuleSet payload"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/rulesets/add [post]
func (*SingboxRouterHandler) ApplyPreset ¶
func (h *SingboxRouterHandler) ApplyPreset(w http.ResponseWriter, r *http.Request)
ApplyPreset materialises the named preset against the chosen outbound.
@Summary Apply singbox-router preset
@Description Materialises the preset (id) into rules + rulesets, routing matched traffic via the selected outbound. Existing rules with the same tag are overwritten.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterApplyPresetRequest true "Preset id + target outbound"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/presets/apply [post]
func (*SingboxRouterHandler) BindDevice ¶
func (h *SingboxRouterHandler) BindDevice(w http.ResponseWriter, r *http.Request)
BindDevice handles POST /api/singbox/router/policy-devices/bind
@Summary Bind device to singbox-router policy
@Description Binds the LAN device (MAC) to the named policy. Replaces any existing binding.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterBindDeviceRequest true "Device MAC + target policy name"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/policy-devices/bind [post]
func (*SingboxRouterHandler) DatRuleSetSRS ¶
func (h *SingboxRouterHandler) DatRuleSetSRS(w http.ResponseWriter, r *http.Request)
DatRuleSetSRS serves a compiled .srs artifact for sing-box. It is intentionally not protected by session cookies because sing-box fetches it as a plain remote rule_set URL; access is controlled by the token in the URL.
func (*SingboxRouterHandler) DatRuleSetURL ¶
func (h *SingboxRouterHandler) DatRuleSetURL(w http.ResponseWriter, r *http.Request)
DatRuleSetURL returns the local tokenized URL that sing-box can fetch directly.
@Summary Build dat→SRS rule-set URL
@Tags singbox-router
@Produce json
@Security CookieAuth
@Param kind query string true "geosite or geoip"
@Param tag query []string true "Geo tag(s)"
@Success 200 {object} SingboxRouterDatRuleSetURLResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/rulesets/dat-url [get]
func (*SingboxRouterHandler) DeleteDNSRule ¶
func (h *SingboxRouterHandler) DeleteDNSRule(w http.ResponseWriter, r *http.Request)
DeleteDNSRule removes the DNS rule at the given index.
@Summary Delete singbox-router DNS rule
@Description Removes the DNS rule at the given index (0-based priority slot).
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSRuleDeleteRequest true "Index of the rule to remove"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/rules/delete [post]
func (*SingboxRouterHandler) DeleteDNSServer ¶
func (h *SingboxRouterHandler) DeleteDNSServer(w http.ResponseWriter, r *http.Request)
DeleteDNSServer removes the DNS upstream identified by tag.
@Summary Delete singbox-router DNS server
@Description Removes the DNS upstream identified by tag. Refuses if any DNS rule references it; pass force=true to override.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSServerDeleteRequest true "Tag + optional force flag"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 409 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/servers/delete [post]
func (*SingboxRouterHandler) DeleteOutbound ¶
func (h *SingboxRouterHandler) DeleteOutbound(w http.ResponseWriter, r *http.Request)
DeleteOutbound removes the composite outbound identified by tag.
@Summary Delete singbox-router outbound
@Description Removes the composite outbound identified by tag. Refuses if any rule references it; pass force=true to override.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterOutboundDeleteRequest true "Tag + optional force flag"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 409 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/outbounds/delete [post]
func (*SingboxRouterHandler) DeleteRule ¶
func (h *SingboxRouterHandler) DeleteRule(w http.ResponseWriter, r *http.Request)
DeleteRule removes the rule at the given index.
@Summary Delete singbox-router rule
@Description Removes the rule at the given index (0-based priority slot).
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterRuleDeleteRequest true "Index of the rule to remove"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/rules/delete [post]
func (*SingboxRouterHandler) DeleteRuleSet ¶
func (h *SingboxRouterHandler) DeleteRuleSet(w http.ResponseWriter, r *http.Request)
DeleteRuleSet removes the ruleset identified by tag.
@Summary Delete singbox-router ruleset
@Description Removes the ruleset identified by tag. Refuses if any rule references it; pass force=true to remove this rule_set tag from referencing route and DNS rules.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterRuleSetDeleteRequest true "Tag + optional force flag"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 409 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/rulesets/delete [post]
func (*SingboxRouterHandler) Disable ¶
func (h *SingboxRouterHandler) Disable(w http.ResponseWriter, r *http.Request)
Disable stops the singbox-router engine and uninstalls iptables/policy rules.
@Summary Disable singbox-router
@Description Stops the singbox-router engine and uninstalls iptables/policy rules. Idempotent.
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} OkResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/disable [post]
func (*SingboxRouterHandler) Enable ¶
func (h *SingboxRouterHandler) Enable(w http.ResponseWriter, r *http.Request)
Enable starts the singbox-router engine and installs iptables/policy rules.
@Summary Enable singbox-router
@Description Starts the singbox-router engine and installs iptables/policy rules. Returns 400 with code POLICY_NOT_CONFIGURED or POLICY_MISSING when the router policy mode is incomplete. Returns 503 SINGBOX_NOT_READY when sing-box did not become ready within the boot-wait window — iptables install is deliberately skipped to avoid orphaning DNS:53 redirects (issue #221).
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Failure 503 {object} APIErrorEnvelope "sing-box did not come up in time"
@Router /singbox/router/enable [post]
func (*SingboxRouterHandler) GetDNSGlobals ¶
func (h *SingboxRouterHandler) GetDNSGlobals(w http.ResponseWriter, r *http.Request)
GetDNSGlobals returns the global DNS final/strategy fields.
@Summary Get singbox-router DNS globals
@Description Returns the global DNS settings: `final` (default server tag) and `strategy` (ipv4_only / prefer_ipv4 / etc.).
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxDNSGlobalsResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/globals [get]
func (*SingboxRouterHandler) GetSettings ¶
func (h *SingboxRouterHandler) GetSettings(w http.ResponseWriter, r *http.Request)
GetSettings reads singbox-router settings (policy-mode, defaults, etc.).
@Summary Get singbox-router settings
@Description Reads the current singbox-router settings (policy mode, defaults, ...).
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxRouterSettingsResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/settings [get]
func (*SingboxRouterHandler) GetStaging ¶
func (h *SingboxRouterHandler) GetStaging(w http.ResponseWriter, r *http.Request)
GetStaging returns the current draft state for the router slot.
@Summary Get router staging status
@Description Returns whether a pending draft exists for the router slot and, if so, its draft timestamp and a preview of the cross-slot validation result.
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} RouterStagingStatusResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/staging [get]
func (*SingboxRouterHandler) GetStatus ¶
func (h *SingboxRouterHandler) GetStatus(w http.ResponseWriter, r *http.Request)
GetStatus returns the current sing-box router engine status.
@Summary Get sing-box router status
@Description Returns the singbox-router status snapshot (running, mode, policy/iptables state, rule/ruleset/outbound counts).
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxRouterStatusResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/status [get]
func (*SingboxRouterHandler) Inspect ¶
func (h *SingboxRouterHandler) Inspect(w http.ResponseWriter, r *http.Request)
Inspect simulates which router rule would match the given domain/IP.
@Summary Inspect router routing decision
@Description Simulates which router rule would match the given domain or IP, returning the would-be outbound. Matchers are evaluated in Go; rule_set matchers are additionally checked via sing-box rule-set match when the binary and rule-set files are available. If unavailable, rule_set degrades to no-match with an explanatory note.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterInspectRequest true "Domain or IP to test, plus optional port/protocol"
@Success 200 {object} SingboxRouterInspectResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/inspect [post]
func (*SingboxRouterHandler) InspectDNS ¶
func (h *SingboxRouterHandler) InspectDNS(w http.ResponseWriter, r *http.Request)
InspectDNS simulates which DNS rule would match the given domain and how the resolved DNS server classifies the resolution (fakeip/real/local).
@Summary Inspect DNS-resolution decision
@Description Simulates the DNS-resolution branch of the inspector: which dns.rule matches the domain, which DNS server answers, and whether the domain gets a fake-ip from a pool (→ tunnel), a real upstream IP, or a local (router) resolution. Mirrors the route inspector but over dns.rules. rule_set matchers are checked via sing-box rule-set match when available.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterInspectDNSRequest true "Domain to test, plus optional query type and source IP"
@Success 200 {object} SingboxRouterInspectDNSResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/inspect-dns [post]
func (*SingboxRouterHandler) InspectStream ¶
func (h *SingboxRouterHandler) InspectStream(w http.ResponseWriter, r *http.Request)
InspectStream streams route-inspector progress events via SSE.
Event names:
- progress
- result
- inspect-error
Each SSE event `data` is a JSON object matching SingboxRouterInspectStreamEventDTO.
@Summary Inspect router routing decision (SSE stream)
@Description Streams route-inspector progress via Server-Sent Events. Event names: progress, result, inspect-error. Data payload for each event is JSON shaped as SingboxRouterInspectStreamEventDTO.
@Tags singbox-router
@Produce text/event-stream
@Security CookieAuth
@Param domain query string true "Domain or IP to test"
@Param port query int false "Destination port, 0-65535"
@Param protocol query string false "Protocol (tcp/udp)"
@Success 200 {object} SingboxRouterInspectStreamEventDTO "SSE event data payload"
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/inspect/stream [get]
func (*SingboxRouterHandler) ListBindableInterfaces ¶
func (h *SingboxRouterHandler) ListBindableInterfaces(w http.ResponseWriter, r *http.Request)
ListBindableInterfaces returns interfaces a user can bind a direct outbound to.
@Summary List bindable interfaces for direct outbounds
@Description Returns router interfaces (minus our own and AWG/WG auto-covered) that a direct outbound can bind to. Fields id and priority are not populated for this endpoint (only name, label, up are meaningful).
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxRouterWANInterfacesListResponse
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/bindable-interfaces [get]
func (*SingboxRouterHandler) ListDNSRules ¶
func (h *SingboxRouterHandler) ListDNSRules(w http.ResponseWriter, r *http.Request)
ListDNSRules returns all DNS routing rules in priority order.
@Summary List singbox-router DNS rules
@Description Returns all DNS routing rules in priority (top-first) order. Always a JSON array, never null.
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxDNSRulesListResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/rules/list [get]
func (*SingboxRouterHandler) ListDNSServers ¶
func (h *SingboxRouterHandler) ListDNSServers(w http.ResponseWriter, r *http.Request)
ListDNSServers returns all configured DNS servers.
@Summary List singbox-router DNS servers
@Description Returns all configured DNS upstreams (tag, address, type, ...). Always a JSON array, never null.
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxDNSServersListResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/servers/list [get]
func (*SingboxRouterHandler) ListIngressEligibleInterfaces ¶
func (h *SingboxRouterHandler) ListIngressEligibleInterfaces(w http.ResponseWriter, r *http.Request)
ListIngressEligibleInterfaces returns interfaces eligible for sing-box ingress-scope.
@Summary List ingress-eligible interfaces
@Description Returns router interfaces eligible for sing-box ingress-scope (bindable minus WAN minus LAN bridges). Used by the ingress multiselect in singbox-router settings.
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxRouterWANInterfacesListResponse
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/ingress-eligible-interfaces [get]
func (*SingboxRouterHandler) ListOutbounds ¶
func (h *SingboxRouterHandler) ListOutbounds(w http.ResponseWriter, r *http.Request)
ListOutbounds returns all composite outbounds.
@Summary List singbox-router outbounds
@Description Returns all composite outbounds (sing-box selectors/urltests over multiple base outbounds).
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxRouterOutboundsListResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/outbounds/list [get]
func (*SingboxRouterHandler) ListPolicyDevices ¶
func (h *SingboxRouterHandler) ListPolicyDevices(w http.ResponseWriter, r *http.Request)
ListPolicyDevices handles GET /api/singbox/router/policy-devices?name=X
@Summary List singbox-router policy devices
@Description Returns the LAN devices currently bound to the named policy. Always a JSON array, never null.
@Tags singbox-router
@Produce json
@Security CookieAuth
@Param name query string true "Policy name"
@Success 200 {object} SingboxRouterPolicyDevicesListResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/policy-devices [get]
func (*SingboxRouterHandler) ListPresets ¶
func (h *SingboxRouterHandler) ListPresets(w http.ResponseWriter, r *http.Request)
ListPresets returns the catalog of built-in singbox-router presets.
@Summary List singbox-router presets
@Description Returns the catalog of built-in presets the user can apply (each preset = a curated bundle of rules + rulesets).
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxRouterPresetsListResponse
@Failure 405 {object} APIErrorEnvelope
@Router /singbox/router/presets/list [get]
func (*SingboxRouterHandler) ListRuleSets ¶
func (h *SingboxRouterHandler) ListRuleSets(w http.ResponseWriter, r *http.Request)
ListRuleSets returns all configured rulesets.
@Summary List singbox-router rulesets
@Description Returns all configured rulesets (downloaded geo files / inline lists), with their tag, type, and freshness metadata.
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxRouterRuleSetsListResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/rulesets/list [get]
func (*SingboxRouterHandler) ListRules ¶
func (h *SingboxRouterHandler) ListRules(w http.ResponseWriter, r *http.Request)
ListRules returns all singbox-router routing rules in priority order.
@Summary List singbox-router rules
@Description Returns all routing rules in priority (top-first) order.
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxRouterRulesListResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/rules/list [get]
func (*SingboxRouterHandler) ListWANInterfaces ¶
func (h *SingboxRouterHandler) ListWANInterfaces(w http.ResponseWriter, r *http.Request)
ListWANInterfaces returns all router WAN interfaces for the WAN-binding picker. No up/down filtering — the UI shows every interface and the user picks.
@Summary List WAN interfaces
@Description Returns all router WAN interfaces (no up/down filtering) used by the WAN-binding picker in singbox-router settings. Always a JSON array, never null. The `name` field is the kernel system-name and is the value that should be persisted into `wanInterface`.
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} SingboxRouterWANInterfacesListResponse
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/wan-interfaces [get]
func (*SingboxRouterHandler) MoveDNSRule ¶
func (h *SingboxRouterHandler) MoveDNSRule(w http.ResponseWriter, r *http.Request)
MoveDNSRule moves a DNS rule from one priority slot to another.
@Summary Move singbox-router DNS rule
@Description Moves the DNS rule from index `from` to index `to` (both 0-based).
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSRuleMoveRequest true "From-index and to-index"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/rules/move [post]
func (*SingboxRouterHandler) MoveDNSServer ¶
func (h *SingboxRouterHandler) MoveDNSServer(w http.ResponseWriter, r *http.Request)
MoveDNSServer reorders a DNS server from one slot to another.
@Summary Move singbox-router DNS server
@Description Moves the DNS server from index `from` to index `to` (both 0-based). Server order is cosmetic — sing-box references servers by tag; this exists only for UX-consistent reordering.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSServerMoveRequest true "From-index and to-index"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/servers/move [post]
func (*SingboxRouterHandler) MoveRule ¶
func (h *SingboxRouterHandler) MoveRule(w http.ResponseWriter, r *http.Request)
MoveRule moves the rule from one priority slot to another.
@Summary Move singbox-router rule
@Description Moves the rule from index `from` to index `to` (both 0-based). Adjusts other rules' indices accordingly.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterRuleMoveRequest true "From-index and to-index"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/rules/move [post]
func (*SingboxRouterHandler) PoliciesCollection ¶
func (h *SingboxRouterHandler) PoliciesCollection(w http.ResponseWriter, r *http.Request)
PoliciesCollection routes by HTTP method:
GET → ListPolicies (returns []router.PolicyInfo)
POST → CreatePolicy (body: {description}, returns router.PolicyInfo)
func (*SingboxRouterHandler) PostStagingApply ¶
func (h *SingboxRouterHandler) PostStagingApply(w http.ResponseWriter, r *http.Request)
PostStagingApply commits the pending draft.
@Summary Apply router staging draft
@Description Validates the pending draft (cross-slot + sing-box check) then atomically swaps pending → active and arms a reload.
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} OkResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 409 {object} APIErrorEnvelope "no draft to apply"
@Failure 422 {object} RouterStagingValidationError
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/staging/apply [post]
func (*SingboxRouterHandler) PostStagingDiscard ¶
func (h *SingboxRouterHandler) PostStagingDiscard(w http.ResponseWriter, r *http.Request)
PostStagingDiscard removes the pending draft.
@Summary Discard router staging draft
@Description Removes pending/20-router.json. Idempotent.
@Tags singbox-router
@Produce json
@Security CookieAuth
@Success 200 {object} OkResponse
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/staging/discard [post]
func (*SingboxRouterHandler) PutDNSGlobals ¶
func (h *SingboxRouterHandler) PutDNSGlobals(w http.ResponseWriter, r *http.Request)
PutDNSGlobals persists global DNS final/strategy fields.
@Summary Update singbox-router DNS globals
@Description Persists the global DNS settings: `final` (default server tag) and `strategy` (ipv4_only / prefer_ipv4 / etc.).
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSGlobalsData true "final + strategy"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/globals [post]
@Router /singbox/router/dns/globals [put]
func (*SingboxRouterHandler) PutSettings ¶
func (h *SingboxRouterHandler) PutSettings(w http.ResponseWriter, r *http.Request)
PutSettings persists singbox-router settings.
@Summary Update singbox-router settings
@Description Persists singbox-router settings. The router is restarted only when fields that affect the running config change.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterSettingsData true "Singbox-router settings payload"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/settings [post]
@Router /singbox/router/settings [put]
func (*SingboxRouterHandler) SetOutboundRefCheckers ¶
func (h *SingboxRouterHandler) SetOutboundRefCheckers(dp tunnelservice.DeviceProxyRefChecker, r tunnelservice.RouterRefChecker)
SetOutboundRefCheckers wires device-proxy and router reference guards for composite-outbound deletion (refuse 409 when the tag is still selected by a device-proxy instance).
func (*SingboxRouterHandler) SetRouteFinal ¶
func (h *SingboxRouterHandler) SetRouteFinal(w http.ResponseWriter, r *http.Request)
SetRouteFinal updates route.final.
@Summary Set route.final outbound
@Description Updates the route.final fallback outbound. Use "direct" for default sing-box direct, or the tag of any existing outbound (composite, AWG, sing-box tunnel).
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterRouteFinalRequest true "New final outbound tag"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/route/final [post]
func (*SingboxRouterHandler) SwitchMode ¶
func (h *SingboxRouterHandler) SwitchMode(w http.ResponseWriter, r *http.Request)
SwitchMode orchestrates a routing-mode transition (off↔tproxy↔fakeip-tun) with directional fail-closed rollback. Progress is reported out-of-band as "singbox-router:transition" events on the existing events SSE stream (GET /events) — no new stream endpoint.
@Summary Switch singbox-router routing mode
@Description Orchestrates a routing-mode transition (off↔tproxy↔fakeip-tun): tears down the old mode then brings up the new one, with directional fail-closed rollback. Per-step progress is published as "singbox-router:transition" events on the existing GET /events SSE stream (see SingboxRouterTransitionData). Returns 400 INVALID_MODE for an unknown mode.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterModeRequest true "Target routing mode"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/mode [post]
func (*SingboxRouterHandler) UnbindDevice ¶
func (h *SingboxRouterHandler) UnbindDevice(w http.ResponseWriter, r *http.Request)
UnbindDevice handles POST /api/singbox/router/policy-devices/unbind
@Summary Unbind device from singbox-router policy
@Description Removes any policy binding for the LAN device identified by MAC.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterUnbindDeviceRequest true "Device MAC"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/policy-devices/unbind [post]
func (*SingboxRouterHandler) UpdateDNSRule ¶
func (h *SingboxRouterHandler) UpdateDNSRule(w http.ResponseWriter, r *http.Request)
UpdateDNSRule replaces the DNS rule at the given index.
@Summary Update singbox-router DNS rule
@Description Replaces the DNS rule at the given index (0-based priority slot) with the provided one.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSRuleUpdateRequest true "Index + replacement rule"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/rules/update [post]
func (*SingboxRouterHandler) UpdateDNSServer ¶
func (h *SingboxRouterHandler) UpdateDNSServer(w http.ResponseWriter, r *http.Request)
UpdateDNSServer replaces the DNS upstream identified by tag.
@Summary Update singbox-router DNS server
@Description Replaces the DNS upstream identified by tag with the provided one.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxDNSServerUpdateRequest true "Tag + replacement server"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/dns/servers/update [post]
func (*SingboxRouterHandler) UpdateOutbound ¶
func (h *SingboxRouterHandler) UpdateOutbound(w http.ResponseWriter, r *http.Request)
UpdateOutbound replaces the composite outbound identified by tag.
@Summary Update singbox-router outbound
@Description Replaces the composite outbound identified by tag with the provided one.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterOutboundUpdateRequest true "Tag + replacement outbound"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/outbounds/update [post]
func (*SingboxRouterHandler) UpdateRule ¶
func (h *SingboxRouterHandler) UpdateRule(w http.ResponseWriter, r *http.Request)
UpdateRule replaces a rule at the given index with the provided one.
@Summary Update singbox-router rule
@Description Replaces the rule at index with the provided one. Index is the priority slot (0-based).
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterRuleUpdateRequest true "Index + replacement rule"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/rules/update [post]
func (*SingboxRouterHandler) UpdateRuleSet ¶
func (h *SingboxRouterHandler) UpdateRuleSet(w http.ResponseWriter, r *http.Request)
UpdateRuleSet replaces the ruleset identified by tag with new content.
@Summary Update singbox-router ruleset
@Description Replaces the ruleset identified by tag with new content. If the payload tag differs, references are renamed atomically.
@Tags singbox-router
@Accept json
@Produce json
@Security CookieAuth
@Param body body SingboxRouterRuleSetUpdateRequest true "Tag + new RuleSet payload"
@Success 200 {object} OkResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/router/rulesets/update [post]
type SingboxRouterInspectDNSData ¶
type SingboxRouterInspectDNSData struct {
Input string `json:"input" example:"discord.com"`
InputType string `json:"inputType" example:"domain"`
Matches []SingboxRouterInspectDNSMatchDTO `json:"matches"`
MatchedRule int `json:"matchedRule" example:"5"`
Server string `json:"server" example:"fakeip"`
Classification string `json:"classification" example:"fakeip"`
Pool string `json:"pool,omitempty" example:"198.18.0.0/15"`
Final string `json:"final" example:"fakeip"`
Note string `json:"note,omitempty"`
}
SingboxRouterInspectDNSData mirrors router.InspectDNSResult.
type SingboxRouterInspectDNSMatchDTO ¶
type SingboxRouterInspectDNSMatchDTO struct {
Index int `json:"index" example:"0"`
Matched bool `json:"matched" example:"true"`
Server string `json:"server,omitempty" example:"fakeip"`
Conditions []string `json:"conditions,omitempty"`
Reason string `json:"reason,omitempty" example:"совпало по: query_type"`
}
SingboxRouterInspectDNSMatchDTO mirrors router.DNSRuleMatchResult.
type SingboxRouterInspectDNSRequest ¶
type SingboxRouterInspectDNSRequest struct {
Domain string `json:"domain" example:"discord.com"`
QueryType string `json:"queryType,omitempty" example:"A"`
SourceIP string `json:"sourceIP,omitempty" example:"192.168.1.70"`
}
SingboxRouterInspectDNSRequest is the body for POST /singbox/router/inspect-dns.
type SingboxRouterInspectDNSResponse ¶
type SingboxRouterInspectDNSResponse struct {
Success bool `json:"success" example:"true"`
Data SingboxRouterInspectDNSData `json:"data"`
}
SingboxRouterInspectDNSResponse is the envelope for POST /singbox/router/inspect-dns.
type SingboxRouterInspectData ¶
type SingboxRouterInspectData struct {
Input string `json:"input" example:"google.com"`
InputType string `json:"inputType" example:"domain"`
Matches []SingboxRouterInspectMatchDTO `json:"matches"`
Destination string `json:"destination" example:"vpn"`
MatchedRule int `json:"matchedRule" example:"0"`
Final string `json:"final" example:"direct"`
Note string `json:"note,omitempty"`
}
SingboxRouterInspectData mirrors router.InspectResult.
type SingboxRouterInspectMatchDTO ¶
type SingboxRouterInspectMatchDTO struct {
Index int `json:"index" example:"0"`
Matched bool `json:"matched" example:"true"`
Action string `json:"action" example:"route"`
Outbound string `json:"outbound,omitempty" example:"vpn"`
Conditions []string `json:"conditions,omitempty"`
Reason string `json:"reason,omitempty" example:"совпало по: domain_suffix"`
}
SingboxRouterInspectMatchDTO mirrors router.RuleMatchResult.
type SingboxRouterInspectProgressDTO ¶
type SingboxRouterInspectProgressDTO struct {
Phase string `json:"phase" example:"rule_set_match_start"`
Message string `json:"message" example:"Проверяем rule_set geosite-youtube через sing-box…"`
RuleIndex *int `json:"ruleIndex,omitempty" example:"3"`
RuleTotal *int `json:"ruleTotal,omitempty" example:"17"`
RuleSetTag string `json:"ruleSetTag,omitempty" example:"geosite-youtube"`
RuleSetIndex *int `json:"ruleSetIndex,omitempty" example:"0"`
RuleSetTotal *int `json:"ruleSetTotal,omitempty" example:"2"`
Final string `json:"final,omitempty" example:"direct"`
UsingDraft bool `json:"usingDraft,omitempty" example:"true"`
}
SingboxRouterInspectProgressDTO mirrors router.InspectProgress.
type SingboxRouterInspectRequest ¶
type SingboxRouterInspectRequest struct {
Domain string `json:"domain" example:"google.com"`
Port int `json:"port,omitempty" example:"443"`
Protocol string `json:"protocol,omitempty" example:"tcp"`
}
SingboxRouterInspectRequest is the body for POST /singbox/router/inspect.
type SingboxRouterInspectResponse ¶
type SingboxRouterInspectResponse struct {
Success bool `json:"success" example:"true"`
Data SingboxRouterInspectData `json:"data"`
}
SingboxRouterInspectResponse is the envelope for POST /singbox/router/inspect.
type SingboxRouterInspectStreamEventDTO ¶
type SingboxRouterInspectStreamEventDTO struct {
Type string `json:"type" example:"progress"`
Progress *SingboxRouterInspectProgressDTO `json:"progress,omitempty"`
Result *SingboxRouterInspectData `json:"result,omitempty"`
Error string `json:"error,omitempty" example:"load router config: ..."`
}
SingboxRouterInspectStreamEventDTO mirrors router.InspectStreamEvent.
type SingboxRouterIssueDTO ¶
type SingboxRouterIssueDTO struct {
Severity string `json:"severity" example:"warning"`
Kind string `json:"kind" example:"missing-outbound"`
RuleIndex int `json:"ruleIndex,omitempty" example:"0"`
Tag string `json:"tag,omitempty" example:"selector"`
Message string `json:"message" example:"outbound 'selector' is referenced but does not exist"`
}
SingboxRouterIssueDTO mirrors router.Issue (one entry of Status.Issues).
type SingboxRouterModeRequest ¶
type SingboxRouterModeRequest struct {
Mode string `json:"mode" example:"fakeip-tun" enums:"off,tproxy,fakeip-tun"`
}
SingboxRouterModeRequest is the body for POST /singbox/router/mode.
type SingboxRouterOutboundDTO ¶
type SingboxRouterOutboundDTO struct {
Type string `json:"type" example:"selector"`
Tag string `json:"tag" example:"my-selector"`
BindInterface string `json:"bind_interface,omitempty" example:"awg-vpn0"`
Outbounds []string `json:"outbounds,omitempty" example:"awg-vpn0"`
URL string `json:"url,omitempty" example:"https://www.gstatic.com/generate_204"`
Interval string `json:"interval,omitempty" example:"3m"`
Tolerance int `json:"tolerance,omitempty" example:"50"`
Default string `json:"default,omitempty" example:"awg-vpn0"`
Strategy string `json:"strategy,omitempty" example:"prefer_ipv4"`
Source string `json:"source" example:"router" enums:"router,subscription"`
}
SingboxRouterOutboundDTO mirrors router.Outbound (composite outbound).
type SingboxRouterOutboundDeleteRequest ¶
type SingboxRouterOutboundDeleteRequest struct {
Tag string `json:"tag" example:"my-selector"`
Force bool `json:"force" example:"false"`
}
SingboxRouterOutboundDeleteRequest is the body for POST /singbox/router/outbounds/delete.
type SingboxRouterOutboundUpdateRequest ¶
type SingboxRouterOutboundUpdateRequest struct {
Tag string `json:"tag" example:"my-selector"`
Outbound SingboxRouterOutboundDTO `json:"outbound"`
}
SingboxRouterOutboundUpdateRequest is the body for POST /singbox/router/outbounds/update.
type SingboxRouterOutboundsListResponse ¶
type SingboxRouterOutboundsListResponse struct {
Success bool `json:"success" example:"true"`
Data []SingboxRouterOutboundDTO `json:"data"`
}
SingboxRouterOutboundsListResponse is the envelope for GET /singbox/router/outbounds/list.
type SingboxRouterPoliciesListResponse ¶
type SingboxRouterPoliciesListResponse struct {
Success bool `json:"success" example:"true"`
Data []SingboxRouterPolicyInfoDTO `json:"data"`
}
SingboxRouterPoliciesListResponse is the envelope for GET /singbox/router/policies.
type SingboxRouterPolicyDeviceDTO ¶
type SingboxRouterPolicyDeviceDTO struct {
MAC string `json:"mac" example:"aa:bb:cc:dd:ee:ff"`
IP string `json:"ip" example:"192.168.1.100"`
Name string `json:"name,omitempty" example:"My Phone"`
Bound bool `json:"bound" example:"true"`
}
SingboxRouterPolicyDeviceDTO mirrors router.PolicyDevice.
type SingboxRouterPolicyDevicesListResponse ¶
type SingboxRouterPolicyDevicesListResponse struct {
Success bool `json:"success" example:"true"`
Data []SingboxRouterPolicyDeviceDTO `json:"data"`
}
SingboxRouterPolicyDevicesListResponse is the envelope for GET /singbox/router/policy-devices.
type SingboxRouterPolicyInfoDTO ¶
type SingboxRouterPolicyInfoDTO struct {
Name string `json:"name" example:"Policy0"`
Description string `json:"description" example:"Default policy"`
Mark string `json:"mark,omitempty" example:"0xffffaaa"`
DeviceCount int `json:"deviceCount" example:"3"`
IsOurDefault bool `json:"isOurDefault" example:"false"`
}
SingboxRouterPolicyInfoDTO mirrors router.PolicyInfo (NDMS policy projection).
type SingboxRouterPolicyResponse ¶
type SingboxRouterPolicyResponse struct {
Success bool `json:"success" example:"true"`
Data SingboxRouterPolicyInfoDTO `json:"data"`
}
SingboxRouterPolicyResponse is the envelope for POST /singbox/router/policies (single policy).
type SingboxRouterPresetDTO ¶
type SingboxRouterPresetDTO struct {
ID string `json:"id" example:"china-direct"`
Name string `json:"name" example:"China Direct"`
Category string `json:"category,omitempty" example:"social"`
IconSlug string `json:"iconSlug,omitempty" example:"china"`
RuleSets []SingboxRouterPresetRuleRefDTO `json:"ruleSets"`
Rules []SingboxRouterPresetRuleLinkDTO `json:"rules"`
Notice string `json:"notice,omitempty" example:"Routes mainland China traffic via the direct outbound."`
Covers []string `json:"covers,omitempty" example:"instagram,whatsapp"`
Featured bool `json:"featured,omitempty" example:"true"`
Sensitive bool `json:"sensitive,omitempty" example:"false"`
}
SingboxRouterPresetDTO mirrors router.Preset (one entry of the preset catalog).
type SingboxRouterPresetRuleLinkDTO ¶
type SingboxRouterPresetRuleLinkDTO struct {
RuleSet []string `json:"rule_set,omitempty" example:"geosite-cn"`
DomainSuffix []string `json:"domain_suffix,omitempty" example:".cn"`
Action string `json:"action,omitempty" example:"route"`
}
SingboxRouterPresetRuleLinkDTO mirrors router.RuleLink.
type SingboxRouterPresetRuleRefDTO ¶
type SingboxRouterPresetRuleRefDTO struct {
Tag string `json:"tag" example:"geosite-cn"`
}
SingboxRouterPresetRuleRefDTO mirrors router.RuleRef.
type SingboxRouterPresetsListResponse ¶
type SingboxRouterPresetsListResponse struct {
Success bool `json:"success" example:"true"`
Data []SingboxRouterPresetDTO `json:"data"`
}
SingboxRouterPresetsListResponse is the envelope for GET /singbox/router/presets/list.
type SingboxRouterRouteFinalRequest ¶
type SingboxRouterRouteFinalRequest struct {
Final string `json:"final" example:"direct"`
}
SingboxRouterRouteFinalRequest is the body for POST /singbox/router/route/final.
type SingboxRouterRuleDTO ¶
type SingboxRouterRuleDTO struct {
DomainSuffix []string `json:"domain_suffix,omitempty" example:".example.com"`
IPCIDR []string `json:"ip_cidr,omitempty" example:"10.0.0.0/8"`
SourceIPCIDR []string `json:"source_ip_cidr,omitempty" example:"192.168.1.100/32"`
Port []int `json:"port,omitempty" example:"443"`
RuleSet []string `json:"rule_set,omitempty" example:"geosite-cn"`
Protocol string `json:"protocol,omitempty" example:"tcp"`
Action string `json:"action" example:"route"`
Outbound string `json:"outbound,omitempty" example:"selector"`
}
SingboxRouterRuleDTO mirrors router.Rule (a routing rule in priority order).
type SingboxRouterRuleDeleteRequest ¶
type SingboxRouterRuleDeleteRequest struct {
Index int `json:"index" example:"0"`
}
SingboxRouterRuleDeleteRequest is the body for POST /singbox/router/rules/delete.
type SingboxRouterRuleMoveRequest ¶
type SingboxRouterRuleMoveRequest struct {
From int `json:"from" example:"3"`
To int `json:"to" example:"0"`
}
SingboxRouterRuleMoveRequest is the body for POST /singbox/router/rules/move.
type SingboxRouterRuleSetDTO ¶
type SingboxRouterRuleSetDTO struct {
Tag string `json:"tag" example:"geosite-cn"`
Type string `json:"type" example:"remote"`
Format string `json:"format,omitempty" example:"binary"`
URL string `json:"url,omitempty" example:"https://cdn.example.com/geosite-cn.srs"`
UpdateInterval string `json:"update_interval,omitempty" example:"24h"`
DownloadDetour string `json:"download_detour,omitempty" example:"direct"`
Path string `json:"path,omitempty" example:"/opt/etc/singbox/rulesets/geosite-cn.srs"`
Rules []map[string]any `json:"rules,omitempty"`
MaterializedSRS bool `json:"materialized_srs,omitempty" example:"true"`
}
SingboxRouterRuleSetDTO mirrors router.RuleSet.
type SingboxRouterRuleSetDeleteRequest ¶
type SingboxRouterRuleSetDeleteRequest struct {
Tag string `json:"tag" example:"geosite-cn"`
Force bool `json:"force" example:"false"`
}
SingboxRouterRuleSetDeleteRequest is the body for POST /singbox/router/rulesets/delete.
type SingboxRouterRuleSetUpdateRequest ¶
type SingboxRouterRuleSetUpdateRequest struct {
Tag string `json:"tag" example:"geosite-cn"`
RuleSet SingboxRouterRuleSetDTO `json:"ruleSet"`
}
SingboxRouterRuleSetUpdateRequest is the body for POST /singbox/router/rulesets/update.
type SingboxRouterRuleSetsListResponse ¶
type SingboxRouterRuleSetsListResponse struct {
Success bool `json:"success" example:"true"`
Data []SingboxRouterRuleSetDTO `json:"data"`
}
SingboxRouterRuleSetsListResponse is the envelope for GET /singbox/router/rulesets/list.
type SingboxRouterRuleUpdateRequest ¶
type SingboxRouterRuleUpdateRequest struct {
Index int `json:"index" example:"0"`
Rule SingboxRouterRuleDTO `json:"rule"`
}
SingboxRouterRuleUpdateRequest is the body for POST /singbox/router/rules/update.
type SingboxRouterRulesListResponse ¶
type SingboxRouterRulesListResponse struct {
Success bool `json:"success" example:"true"`
Data []SingboxRouterRuleDTO `json:"data"`
}
SingboxRouterRulesListResponse is the envelope for GET /singbox/router/rules/list.
type SingboxRouterSettingsData ¶
type SingboxRouterSettingsData struct {
Enabled bool `json:"enabled" example:"true"`
PolicyName string `json:"policyName" example:"awgm-router"`
DeviceMode string `json:"deviceMode,omitempty" example:"policy" enums:"policy,all"`
RoutingMode string `json:"routingMode,omitempty" example:"tproxy" enums:"tproxy,fakeip-tun"`
SnifferEnabled bool `json:"snifferEnabled" example:"true"`
// WANAutoDetect / WANInterface form a two-field discriminator:
// true + "" → sing-box auto_detect_interface
// false + "ppp0"→ sing-box default_interface=ppp0
// Other combinations are rejected by the backend validator.
// Example below shows the PINNED case as it's the more interesting
// shape to document (auto case has WANInterface omitted via omitempty
// and wanAutoDetect=true); both examples are intentionally consistent.
WANAutoDetect bool `json:"wanAutoDetect" example:"false"`
WANInterface string `json:"wanInterface,omitempty" example:"ppp0"`
// BypassPresets lists active named port-bypass presets.
// Valid values: "l2tp", "ntp", "netbios-smb".
BypassPresets []string `json:"bypassPresets,omitempty" example:"l2tp"`
// BypassExtraPorts is a user-defined comma-separated list of extra
// port exclusions in "PORT UDP|TCP" format (e.g. "51820 UDP, 1194 TCP").
BypassExtraPorts string `json:"bypassExtraPorts,omitempty" example:"51820 UDP"`
// BypassExtraSubnets is a user-defined comma/space-separated list of IPv4
// IP/CIDR destinations whose traffic bypasses sing-box entirely (incl.
// DNS/53). Bare IP is treated as /32. E.g. "203.0.113.0/24, 10.8.0.5".
BypassExtraSubnets string `json:"bypassExtraSubnets,omitempty" example:"203.0.113.0/24"`
// IngressInterfaces lists interface refs whose ingress traffic is
// redirected through the sing-box router (e.g. "managed:Wireguard3").
IngressInterfaces []string `json:"ingressInterfaces,omitempty" example:"managed:Wireguard3"`
// --- fakeip-tun engine settings (user-editable) ---
// FakeIPStack selects the sing-tun stack: "gvisor" (default) or "system".
FakeIPStack string `json:"fakeipStack,omitempty" example:"gvisor" enums:"gvisor,system"`
// FakeIPPool4 is the fakeip v4 pool CIDR (default "198.18.0.0/15").
FakeIPPool4 string `json:"fakeipPool4,omitempty" example:"198.18.0.0/15"`
// FakeIPPool6 is the fakeip v6 pool CIDR (default "fc00::/18"); "" disables v6.
FakeIPPool6 string `json:"fakeipPool6,omitempty" example:"fc00::/18"`
// FakeIPMTU is the tun MTU (default 1500; valid range 576-9000).
FakeIPMTU int `json:"fakeipMtu,omitempty" example:"1500"`
// UDPTimeout sets the UDP session timeout for the tproxy-in inbound
// (Go duration string, e.g. "3m0s", "10m0s"). Empty = use default (3m0s).
// Increase to prevent long-quiet UDP applications (games, etc.) from
// having their sessions silently dropped mid-game.
UDPTimeout string `json:"udpTimeout,omitempty" example:"10m0s"`
}
SingboxRouterSettingsData mirrors storage.SingboxRouterSettings.
type SingboxRouterSettingsResponse ¶
type SingboxRouterSettingsResponse struct {
Success bool `json:"success" example:"true"`
Data SingboxRouterSettingsData `json:"data"`
}
SingboxRouterSettingsResponse is the envelope for GET /singbox/router/settings.
type SingboxRouterStatusData ¶
type SingboxRouterStatusData struct {
Enabled bool `json:"enabled" example:"true"`
Installed bool `json:"installed" example:"true"`
Active bool `json:"active" example:"true"`
NetfilterAvailable bool `json:"netfilterAvailable" example:"true"`
NetfilterComponentName string `json:"netfilterComponentName,omitempty" example:"iptables-mod-tproxy"`
TProxyTargetAvailable bool `json:"tproxyTargetAvailable" example:"true"`
PolicyName string `json:"policyName" example:"awgm-router"`
PolicyMark string `json:"policyMark,omitempty" example:"0xffffaaa"`
PolicyExists bool `json:"policyExists" example:"true"`
DeviceMode string `json:"deviceMode" example:"policy" enums:"policy,all"`
SnifferEnabled bool `json:"snifferEnabled" example:"true"`
DeviceCount int `json:"deviceCount" example:"3"`
RuleCount int `json:"ruleCount" example:"12"`
RuleSetCount int `json:"ruleSetCount" example:"4"`
OutboundAWGCount int `json:"outboundAwgCount" example:"2"`
OutboundCompositeCount int `json:"outboundCompositeCount" example:"1"`
Final string `json:"final" example:"direct"`
FakeIPIface string `json:"fakeipIface,omitempty" example:"opkgtun0"`
FakeIPDns string `json:"fakeipDns,omitempty" example:"172.18.0.2"`
FakeIPTunAddr string `json:"fakeipTunAddr,omitempty" example:"172.18.0.1"`
LastError string `json:"lastError,omitempty" example:"engine start failed"`
Issues []SingboxRouterIssueDTO `json:"issues,omitempty"`
}
SingboxRouterStatusData mirrors router.Status.
type SingboxRouterStatusResponse ¶
type SingboxRouterStatusResponse struct {
Success bool `json:"success" example:"true"`
Data SingboxRouterStatusData `json:"data"`
}
SingboxRouterStatusResponse is the envelope for GET /singbox/router/status.
type SingboxRouterTransitionData ¶
type SingboxRouterTransitionData struct {
TransitionID string `json:"transitionId" example:"switch-7"`
From string `json:"from" example:"tproxy" enums:"off,tproxy,fakeip-tun"`
To string `json:"to" example:"fakeip-tun" enums:"off,tproxy,fakeip-tun"`
Step SingboxRouterTransitionStepDTO `json:"step"`
Done bool `json:"done,omitempty" example:"true"`
FinalState string `json:"finalState,omitempty" example:"fakeip-tun" enums:"off,tproxy,fakeip-tun"`
Error string `json:"error,omitempty" example:""`
}
SingboxRouterTransitionData mirrors router.TransitionEvent. It documents the payload of the "singbox-router:transition" events emitted on the GET /events SSE stream during a POST /singbox/router/mode switch (the UI progress screen).
type SingboxRouterTransitionStepDTO ¶
type SingboxRouterTransitionStepDTO struct {
Step string `json:"step" example:"provision" enums:"start,teardown,provision,readiness,ready,rollback,error"`
Status string `json:"status" example:"current" enums:"current,done,error"`
Message string `json:"message,omitempty" example:"restored tproxy"`
}
SingboxRouterTransitionStepDTO mirrors router.TransitionStep — one milestone of a routing-mode switch.
type SingboxRouterUnbindDeviceRequest ¶
type SingboxRouterUnbindDeviceRequest struct {
MAC string `json:"mac" example:"aa:bb:cc:dd:ee:ff"`
}
SingboxRouterUnbindDeviceRequest is the body for POST /singbox/router/policy-devices/unbind.
type SingboxRouterWANInterfaceDTO ¶
type SingboxRouterWANInterfaceDTO struct {
Name string `json:"name" example:"ppp0"`
ID string `json:"id" example:"PPPoE0"`
Label string `json:"label" example:"Резервный канал"`
Up bool `json:"up" example:"true"`
Priority int `json:"priority" example:"700000"`
}
SingboxRouterWANInterfaceDTO mirrors router.WANInterfaceInfo for the WAN-binding picker.
type SingboxRouterWANInterfacesListResponse ¶
type SingboxRouterWANInterfacesListResponse struct {
Success bool `json:"success" example:"true"`
Data []SingboxRouterWANInterfaceDTO `json:"data"`
}
SingboxRouterWANInterfacesListResponse is the envelope for GET /singbox/router/wan-interfaces and GET /singbox/router/bindable-interfaces. For the bindable-interfaces endpoint, id and priority are always zero (only name, label, up are populated).
type SingboxStatusData ¶
type SingboxStatusData struct {
Installed bool `json:"installed" example:"true"`
Version string `json:"version,omitempty" example:"1.9.3"`
Running bool `json:"running" example:"true"`
PID int `json:"pid,omitempty" example:"12345"`
TunnelCount int `json:"tunnelCount" example:"2"`
ProxyComponent bool `json:"proxyComponent" example:"true"`
NDMSProxyEnabled bool `json:"ndmsProxyEnabled" example:"true"`
Features []string `json:"features,omitempty" example:"with_quic"`
LastError string `json:"lastError,omitempty" example:"+0000 2026-05-14 21:45:56 FATAL[0000] failed to initialize"`
CurrentVersion string `json:"currentVersion,omitempty" example:"1.13.11"`
RequiredVersion string `json:"requiredVersion" example:"1.13.11"`
CurrentSHA256 string `json:"currentSha256,omitempty" example:"76e67bb07b5c2bf4cef108c2f21a5ffaa684d124c21ffe220fc89b39cf1de934"`
RequiredSHA256 string `json:"requiredSha256,omitempty" example:"76e67bb07b5c2bf4cef108c2f21a5ffaa684d124c21ffe220fc89b39cf1de934"`
UpdateAvailable bool `json:"updateAvailable" example:"false"`
InstallState string `json:"installState" example:"outdated_no_space"`
RequiredBytes int64 `json:"requiredBytes" example:"32145678"`
FreeBytes int64 `json:"freeBytes" example:"8221456"`
}
SingboxStatusData mirrors frontend SingboxStatus.
type SingboxStatusResponse ¶
type SingboxStatusResponse struct {
Success bool `json:"success" example:"true"`
Data SingboxStatusData `json:"data"`
}
SingboxStatusResponse is the envelope for GET /singbox/status.
type SingboxTunnelConnectivity ¶
type SingboxTunnelConnectivity struct {
Connected bool `json:"connected" example:"true"`
Latency *int `json:"latency" swaggertype:"integer" example:"42"`
}
SingboxTunnelConnectivity is the connectivity field in SingboxTunnel.
type SingboxTunnelDTO ¶
type SingboxTunnelDTO struct {
Tag string `json:"tag" example:"proxy-01"`
Protocol string `json:"protocol" example:"vless"`
Server string `json:"server" example:"proxy.example.com"`
Port int `json:"port" example:"443"`
Security string `json:"security" example:"reality"`
Transport string `json:"transport" example:"tcp"`
ListenPort int `json:"listenPort" example:"7891"`
ProxyInterface string `json:"proxyInterface" example:"br0"`
SNI string `json:"sni,omitempty" example:"cdn.example.com"`
Fingerprint string `json:"fingerprint,omitempty" example:"chrome"`
Connectivity SingboxTunnelConnectivity `json:"connectivity"`
Running bool `json:"running" example:"true"`
}
SingboxTunnelDTO mirrors frontend SingboxTunnel.
type SingboxTunnelsResponse ¶
type SingboxTunnelsResponse struct {
Success bool `json:"success" example:"true"`
Data []SingboxTunnelDTO `json:"data"`
}
SingboxTunnelsResponse is the envelope for GET /singbox/tunnels.
type SpeedTestInfoData ¶
type SpeedTestInfoData struct {
Available bool `json:"available" example:"true"`
Servers []SpeedTestServerDTO `json:"servers"`
}
SpeedTestInfoData mirrors frontend SpeedTestInfo.
type SpeedTestInfoResponse ¶
type SpeedTestInfoResponse struct {
Success bool `json:"success" example:"true"`
Data SpeedTestInfoData `json:"data"`
}
SpeedTestInfoResponse is the envelope for GET /test/speed/servers.
type SpeedTestResultData ¶
type SpeedTestResultData struct {
Server string `json:"server" example:"speedtest.msk.ru"`
Direction string `json:"direction" example:"download"`
Bandwidth float64 `json:"bandwidth" example:"52428800"`
Bytes int64 `json:"bytes" example:"157286400"`
Duration float64 `json:"duration" example:"3.0"`
Retransmits int `json:"retransmits" example:"0"`
}
SpeedTestResultData mirrors frontend SpeedTestResult.
type SpeedTestResultResponse ¶
type SpeedTestResultResponse struct {
Success bool `json:"success" example:"true"`
Data SpeedTestResultData `json:"data"`
}
SpeedTestResultResponse is the envelope for GET /test/speed.
type SpeedTestServerDTO ¶
type SpeedTestServerDTO struct {
Label string `json:"label" example:"Moscow, RU"`
Host string `json:"host" example:"speedtest.msk.ru"`
Port int `json:"port" example:"5201"`
}
SpeedTestServerDTO mirrors frontend SpeedTestServer.
type StaticRouteDTO ¶
type StaticRouteDTO struct {
ID string `json:"id" example:"sr_001"`
Name string `json:"name" example:"Office subnets"`
TunnelID string `json:"tunnelID" example:"tun_abc123"`
Subnets []string `json:"subnets" example:"192.168.10.0/24"`
Fallback string `json:"fallback,omitempty" example:""`
IconURL string `json:"iconUrl,omitempty" example:"https://cdn.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Cloudflare.png"`
Enabled bool `json:"enabled" example:"true"`
CreatedAt string `json:"createdAt" example:"2024-01-01T00:00:00Z"`
UpdatedAt string `json:"updatedAt" example:"2024-01-15T12:00:00Z"`
}
StaticRouteDTO mirrors frontend StaticRouteList.
type StaticRouteHandler ¶
type StaticRouteHandler struct {
// contains filtered or unexported fields
}
StaticRouteHandler handles static route API endpoints.
func NewStaticRouteHandler ¶
func NewStaticRouteHandler(svc StaticRouteService, appLogger logging.AppLogger) *StaticRouteHandler
NewStaticRouteHandler creates a new static route handler.
func (*StaticRouteHandler) Create ¶
func (h *StaticRouteHandler) Create(w http.ResponseWriter, r *http.Request)
Create creates a new static route list.
@Summary Create static route
@Tags static-routes
@Accept json
@Produce json
@Security CookieAuth
@Success 200 {object} StaticRoutesListResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /static-routes/create [post]
func (*StaticRouteHandler) Delete ¶
func (h *StaticRouteHandler) Delete(w http.ResponseWriter, r *http.Request)
Delete deletes a static route list by ID.
@Summary Delete static route
@Tags static-routes
@Produce json
@Security CookieAuth
@Param id query string true "List id"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /static-routes/delete [post]
func (*StaticRouteHandler) Import ¶
func (h *StaticRouteHandler) Import(w http.ResponseWriter, r *http.Request)
Import imports subnets from a .bat file content.
@Summary Import static routes
@Tags static-routes
@Accept json
@Produce json
@Security CookieAuth
@Success 200 {object} StaticRoutesListResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /static-routes/import [post]
func (*StaticRouteHandler) List ¶
func (h *StaticRouteHandler) List(w http.ResponseWriter, r *http.Request)
List returns static IP routes.
@Summary List static routes
@Tags static-routes
@Produce json
@Security CookieAuth
@Success 200 {object} StaticRoutesListResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /static-routes/list [get]
@Router /routing/static-routes [get]
func (*StaticRouteHandler) SetEnabled ¶
func (h *StaticRouteHandler) SetEnabled(w http.ResponseWriter, r *http.Request)
SetEnabled toggles the enabled state of a static route list.
@Summary Set static route enabled
@Tags static-routes
@Accept json
@Produce json
@Security CookieAuth
@Param id query string true "List id"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /static-routes/set-enabled [post]
func (*StaticRouteHandler) SetEventBus ¶
func (h *StaticRouteHandler) SetEventBus(bus *events.Bus)
SetEventBus sets the event bus for SSE publishing.
func (*StaticRouteHandler) Update ¶
func (h *StaticRouteHandler) Update(w http.ResponseWriter, r *http.Request)
Update updates an existing static route list.
@Summary Update static route
@Tags static-routes
@Accept json
@Produce json
@Security CookieAuth
@Success 200 {object} StaticRoutesListResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /static-routes/update [post]
type StaticRouteService ¶
type StaticRouteService interface {
List() ([]storage.StaticRouteList, error)
Get(id string) (*storage.StaticRouteList, error)
Create(ctx context.Context, rl storage.StaticRouteList) (*storage.StaticRouteList, error)
Update(ctx context.Context, rl storage.StaticRouteList) (*storage.StaticRouteList, error)
Delete(ctx context.Context, id string) error
SetEnabled(ctx context.Context, id string, enabled bool) error
Import(ctx context.Context, tunnelID, name, batContent string) (*storage.StaticRouteList, error)
}
StaticRouteService defines what the static route handler needs from the service.
type StaticRoutesListResponse ¶
type StaticRoutesListResponse struct {
Success bool `json:"success" example:"true"`
Data []StaticRouteDTO `json:"data"`
}
StaticRoutesListResponse is the envelope for GET /static-routes/list.
type SubgroupsData ¶
type SubgroupsData struct {
Group string `json:"group" example:"routing"`
Subgroups []string `json:"subgroups"`
}
SubgroupsData is the payload for GET /logs/subgroups.
type SubgroupsResponseEnvelope ¶
type SubgroupsResponseEnvelope struct {
Success bool `json:"success" example:"true"`
Data SubgroupsData `json:"data"`
}
SubgroupsResponseEnvelope is the envelope for GET /logs/subgroups.
type SubscriptionDTO ¶
type SubscriptionDTO struct {
ID string `json:"id" example:"sub-demo"`
Label string `json:"label" example:"Demo Provider"`
URL string `json:"url" example:"https://example.com/subscriptions/demo.txt"`
IsInline bool `json:"isInline" example:"false"`
Headers []SubscriptionHeader `json:"headers"`
RefreshHours int `json:"refreshHours" example:"24"`
LastFetched string `json:"lastFetched" example:"2026-05-14T21:30:00Z"`
LastError string `json:"lastError,omitempty" example:""`
SelectorTag string `json:"selectorTag" example:"sub-demo"`
InboundTag string `json:"inboundTag" example:"sub-demo-in"`
ListenPort int `json:"listenPort" example:"11000"`
ProxyIndex int `` /* 310-byte string literal not displayed */
MemberTags []string `json:"memberTags" example:"sub-demo-001,sub-demo-002,sub-demo-003"`
Members []SubscriptionMemberDTO `json:"members"`
OrphanTags []string `json:"orphanTags" example:""`
RejectedMembers []SubscriptionRejectedDTO `json:"rejectedMembers"`
InfoItems []SubscriptionInfoItemDTO `json:"infoItems"`
ActiveMember string `json:"activeMember" example:"sub-demo-001"`
ExcludedTags []string `json:"excludedTags"`
ExcludedMembers []SubscriptionMemberDTO `json:"excludedMembers,omitempty"`
Enabled bool `json:"enabled" example:"true"`
Mode string `json:"mode" example:"selector"`
URLTest *SubscriptionURLTestDTO `json:"urlTest,omitempty"`
}
SubscriptionDTO mirrors subscription.Subscription for OpenAPI exposure.
Inline content is deliberately NOT exposed: pasted share-links carry the full server address + UUID/password and would otherwise leak into every list-all response (i.e. every page load), browser DevTools, and any reverse-proxy access log that records response bodies. Frontend only needs IsInline to gate UI affordances; raw paste stays server-side until a future single-record endpoint requires it.
type SubscriptionHandler ¶
type SubscriptionHandler struct {
// contains filtered or unexported fields
}
SubscriptionHandler exposes /api/singbox/subscriptions/* endpoints.
func NewSubscriptionHandler ¶
func NewSubscriptionHandler(svc *subscription.Service, presence SingboxPresenceProbe, appLogger ...logging.AppLogger) *SubscriptionHandler
func (*SubscriptionHandler) ActiveMember ¶
func (h *SubscriptionHandler) ActiveMember(w http.ResponseWriter, r *http.Request)
ActiveMember handles POST /api/singbox/subscriptions/active-member?id=
@Summary Set active member
@Tags subscriptions
@Accept json
@Produce json
@Param id query string true "subscription id"
@Param req body ActiveMemberRequest true "member tag"
@Success 200 {object} SubscriptionResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/subscriptions/active-member [post]
func (*SubscriptionHandler) ActiveNow ¶
func (h *SubscriptionHandler) ActiveNow(w http.ResponseWriter, r *http.Request)
ActiveNow handles GET /api/singbox/subscriptions/active-now?id=
@Summary Live active member from Clash
@Description Returns the currently-active member tag as reported by the running sing-box Clash API. For urltest mode this reflects the auto-selected fastest member. Empty `now` means Clash is unreachable or no member selected yet.
@Tags subscriptions
@Produce json
@Security CookieAuth
@Param id query string true "Subscription id"
@Success 200 {object} OkResponse{data=ActiveNowResponse}
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/subscriptions/active-now [get]
func (*SubscriptionHandler) AddMember ¶
func (h *SubscriptionHandler) AddMember(w http.ResponseWriter, r *http.Request)
AddMember handles POST /api/singbox/subscriptions/members/add?id=
@Summary Add a manual member to an inline subscription
@Tags subscriptions
@Accept json
@Produce json
@Security CookieAuth
@Param id query string true "Subscription ID"
@Param body body AddMemberRequest true "Share-link"
@Success 200 {object} SubscriptionResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 409 {object} APIErrorEnvelope
@Failure 422 {object} APIErrorEnvelope "sing-box validation rejected the new member"
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/subscriptions/members/add [post]
func (*SubscriptionHandler) Create ¶
func (h *SubscriptionHandler) Create(w http.ResponseWriter, r *http.Request)
Create handles POST /api/singbox/subscriptions/create
@Summary Create sing-box subscription
@Description Creates subscription from URL or inline share links. Returns 422 VALIDATION_FAILED when the merged sing-box config is rejected by `sing-box check` (e.g. reality outbound without uTLS).
@Tags subscriptions
@Accept json
@Produce json
@Param req body CreateSubscriptionRequest true "create request"
@Success 200 {object} SubscriptionResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 412 {object} APIErrorEnvelope
@Failure 422 {object} APIErrorEnvelope "sing-box validation rejected the subscription"
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/subscriptions/create [post]
func (*SubscriptionHandler) Delete ¶
func (h *SubscriptionHandler) Delete(w http.ResponseWriter, r *http.Request)
Delete handles DELETE /api/singbox/subscriptions/delete?id= Always performs full cleanup (no cascade flag).
@Summary Delete sing-box subscription
@Tags subscriptions
@Produce json
@Param id query string true "subscription id"
@Success 200 {object} APIEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/subscriptions/delete [delete]
func (*SubscriptionHandler) ExcludeMembers ¶
func (h *SubscriptionHandler) ExcludeMembers(w http.ResponseWriter, r *http.Request)
ExcludeMembers handles POST /api/singbox/subscriptions/members/exclude?id=
@Summary Exclude members from a URL subscription
@Description Marks the given member tags as excluded: rebuilds the
@Description selector without them, drops their outbounds and survives
@Description refresh. Reversible via restore. URL subscriptions only.
@Tags subscriptions
@Accept json
@Produce json
@Security CookieAuth
@Param id query string true "Subscription ID"
@Param body body ExcludeMembersRequest true "Member tags to exclude"
@Success 200 {object} SubscriptionResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 409 {object} APIErrorEnvelope "excluding all members is not allowed"
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/subscriptions/members/exclude [post]
func (*SubscriptionHandler) Get ¶
func (h *SubscriptionHandler) Get(w http.ResponseWriter, r *http.Request)
Get handles GET /api/singbox/subscriptions/get?id=
@Summary Get sing-box subscription
@Tags subscriptions
@Produce json
@Param id query string true "subscription id"
@Success 200 {object} SubscriptionResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Router /singbox/subscriptions/get [get]
func (*SubscriptionHandler) GetStream ¶
func (h *SubscriptionHandler) GetStream(w http.ResponseWriter, r *http.Request)
GetStream handles GET /api/singbox/subscriptions/get-stream?id=
@Summary Stream subscription details progressively (SSE)
@Description Streams a subscription as Server-Sent Events: one `meta` event with subscription header (incl. total member count), then one `member` event per server member, then a `done` event with finalisation (orphans, active member). Frontend uses this to show a progress bar and render cards as they arrive instead of waiting for the full payload. Service.Get is itself sync; the streaming is the handler's contract — it writes events with Flush() between, so TCP + browser deliver progressively.
@Tags subscriptions
@Produce text/event-stream
@Security CookieAuth
@Param id query string true "Subscription id"
@Success 200 "Stream of SSE events: meta, member×N, done"
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 405 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/subscriptions/get-stream [get]
func (*SubscriptionHandler) InfoRemove ¶
func (h *SubscriptionHandler) InfoRemove(w http.ResponseWriter, r *http.Request)
InfoRemove handles POST /api/singbox/subscriptions/info/remove?id=
func (*SubscriptionHandler) List ¶
func (h *SubscriptionHandler) List(w http.ResponseWriter, r *http.Request)
List handles GET /api/singbox/subscriptions
@Summary List sing-box subscriptions
@Description Returns configured subscriptions with parsed members. Mocked examples include vless/reality members.
@Tags subscriptions
@Produce json
@Success 200 {object} SubscriptionListResponse
@Failure 405 {object} APIErrorEnvelope
@Router /singbox/subscriptions [get]
func (*SubscriptionHandler) OrphansDelete ¶
func (h *SubscriptionHandler) OrphansDelete(w http.ResponseWriter, r *http.Request)
OrphansDelete handles POST /api/singbox/subscriptions/orphans/delete?id=
@Summary Delete orphan members from subscription
@Tags subscriptions
@Produce json
@Param id query string true "subscription id"
@Success 200 {object} SubscriptionResponse
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/subscriptions/orphans/delete [post]
func (*SubscriptionHandler) PreviewURL ¶
func (h *SubscriptionHandler) PreviewURL(w http.ResponseWriter, r *http.Request)
PreviewURL handles POST /api/singbox/subscriptions/preview
@Summary Preview a subscription URL without creating it
@Description Read-only fetch + parse of a subscription URL. Returns the
@Description parsed members (with subID-independent keys) so the import
@Description wizard can offer per-server exclusion before creation.
@Tags subscriptions
@Accept json
@Produce json
@Security CookieAuth
@Param body body PreviewURLRequest true "URL and optional headers"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 502 {object} APIErrorEnvelope "fetch or parse failed"
@Router /singbox/subscriptions/preview [post]
func (*SubscriptionHandler) Refresh ¶
func (h *SubscriptionHandler) Refresh(w http.ResponseWriter, r *http.Request)
Refresh handles POST /api/singbox/subscriptions/refresh?id=
@Summary Refresh sing-box subscription
@Description Re-fetches the provider URL and re-runs Pass 1 / Pass 2 validation. Returns 422 VALIDATION_FAILED when the refreshed config is rejected by `sing-box check`.
@Tags subscriptions
@Produce json
@Param id query string false "subscription id"
@Success 200 {object} SubscriptionResponse
@Failure 422 {object} APIErrorEnvelope "sing-box validation rejected the refreshed subscription"
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/subscriptions/refresh [post]
func (*SubscriptionHandler) RejectedToInfo ¶
func (h *SubscriptionHandler) RejectedToInfo(w http.ResponseWriter, r *http.Request)
RejectedToInfo handles POST /api/singbox/subscriptions/rejected/to-info?id=
func (*SubscriptionHandler) RemoveMember ¶
func (h *SubscriptionHandler) RemoveMember(w http.ResponseWriter, r *http.Request)
RemoveMember handles POST /api/singbox/subscriptions/members/remove?id=
@Summary Remove a member from an inline subscription
@Description Removing the last member tears the whole subscription
@Description down. The response indicates whether the subscription
@Description itself was deleted via deleted=true.
@Tags subscriptions
@Accept json
@Produce json
@Security CookieAuth
@Param id query string true "Subscription ID"
@Param body body RemoveMemberRequest true "Member tag"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 422 {object} APIErrorEnvelope "sing-box validation rejected the remainder"
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/subscriptions/members/remove [post]
func (*SubscriptionHandler) RestoreMembers ¶
func (h *SubscriptionHandler) RestoreMembers(w http.ResponseWriter, r *http.Request)
RestoreMembers handles POST /api/singbox/subscriptions/members/restore?id=
@Summary Restore previously excluded members
@Description Removes the given tags from the exclusion set and runs a
@Description refresh, re-materializing the returned servers.
@Tags subscriptions
@Accept json
@Produce json
@Security CookieAuth
@Param id query string true "Subscription ID"
@Param body body RestoreMembersRequest true "Member tags to restore"
@Success 200 {object} SubscriptionResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 404 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/subscriptions/members/restore [post]
func (*SubscriptionHandler) SetNDMSProxyToggler ¶
func (h *SubscriptionHandler) SetNDMSProxyToggler(s ndmsProxyToggler)
SetNDMSProxyToggler wires the global NDMS Proxy flag reader. When wired and the flag is false, DTO converters surface proxyIndex=-1 so the UI (and any other API consumer) sees that the composite NDMS Proxy is gone — same shape contract as ListTunnels uses for tunnel ProxyInterface fields. Without this setter, every subscription DTO surfaces the stored ProxyIndex unconditionally.
func (*SubscriptionHandler) SetOutboundRefCheckers ¶
func (h *SubscriptionHandler) SetOutboundRefCheckers(dp tunnelservice.DeviceProxyRefChecker, r tunnelservice.RouterRefChecker)
SetOutboundRefCheckers wires device-proxy and router reference guards for subscription deletion (refuse when selector/members are still referenced).
func (*SubscriptionHandler) Update ¶
func (h *SubscriptionHandler) Update(w http.ResponseWriter, r *http.Request)
Update handles PUT /api/singbox/subscriptions/update?id=
@Summary Update sing-box subscription
@Description Updates subscription metadata or refreshes from a new URL. Returns 422 VALIDATION_FAILED when the new merged config is rejected by `sing-box check`.
@Tags subscriptions
@Accept json
@Produce json
@Param id query string true "subscription id"
@Param req body UpdateSubscriptionRequest true "update request"
@Success 200 {object} SubscriptionResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 422 {object} APIErrorEnvelope "sing-box validation rejected the subscription"
@Failure 500 {object} APIErrorEnvelope
@Router /singbox/subscriptions/update [put]
type SubscriptionHeader ¶
type SubscriptionHeader struct {
Name string `json:"name" example:"User-Agent"`
Value string `json:"value" example:"Happ/4.6.0"`
}
SubscriptionHeader is a single custom HTTP header for the fetch request.
type SubscriptionInfoItemDTO ¶
type SubscriptionInfoItemDTO struct {
ID string `json:"id"`
Label string `json:"label"`
Tag string `json:"tag,omitempty"`
Source string `json:"source,omitempty"`
}
SubscriptionInfoItemDTO is a provider info banner (not a proxy).
type SubscriptionListResponse ¶
type SubscriptionListResponse struct {
Success bool `json:"success" example:"true"`
Data []SubscriptionDTO `json:"data"`
}
SubscriptionListResponse is the envelope for GET /api/singbox/subscriptions.
type SubscriptionMemberDTO ¶
type SubscriptionMemberDTO struct {
Tag string `json:"tag" example:"sub-abc12345-aabbccdd"`
Label string `json:"label,omitempty" example:"🇺🇸 LA-1"`
Protocol string `json:"protocol" example:"vless"`
Server string `json:"server" example:"de01.example.com"`
Port int `json:"port" example:"443"`
SNI string `json:"sni,omitempty" example:"de01.example.com"`
Transport string `json:"transport,omitempty" example:"ws"`
Security string `json:"security,omitempty" example:"tls"`
}
SubscriptionMemberDTO carries per-member parsed metadata for the UI.
type SubscriptionMetaDTO ¶
type SubscriptionMetaDTO struct {
ID string `json:"id"`
Label string `json:"label"`
URL string `json:"url"`
IsInline bool `json:"isInline"`
Headers []SubscriptionHeader `json:"headers"`
RefreshHours int `json:"refreshHours"`
LastFetched string `json:"lastFetched" example:"2026-05-14T21:30:00Z"`
LastError string `json:"lastError,omitempty" example:""`
SelectorTag string `json:"selectorTag"`
InboundTag string `json:"inboundTag"`
ListenPort int `json:"listenPort"`
ProxyIndex int `json:"proxyIndex" description:"See SubscriptionDTO.ProxyIndex — gated identically (-1 when NDMS Proxy disabled)."`
Enabled bool `json:"enabled"`
Mode string `json:"mode"`
URLTest *SubscriptionURLTestDTO `json:"urlTest,omitempty"`
Total int `json:"total"`
RejectedMembers []SubscriptionRejectedDTO `json:"rejectedMembers"`
InfoItems []SubscriptionInfoItemDTO `json:"infoItems"`
}
SubscriptionMetaDTO is the meta-event payload for the streaming /get-stream endpoint. Mirrors SubscriptionDTO minus Members (those arrive as separate member events). The `total` field tells the UI how many member events to expect for progress.
type SubscriptionRejectedDTO ¶
type SubscriptionRejectedDTO struct {
Tag string `json:"tag,omitempty"`
Label string `json:"label,omitempty"`
Protocol string `json:"protocol,omitempty"`
Server string `json:"server,omitempty"`
Port int `json:"port,omitempty"`
Reason string `json:"reason"`
}
SubscriptionRejectedDTO is a parsed share-link that was not added to sing-box.
type SubscriptionResponse ¶
type SubscriptionResponse struct {
Success bool `json:"success" example:"true"`
Data SubscriptionDTO `json:"data"`
}
SubscriptionResponse is the envelope for single-subscription responses.
type SubscriptionStreamDoneDTO ¶
type SubscriptionStreamDoneDTO struct {
OrphanTags []string `json:"orphanTags"`
ActiveMember string `json:"activeMember"`
RejectedMembers []SubscriptionRejectedDTO `json:"rejectedMembers"`
InfoItems []SubscriptionInfoItemDTO `json:"infoItems"`
ExcludedTags []string `json:"excludedTags"`
ExcludedMembers []SubscriptionMemberDTO `json:"excludedMembers,omitempty"`
}
SubscriptionStreamDoneDTO is the done-event payload — finalisation fields that don't fit the meta header but the frontend needs to complete the rendering.
type SubscriptionStreamMemberDTO ¶
type SubscriptionStreamMemberDTO struct {
Index int `json:"index"`
Member SubscriptionMemberDTO `json:"member"`
}
SubscriptionStreamMemberDTO wraps a single member with its index for the member-event payload. Index lets the frontend reason about progress (i+1 / total) and detect gaps if events arrive out of order.
type SubscriptionURLTestDTO ¶
type SubscriptionURLTestDTO struct {
URL string `json:"url" example:"https://www.gstatic.com/generate_204"`
IntervalSec int `json:"intervalSec" example:"60"`
ToleranceMs int `json:"toleranceMs" example:"50"`
}
SubscriptionURLTestDTO carries urltest tuning. Only meaningful when SubscriptionDTO.Mode == "urltest"; when absent or mode is "selector" the consumer should ignore it.
type SuggestAddressData ¶
type SuggestAddressData struct {
Address string `json:"address" example:"10.10.0.1"`
Mask string `json:"mask" example:"255.255.255.0"`
}
SuggestAddressData carries a free private /24 for the create-server UI.
type SuggestAddressResponse ¶
type SuggestAddressResponse struct {
Success bool `json:"success" example:"true"`
Data SuggestAddressData `json:"data"`
}
SuggestAddressResponse is the envelope for GET /managed-servers/suggest-address.
type SystemHandler ¶
type SystemHandler struct {
// contains filtered or unexported fields
}
SystemHandler handles system information endpoints.
func NewSystemHandler ¶
func NewSystemHandler(version string) *SystemHandler
NewSystemHandler creates a new system handler.
func (*SystemHandler) AllInterfaces ¶
func (h *SystemHandler) AllInterfaces(w http.ResponseWriter, r *http.Request)
AllInterfaces returns all router interfaces for routing configuration. GET /api/system/all-interfaces
@Summary All interfaces
@Tags system
@Produce json
@Security CookieAuth
@Success 200 {object} AllInterfacesResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /system/all-interfaces [get]
func (*SystemHandler) BuildSystemInfo ¶
func (h *SystemHandler) BuildSystemInfo() map[string]interface{}
BuildSystemInfo returns system info for SSE snapshot.
func (*SystemHandler) HydraRouteControl ¶
func (h *SystemHandler) HydraRouteControl(w http.ResponseWriter, r *http.Request)
HydraRouteControl starts/stops/restarts the HydraRoute daemon.
@Summary HydraRoute control (system)
@Tags system
@Accept json
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /system/hydraroute-control [post]
func (*SystemHandler) HydraRouteStatus ¶
func (h *SystemHandler) HydraRouteStatus(w http.ResponseWriter, r *http.Request)
HydraRouteStatus returns HydraRoute Neo detection status.
@Summary HydraRoute status (system)
@Tags system
@Produce json
@Security CookieAuth
@Success 200 {object} HydraRouteStatusResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /system/hydraroute-status [get]
func (*SystemHandler) Info ¶
func (h *SystemHandler) Info(w http.ResponseWriter, r *http.Request)
Info returns system information.
@Summary System info
@Tags system
@Produce json
@Security CookieAuth
@Success 200 {object} SystemInfoResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /system/info [get]
func (*SystemHandler) RestartDaemon ¶
func (h *SystemHandler) RestartDaemon(w http.ResponseWriter, r *http.Request)
RestartDaemon triggers a self-restart of the AWG Manager daemon.
@Summary Restart daemon
@Tags system
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /system/restart [post]
func (*SystemHandler) SetActiveBackend ¶
func (h *SystemHandler) SetActiveBackend(b backend.Backend)
SetActiveBackend sets the active backend for status reporting.
func (*SystemHandler) SetBootStatusFunc ¶
func (h *SystemHandler) SetBootStatusFunc(fn func() bool)
SetBootStatusFunc sets the callback to check if boot is in progress.
func (*SystemHandler) SetEventBus ¶
func (h *SystemHandler) SetEventBus(bus *events.Bus)
SetEventBus wires the SSE bus so HR Neo control actions emit `routing.hydrarouteStatus` resource:invalidated hints.
func (*SystemHandler) SetHydraRoute ¶
func (h *SystemHandler) SetHydraRoute(svc *hydraroute.Service)
SetHydraRoute sets the HydraRoute Neo service for status/control endpoints.
func (*SystemHandler) SetKmodLoader ¶
func (h *SystemHandler) SetKmodLoader(l KmodLoader)
SetKmodLoader sets the kernel module loader for status reporting.
func (*SystemHandler) SetNDMSQueries ¶
func (h *SystemHandler) SetNDMSQueries(q *ndmsquery.Queries)
SetNDMSQueries sets the NDMS query registry for the new CQRS layer.
func (*SystemHandler) SetPingCheckService ¶
func (h *SystemHandler) SetPingCheckService(svc PingCheckService)
SetPingCheckService sets the ping check service for stopping monitoring on restart.
func (*SystemHandler) SetRestartFunc ¶
func (h *SystemHandler) SetRestartFunc(fn func())
SetRestartFunc sets the callback to trigger daemon self-restart.
func (*SystemHandler) SetSettingsStore ¶
func (h *SystemHandler) SetSettingsStore(sp SettingsProvider)
SetSettingsStore sets the settings provider.
func (*SystemHandler) SetSettingsWriter ¶
func (h *SystemHandler) SetSettingsWriter(sw *storage.SettingsStore)
SetSettingsWriter sets the writable settings store for saving.
func (*SystemHandler) SetSingboxOperator ¶
func (h *SystemHandler) SetSingboxOperator(op *singbox.Operator)
SetSingboxOperator provides access to the sing-box operator for reporting install status in system info.
func (*SystemHandler) SetSlowRequestThresholdMs ¶
func (h *SystemHandler) SetSlowRequestThresholdMs(ms int)
SetSlowRequestThresholdMs exposes the -slow-request-ms runtime flag to the UI.
func (*SystemHandler) SetTunnelService ¶
func (h *SystemHandler) SetTunnelService(svc TunnelService)
SetTunnelService sets the tunnel service for stopping tunnels on backend change.
func (*SystemHandler) WANInterfaces ¶
func (h *SystemHandler) WANInterfaces(w http.ResponseWriter, r *http.Request)
WANInterfaces returns available WAN interfaces for routing. GET /api/system/wan-interfaces
@Summary WAN interfaces
@Tags system
@Produce json
@Security CookieAuth
@Success 200 {object} WANInterfacesResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /system/wan-interfaces [get]
type SystemInfoBackendAvailability ¶
type SystemInfoBackendAvailability struct {
Nativewg bool `json:"nativewg" example:"true"`
Kernel bool `json:"kernel" example:"false"`
}
SystemInfoBackendAvailability shows which tunnel backends are available.
type SystemInfoData ¶
type SystemInfoData struct {
Version string `json:"version" example:"2.5.0"`
GoVersion string `json:"goVersion" example:"go1.23.0"`
GoArch string `json:"goArch" example:"arm64"`
GoOS string `json:"goOS" example:"linux"`
KeeneticOS string `json:"keeneticOS" example:"ndms"`
IsOS5 bool `json:"isOS5" example:"true"`
FirmwareVersion string `json:"firmwareVersion" example:"4.2.1"`
SupportsExtendedASC bool `json:"supportsExtendedASC" example:"true"`
SupportsHRanges bool `json:"supportsHRanges" example:"true"`
SupportsPingCheck bool `json:"supportsPingCheck" example:"true"`
TotalMemoryMB int `json:"totalMemoryMB" example:"512"`
IsLowMemory bool `json:"isLowMemory" example:"false"`
GcMemLimit string `json:"gcMemLimit" example:"128MiB"`
Gogc string `json:"gogc" example:"25"`
DisableMemorySaving bool `json:"disableMemorySaving" example:"false"`
KernelModuleExists bool `json:"kernelModuleExists" example:"true"`
KernelModuleLoaded bool `json:"kernelModuleLoaded" example:"false"`
KernelModuleModel string `json:"kernelModuleModel" example:"MT7981"`
KernelModuleVersion string `json:"kernelModuleVersion" example:""`
IsAarch64 bool `json:"isAarch64" example:"true"`
ActiveBackend string `json:"activeBackend" example:"nativewg"`
RouterIP string `json:"routerIP" example:"192.168.1.1"`
RouterTime string `json:"routerTime" example:"2026-05-20T14:32:10+03:00"`
RouterTimezone string `json:"routerTimezone" example:"MSK"`
RouterTimezoneOffsetMinutes int `json:"routerTimezoneOffsetMinutes" example:"180"`
BootInProgress bool `json:"bootInProgress" example:"false"`
SlowRequestThresholdMs int `json:"slowRequestThresholdMs" example:"0"`
BackendAvailability SystemInfoBackendAvailability `json:"backendAvailability"`
Singbox SystemInfoSingbox `json:"singbox"`
RouterDetails *RouterDetails `json:"routerDetails,omitempty"`
}
SystemInfoData is the payload returned by GET /system/info.
type SystemInfoResponse ¶
type SystemInfoResponse struct {
Success bool `json:"success" example:"true"`
Data SystemInfoData `json:"data"`
}
SystemInfoResponse is the envelope for GET /system/info.
type SystemInfoSingbox ¶
type SystemInfoSingbox struct {
Installed bool `json:"installed" example:"true"`
Version string `json:"version" example:"1.9.3"`
}
SystemInfoSingbox shows sing-box component info embedded in system info.
type SystemTunnelDTO ¶
type SystemTunnelDTO struct {
ID string `json:"id" example:"Wireguard0"`
InterfaceName string `json:"interfaceName" example:"Wireguard0"`
Description string `json:"description" example:"Home Server"`
Status string `json:"status" example:"up"`
Connected bool `json:"connected" example:"true"`
MTU int `json:"mtu" example:"1420"`
Peer *SystemTunnelPeerDTO `json:"peer,omitempty"`
}
SystemTunnelDTO mirrors frontend SystemTunnel.
type SystemTunnelPeerDTO ¶
type SystemTunnelPeerDTO struct {
PublicKey string `json:"publicKey" example:"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC="`
Endpoint string `json:"endpoint" example:"vpn2.example.com:51820"`
RxBytes int64 `json:"rxBytes" example:"2097152"`
TxBytes int64 `json:"txBytes" example:"1048576"`
LastHandshake string `json:"lastHandshake" example:"2024-01-15T10:30:00Z"`
Online bool `json:"online" example:"true"`
}
SystemTunnelPeerDTO mirrors the peer field in SystemTunnel.
type SystemTunnelsHandler ¶
type SystemTunnelsHandler struct {
// contains filtered or unexported fields
}
SystemTunnelsHandler handles system WireGuard tunnel operations.
func NewSystemTunnelsHandler ¶
func NewSystemTunnelsHandler(svc systemtunnel.Service, settings *storage.SettingsStore, awgStore *storage.AWGTunnelStore, appLogger logging.AppLogger) *SystemTunnelsHandler
NewSystemTunnelsHandler creates a new system tunnels handler.
func (*SystemTunnelsHandler) ASC ¶
func (h *SystemTunnelsHandler) ASC(w http.ResponseWriter, r *http.Request)
ASC handles ASC parameter operations. GET /api/system-tunnels/asc?name=X — read params POST /api/system-tunnels/asc?name=X — write params
func (*SystemTunnelsHandler) CheckConnectivity ¶
func (h *SystemTunnelsHandler) CheckConnectivity(w http.ResponseWriter, r *http.Request)
CheckConnectivity performs connectivity test through system tunnel. GET /api/system-tunnels/test-connectivity?name=Wireguard0
func (*SystemTunnelsHandler) CheckIP ¶
func (h *SystemTunnelsHandler) CheckIP(w http.ResponseWriter, r *http.Request)
CheckIP tests IP through system tunnel. GET /api/system-tunnels/test-ip?name=Wireguard0&service=optional
func (*SystemTunnelsHandler) Get ¶
func (h *SystemTunnelsHandler) Get(w http.ResponseWriter, r *http.Request)
Get returns a single system WireGuard tunnel. GET /api/system-tunnels/get?name=Wireguard0
func (*SystemTunnelsHandler) List ¶
func (h *SystemTunnelsHandler) List(w http.ResponseWriter, r *http.Request)
List returns all visible (non-hidden) system WireGuard tunnels. GET /api/system-tunnels
@Summary List system tunnels
@Description Returns all WireGuard tunnels managed by the router OS itself (non-hidden).
@Tags system-tunnels
@Produce json
@Security CookieAuth
@Success 200 {object} SystemTunnelsResponse
@Failure 500 {object} APIErrorEnvelope
@Router /system-tunnels [get]
func (*SystemTunnelsHandler) SpeedTestStream ¶
func (h *SystemTunnelsHandler) SpeedTestStream(w http.ResponseWriter, r *http.Request)
SpeedTestStream runs iperf3 speed test with SSE streaming through system tunnel. GET /api/system-tunnels/test-speed?name=Wireguard0&server=X&port=N&direction=download|upload
type SystemTunnelsResponse ¶
type SystemTunnelsResponse struct {
Success bool `json:"success" example:"true"`
Data []SystemTunnelDTO `json:"data"`
}
SystemTunnelsResponse is the envelope for GET /system-tunnels.
type TakeGeoFileControlRequest ¶
type TakeGeoFileControlRequest struct {
Path string `json:"path" example:"/opt/etc/HydraRoute/geosite_GA.dat"`
}
TakeGeoFileControlRequest is the body for POST /hydraroute/geo-files/take-control.
type TerminalHandler ¶
type TerminalHandler struct {
// contains filtered or unexported fields
}
TerminalHandler handles terminal API endpoints.
func NewTerminalHandler ¶
func NewTerminalHandler(manager terminal.Manager, log logging.AppLogger) *TerminalHandler
NewTerminalHandler creates a new terminal handler.
func (*TerminalHandler) Install ¶
func (h *TerminalHandler) Install(w http.ResponseWriter, r *http.Request)
Install installs ttyd via opkg. POST /api/terminal/install
@Summary Install terminal (ttyd)
@Tags terminal
@Produce json
@Security CookieAuth
@Success 200 {object} TerminalStatusResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /terminal/install [post]
func (*TerminalHandler) Start ¶
func (h *TerminalHandler) Start(w http.ResponseWriter, r *http.Request)
Start launches the ttyd process. POST /api/terminal/start
@Summary Start terminal
@Tags terminal
@Produce json
@Security CookieAuth
@Success 200 {object} TerminalStartResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /terminal/start [post]
func (*TerminalHandler) Status ¶
func (h *TerminalHandler) Status(w http.ResponseWriter, r *http.Request)
Status returns the current terminal state. GET /api/terminal/status
@Summary Terminal status
@Tags terminal
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope{data=TerminalStatusResponse}
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /terminal/status [get]
func (*TerminalHandler) Stop ¶
func (h *TerminalHandler) Stop(w http.ResponseWriter, r *http.Request)
Stop kills the ttyd process. POST /api/terminal/stop
@Summary Stop terminal
@Tags terminal
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /terminal/stop [post]
func (*TerminalHandler) WebSocket ¶
func (h *TerminalHandler) WebSocket(w http.ResponseWriter, r *http.Request)
WebSocket proxies WebSocket connection to ttyd. GET /api/terminal/ws
@Summary Terminal WebSocket
@Tags terminal
@Produce json
@Security CookieAuth
@Success 200 {string} string "WebSocket upgrade"
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /terminal/ws [get]
type TerminalStartData ¶
type TerminalStartData struct {
Port int `json:"port" example:"7681"`
}
TerminalStartData is the payload returned by POST /terminal/start.
type TerminalStartResponse ¶
type TerminalStartResponse struct {
Success bool `json:"success" example:"true"`
Data TerminalStartData `json:"data"`
}
TerminalStartResponse is the envelope for POST /terminal/start.
type TerminalStatusResponse ¶
type TerminalStatusResponse struct {
Installed bool `json:"installed" example:"true"`
Running bool `json:"running" example:"false"`
SessionActive bool `json:"sessionActive" example:"false"`
}
TerminalStatusResponse represents terminal status.
type TestingHandler ¶
type TestingHandler struct {
// contains filtered or unexported fields
}
TestingHandler handles tunnel testing operations.
func NewTestingHandler ¶
func NewTestingHandler(testingService *testing.Service) *TestingHandler
NewTestingHandler creates a new testing handler.
func (*TestingHandler) CheckConnectivity ¶
func (h *TestingHandler) CheckConnectivity(w http.ResponseWriter, r *http.Request)
CheckConnectivity performs a quick connectivity test through tunnel.
@Summary Connectivity check
@Tags test
@Produce json
@Security CookieAuth
@Param id query string true "Tunnel id"
@Success 200 {object} ConnectivityResultResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /test/connectivity [get]
func (*TestingHandler) CheckIP ¶
func (h *TestingHandler) CheckIP(w http.ResponseWriter, r *http.Request)
CheckIP tests if traffic goes through tunnel by comparing IPs.
@Summary IP leak check
@Tags test
@Produce json
@Security CookieAuth
@Param id query string false "Tunnel id"
@Param service query string false "Check service id"
@Success 200 {object} IPResultResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /test/ip [get]
func (*TestingHandler) IPCheckServices ¶
func (h *TestingHandler) IPCheckServices(w http.ResponseWriter, r *http.Request)
IPCheckServices returns the list of available IP check services.
@Summary IP check services
@Tags test
@Produce json
@Security CookieAuth
@Success 200 {object} IPServicesResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /test/ip/services [get]
func (*TestingHandler) SpeedTest ¶
func (h *TestingHandler) SpeedTest(w http.ResponseWriter, r *http.Request)
SpeedTest runs iperf3 speed test through a tunnel.
@Summary Speed test (sync)
@Tags test
@Produce json
@Security CookieAuth
@Success 200 {object} SpeedTestResultResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /test/speed [get]
func (*TestingHandler) SpeedTestServers ¶
func (h *TestingHandler) SpeedTestServers(w http.ResponseWriter, r *http.Request)
SpeedTestServers returns iperf3 availability and server list.
@Summary Speed test servers
@Tags test
@Produce json
@Security CookieAuth
@Success 200 {object} SpeedTestInfoResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /test/speed/servers [get]
func (*TestingHandler) SpeedTestStream ¶
func (h *TestingHandler) SpeedTestStream(w http.ResponseWriter, r *http.Request)
SpeedTestStream runs iperf3 speed test with SSE streaming of per-second intervals.
@Summary Speed test stream
@Tags test
@Produce text/event-stream
@Security CookieAuth
@Success 200 {string} string "SSE stream"
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /test/speed/stream [get]
type ToggleNDMSProxyRequest ¶
type ToggleNDMSProxyRequest struct {
Enabled bool `json:"enabled"`
}
ToggleNDMSProxyRequest is the body for POST /singbox/ndms-proxy.
type TunnelConnectionInfoDTO ¶
type TunnelConnectionInfoDTO struct {
Name string `json:"name" example:"My VPN"`
Interface string `json:"interface" example:"nwg0"`
Count int `json:"count" example:"12"`
}
TunnelConnectionInfoDTO mirrors frontend TunnelConnectionInfo.
type TunnelControlData ¶
type TunnelControlData struct {
ID string `json:"id" example:"tun_abc123"`
Status string `json:"status" example:"connected"`
}
TunnelControlData is the response data for control operations (start/stop/restart).
type TunnelControlResponse ¶
type TunnelControlResponse struct {
Success bool `json:"success" example:"true"`
Data TunnelControlData `json:"data"`
}
TunnelControlResponse is the envelope for control operations.
type TunnelDeleteResponse ¶
type TunnelDeleteResponse struct {
Success bool `json:"success" example:"true"`
Data TunnelDeleteResultData `json:"data"`
}
TunnelDeleteResponse is the envelope for POST /tunnels/delete.
type TunnelDeleteResultData ¶
type TunnelDeleteResultData struct {
Success bool `json:"success" example:"true"`
TunnelId string `json:"tunnelId" example:"tun_abc123"`
Verified bool `json:"verified" example:"true"`
}
TunnelDeleteResultData mirrors frontend DeleteResult.
type TunnelDetailResponse ¶
type TunnelDetailResponse struct {
Success bool `json:"success" example:"true"`
Data AWGTunnelDTO `json:"data"`
}
TunnelDetailResponse is the envelope for GET /tunnels/get.
type TunnelHookInvalidator ¶
TunnelHookInvalidator is invoked on ifcreated / ifdestroyed hooks so the handler can drop stale NDMS caches and publish a `resource:invalidated` hint for the tunnels resource. Every connected SSE client then refetches `/api/tunnels/all` and the UI drops/adds tunnel cards without a browser refresh.
type TunnelListItemDTO ¶
type TunnelListItemDTO struct {
ID string `json:"id" example:"tun_abc123"`
Name string `json:"name" example:"My AWG Tunnel"`
Type string `json:"type" example:"awg" enums:"awg,wg"`
Status string `json:"status" example:"connected" enums:"connected,disconnected,error,disabled"`
Enabled bool `json:"enabled" example:"true"`
DefaultRoute bool `json:"defaultRoute" example:"false"`
Endpoint string `json:"endpoint" example:"vpn.example.com:51820"`
Address string `json:"address" example:"10.0.0.2/32"`
InterfaceName string `json:"interfaceName,omitempty" example:"nwg0"`
NdmsName string `json:"ndmsName,omitempty" example:"Wireguard0"`
Backend string `json:"backend,omitempty" example:"nativewg" enums:"nativewg,kernel"`
AWGVersion string `json:"awgVersion,omitempty" example:"awg2.0" enums:"wg,awg1.0,awg1.5,awg2.0"`
MTU int `json:"mtu,omitempty" example:"1420"`
IspInterface string `json:"ispInterface,omitempty" example:"PPPoE0"`
IspInterfaceLabel string `json:"ispInterfaceLabel,omitempty" example:"WAN"`
ResolvedIspInterface string `json:"resolvedIspInterface,omitempty" example:"PPPoE0"`
ResolvedIspInterfaceLabel string `json:"resolvedIspInterfaceLabel,omitempty" example:"WAN"`
HasAddressConflict bool `json:"hasAddressConflict,omitempty" example:"false"`
StartedAt string `json:"startedAt,omitempty" example:"2024-01-15T10:00:00Z"`
RxBytes int64 `json:"rxBytes,omitempty" example:"10485760"`
TxBytes int64 `json:"txBytes,omitempty" example:"5242880"`
LastHandshake string `json:"lastHandshake,omitempty" example:"2024-01-15T10:30:00Z"`
PingCheck TunnelPingCheckStatus `json:"pingCheck"`
}
TunnelListItemDTO mirrors frontend TunnelListItem.
type TunnelListResponse ¶
type TunnelListResponse struct {
Success bool `json:"success" example:"true"`
Data []TunnelListItemDTO `json:"data"`
}
TunnelListResponse is the envelope for GET /tunnels/list.
type TunnelPingCheckStatus ¶
type TunnelPingCheckStatus struct {
Status string `json:"status" example:"alive"`
RestartCount int `json:"restartCount" example:"0"`
FailCount int `json:"failCount" example:"0"`
FailThreshold int `json:"failThreshold" example:"3"`
}
TunnelPingCheckStatus is the ping-check status embedded in TunnelListItem.
type TunnelPingStatusDTO ¶
type TunnelPingStatusDTO struct {
TunnelId string `json:"tunnelId" example:"tun_abc123"`
TunnelName string `json:"tunnelName" example:"My VPN"`
Enabled bool `json:"enabled" example:"true"`
Backend string `json:"backend" example:"nativewg"`
Status string `json:"status" example:"alive"`
Method string `json:"method" example:"http"`
LastLatency int `json:"lastLatency" example:"35"`
FailCount int `json:"failCount" example:"0"`
FailThreshold int `json:"failThreshold" example:"3"`
RestartCount int `json:"restartCount" example:"0"`
}
TunnelPingStatusDTO mirrors frontend TunnelPingStatus.
type TunnelReferencedDetails ¶
type TunnelReferencedDetails struct {
TunnelID string `json:"tunnelId" example:"tun-a"`
DeviceProxy bool `json:"deviceProxy" example:"false"`
RouterRules []int `json:"routerRules"`
RouterOther []string `json:"routerOther"`
}
TunnelReferencedDetails describes where a tunnel is still referenced when deletion is refused (HTTP 409).
type TunnelReferencedResponse ¶
type TunnelReferencedResponse struct {
Error string `json:"error" example:"tunnel_referenced"`
Details TunnelReferencedDetails `json:"details"`
}
TunnelReferencedResponse is the HTTP 409 body for POST /tunnels/delete when the tunnel's outbound tag is still referenced by sing-box router or device-proxy config. The client uses details to deeplink the user to the referencing configuration.
type TunnelService ¶
type TunnelService interface {
// CRUD
List(ctx context.Context) ([]service.TunnelWithStatus, error)
Get(ctx context.Context, tunnelID string) (*service.TunnelWithStatus, error)
Create(ctx context.Context, tunnelID, name string, cfg tunnel.Config, stored *storage.AWGTunnel) error
Update(ctx context.Context, oldStored, newStored *storage.AWGTunnel) error
Delete(ctx context.Context, tunnelID string) error
// Lifecycle (delegated to orchestrator)
Start(ctx context.Context, tunnelID string) error
Stop(ctx context.Context, tunnelID string) error
Restart(ctx context.Context, tunnelID string) error
// Validation
CheckAddressConflicts(ctx context.Context, tunnelID string) []string
// State
GetState(ctx context.Context, tunnelID string) tunnel.StateInfo
// Settings
SetEnabled(ctx context.Context, tunnelID string, enabled bool) error
SetDefaultRoute(ctx context.Context, tunnelID string, enabled bool) error
// Import
Import(ctx context.Context, confContent, name, backend string) (*service.TunnelWithStatus, error)
// ReplaceConfig replaces a tunnel's config from a new .conf file.
ReplaceConfig(ctx context.Context, tunnelID, confContent, newName string) error
// WAN state model
WANModel() *wan.Model
// Resolved ISP for auto-mode tunnels
GetResolvedISP(tunnelID string) string
// SetSelfCreateGate wires the gate used by import/create paths to
// suppress hook-driven snapshot refreshes while an NDMS interface is
// being created but our store.Save hasn't run yet.
SetSelfCreateGate(g tunnel.SelfCreateGater)
}
TunnelService defines the interface for tunnel operations used by API handlers.
type TunnelStateInfoDTO ¶
type TunnelStateInfoDTO struct {
State int `json:"state" example:"3"`
InterfaceUp bool `json:"interfaceUp" example:"true"`
ProcessRunning bool `json:"processRunning" example:"true"`
HasHandshake bool `json:"hasHandshake" example:"true"`
LastHandshake string `json:"lastHandshake" example:"2024-01-15T10:30:00Z"`
RxBytes int64 `json:"rxBytes" example:"10485760"`
TxBytes int64 `json:"txBytes" example:"5242880"`
}
TunnelStateInfoDTO mirrors frontend TunnelStateInfo.
type TunnelTrafficData ¶
type TunnelTrafficData struct {
Points []TunnelTrafficPoint `json:"points"`
Stats TunnelTrafficStats `json:"stats"`
}
TunnelTrafficData is the payload for GET /tunnels/traffic.
type TunnelTrafficPoint ¶
type TunnelTrafficPoint struct {
T int64 `json:"t" example:"1705312200"`
Rx int64 `json:"rx" example:"1024000"`
Tx int64 `json:"tx" example:"512000"`
}
TunnelTrafficPoint is one point in a traffic chart.
type TunnelTrafficResponse ¶
type TunnelTrafficResponse struct {
Success bool `json:"success" example:"true"`
Data TunnelTrafficData `json:"data"`
}
TunnelTrafficResponse is the envelope for GET /tunnels/traffic.
type TunnelTrafficStats ¶
type TunnelTrafficStats struct {
Points int `json:"points" example:"60"`
PeakRate float64 `json:"peakRate" example:"1048576"`
AvgRx float64 `json:"avgRx" example:"524288"`
AvgTx float64 `json:"avgTx" example:"262144"`
CurrentRx float64 `json:"currentRx" example:"102400"`
CurrentTx float64 `json:"currentTx" example:"51200"`
// VolumeRx is estimated bytes received over the selected window (Σ rxRate×Δt on raw history samples).
VolumeRx int64 `json:"volumeRx" example:"1073741824"`
// VolumeTx is estimated bytes sent over the selected window (Σ txRate×Δt on raw history samples).
VolumeTx int64 `json:"volumeTx" example:"536870912"`
}
TunnelTrafficStats are aggregate stats for a traffic period.
type TunnelsAllResponse ¶
type TunnelsAllResponse struct {
Success bool `json:"success" example:"true"`
Data TunnelsAllSnapshotData `json:"data"`
}
TunnelsAllResponse is the envelope for GET /tunnels/all.
type TunnelsAllSnapshotData ¶
type TunnelsAllSnapshotData struct {
Tunnels []TunnelListItemDTO `json:"tunnels"`
External []ExternalTunnelDTO `json:"external"`
System []SystemTunnelDTO `json:"system"`
}
TunnelsAllSnapshotData is the payload for GET /tunnels/all.
type TunnelsHandler ¶
type TunnelsHandler struct {
// contains filtered or unexported fields
}
TunnelsHandler handles tunnel CRUD operations.
func NewTunnelsHandler ¶
func NewTunnelsHandler(svc TunnelService, store *storage.AWGTunnelStore, appLogger logging.AppLogger) *TunnelsHandler
NewTunnelsHandler creates a new tunnels handler.
func (*TunnelsHandler) Create ¶
func (h *TunnelsHandler) Create(w http.ResponseWriter, r *http.Request)
Create creates a new tunnel.
@Summary Create tunnel
@Tags tunnels
@Accept json
@Produce json
@Security CookieAuth
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /tunnels/create [post]
func (*TunnelsHandler) Delete ¶
func (h *TunnelsHandler) Delete(w http.ResponseWriter, r *http.Request)
Delete deletes a tunnel.
@Summary Delete tunnel
@Tags tunnels
@Produce json
@Security CookieAuth
@Param id query string true "Tunnel id"
@Success 200 {object} TunnelDeleteResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 409 {object} TunnelReferencedResponse
@Failure 500 {object} APIErrorEnvelope
@Router /tunnels/delete [post]
func (*TunnelsHandler) Export ¶
func (h *TunnelsHandler) Export(w http.ResponseWriter, r *http.Request)
Export returns a single tunnel config as a downloadable .conf file.
@Summary Export tunnel config
@Tags tunnels
@Produce plain
@Security CookieAuth
@Param id query string true "Tunnel id"
@Success 200 {file} binary
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /tunnels/export [get]
func (*TunnelsHandler) ExportAll ¶
func (h *TunnelsHandler) ExportAll(w http.ResponseWriter, r *http.Request)
ExportAll returns all tunnel configs as a downloadable ZIP archive.
@Summary Export all tunnels (zip)
@Tags tunnels
@Produce application/zip
@Security CookieAuth
@Success 200 {file} binary
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /tunnels/export-all [get]
func (*TunnelsHandler) Get ¶
func (h *TunnelsHandler) Get(w http.ResponseWriter, r *http.Request)
Get returns a single tunnel by ID.
@Summary Get tunnel
@Tags tunnels
@Produce json
@Security CookieAuth
@Param id query string true "Tunnel id"
@Success 200 {object} TunnelDetailResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /tunnels/get [get]
func (*TunnelsHandler) GetAll ¶
func (h *TunnelsHandler) GetAll(w http.ResponseWriter, r *http.Request)
GetAll returns the composite tunnels snapshot ({tunnels, external, system}) the frontend polls instead of listening to a legacy snapshot SSE event. GET /api/tunnels/all
@Summary Composite tunnels snapshot
@Tags tunnels
@Produce json
@Security CookieAuth
@Success 200 {object} TunnelsAllResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /tunnels/all [get]
func (*TunnelsHandler) List ¶
func (h *TunnelsHandler) List(w http.ResponseWriter, r *http.Request)
List returns all tunnels.
@Summary List tunnels
@Tags tunnels
@Produce json
@Security CookieAuth
@Success 200 {object} TunnelListResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /tunnels/list [get]
func (*TunnelsHandler) PublishTunnelList ¶
func (h *TunnelsHandler) PublishTunnelList(ctx context.Context)
PublishTunnelList emits resource:invalidated hints for tunnels and routing.tunnels so polling stores refetch immediately. Exported for cross-handler use (Import, ExternalAdopt, Control).
func (*TunnelsHandler) ReplaceConf ¶
func (h *TunnelsHandler) ReplaceConf(w http.ResponseWriter, r *http.Request)
ReplaceConf replaces a tunnel's configuration from a new .conf file. If the tunnel is running, it is stopped before replacement and restarted after.
@Summary Replace tunnel from conf
@Tags tunnels
@Accept json
@Produce json
@Security CookieAuth
@Param id query string true "Tunnel id"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /tunnels/replace [post]
func (*TunnelsHandler) SetCatalog ¶
func (h *TunnelsHandler) SetCatalog(cat routing.Catalog)
SetCatalog sets the routing catalog for tunnel list updates.
func (*TunnelsHandler) SetEventBus ¶
func (h *TunnelsHandler) SetEventBus(bus *events.Bus)
SetEventBus sets the event bus for SSE publishing.
func (*TunnelsHandler) SetOrchestrator ¶
func (h *TunnelsHandler) SetOrchestrator(orch *orchestrator.Orchestrator)
SetOrchestrator sets the orchestrator for lifecycle operations.
func (*TunnelsHandler) SetPingCheckService ¶
func (h *TunnelsHandler) SetPingCheckService(svc PingCheckService)
SetPingCheckService sets the ping check service for monitoring control.
func (*TunnelsHandler) SetPingCheckSnapshot ¶
func (h *TunnelsHandler) SetPingCheckSnapshot(fn func())
SetPingCheckSnapshot sets the function that publishes a pingcheck snapshot.
func (*TunnelsHandler) SetSelfCreateGate ¶
func (h *TunnelsHandler) SetSelfCreateGate(g tunnel.SelfCreateGater)
SetSelfCreateGate wires the gate used to suppress hook-driven snapshot refreshes while the handler itself is creating an NDMS interface (manual Create path — import path gates inside ServiceImpl directly).
func (*TunnelsHandler) SetSettingsStore ¶
func (h *TunnelsHandler) SetSettingsStore(store *storage.SettingsStore)
SetSettingsStore sets the settings store for reading defaults.
func (*TunnelsHandler) SetTrafficHistory ¶
func (h *TunnelsHandler) SetTrafficHistory(th *traffic.History)
SetTrafficHistory sets the traffic history accumulator.
func (*TunnelsHandler) SetTunnelsSnapshotBuilder ¶
func (h *TunnelsHandler) SetTunnelsSnapshotBuilder(fn func(ctx context.Context) map[string]interface{})
SetTunnelsSnapshotBuilder wires the composer used by GetAll and mutation handlers that return fresh snapshot state. Server.go typically injects TunnelsSnapshotBuilder.Build.
func (*TunnelsHandler) Traffic ¶
func (h *TunnelsHandler) Traffic(w http.ResponseWriter, r *http.Request)
Traffic returns rate history + aggregates for a single tunnel. GET /api/tunnels/traffic?id=<tunnelID>&period=5m|10m|30m|1h|3h|6h|12h|24h
Only a fixed set of short/long-range presets is accepted — anything else returns 400. 1h is what the card chart fetches on mount to backfill before SSE takes over; the detail modal can request any of the supported presets.
data.stats.volumeRx and data.stats.volumeTx are byte estimates for the selected window from raw in-memory samples (zero if fewer than two samples).
@Summary Tunnel traffic history
@Tags tunnels
@Produce json
@Security CookieAuth
@Param id query string true "Tunnel id"
@Param period query string true "5m, 10m, 30m, 1h, 3h, 6h, 12h, or 24h"
@Success 200 {object} TunnelTrafficResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /tunnels/traffic [get]
func (*TunnelsHandler) Update ¶
func (h *TunnelsHandler) Update(w http.ResponseWriter, r *http.Request)
Update updates an existing tunnel.
@Summary Update tunnel
@Tags tunnels
@Accept json
@Produce json
@Security CookieAuth
@Param id query string true "Tunnel id"
@Success 200 {object} APIEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /tunnels/update [post]
type TunnelsSnapshotBuilder ¶
type TunnelsSnapshotBuilder struct {
// contains filtered or unexported fields
}
TunnelsSnapshotBuilder composes the {tunnels, external, system} payload used by GET /api/tunnels/all and by the hook-driven resource:invalidated refresher. It is the single assembly point for the composite tunnels list the polling store reads.
The struct is a thin holder for the three handler references; callers wire whichever handlers are available and call Build. Missing handlers produce empty slices in the relevant keys.
func NewTunnelsSnapshotBuilder ¶
func NewTunnelsSnapshotBuilder() *TunnelsSnapshotBuilder
NewTunnelsSnapshotBuilder creates a new builder with no handlers wired. Use the setters to wire the three handler references.
func (*TunnelsSnapshotBuilder) Build ¶
func (b *TunnelsSnapshotBuilder) Build(ctx context.Context) map[string]interface{}
Build composes the snapshot payload for the polling store. Returns nil when no TunnelsHandler is wired, or when its listItems call errors — in both cases there's nothing safe to return.
func (*TunnelsSnapshotBuilder) SetExternalHandler ¶
func (b *TunnelsSnapshotBuilder) SetExternalHandler(h *ExternalTunnelsHandler)
SetExternalHandler sets the external tunnels handler reference.
func (*TunnelsSnapshotBuilder) SetSystemTunnelsHandler ¶
func (b *TunnelsSnapshotBuilder) SetSystemTunnelsHandler(h *SystemTunnelsHandler)
SetSystemTunnelsHandler sets the system tunnels handler reference.
func (*TunnelsSnapshotBuilder) SetTunnelsHandler ¶
func (b *TunnelsSnapshotBuilder) SetTunnelsHandler(h *TunnelsHandler)
SetTunnelsHandler sets the tunnels handler reference.
type UpdateApplyData ¶
type UpdateApplyData struct {
Status string `json:"status" example:"updating"`
}
UpdateApplyData is the payload for POST /system/update/apply.
type UpdateApplyResponse ¶
type UpdateApplyResponse struct {
Success bool `json:"success" example:"true"`
Data UpdateApplyData `json:"data"`
}
UpdateApplyResponse is the envelope for POST /system/update/apply.
type UpdateCheckResponse ¶
type UpdateCheckResponse struct {
Success bool `json:"success" example:"true"`
Data UpdateInfoData `json:"data"`
}
UpdateCheckResponse is the envelope for GET /system/update/check.
type UpdateGeoFileRequest ¶
type UpdateGeoFileRequest struct {
Path string `json:"path" example:"/opt/etc/hrneo/geosite.db"`
Route *DownloadRouteDTO `json:"route,omitempty"`
}
UpdateGeoFileRequest is the body for POST /hydraroute/geo-files/update. Empty path triggers a bulk refresh of every tracked geo file.
type UpdateHandler ¶
type UpdateHandler struct {
// contains filtered or unexported fields
}
UpdateHandler handles update check and apply endpoints.
func NewUpdateHandler ¶
func NewUpdateHandler(updater *updater.Service, appLogger logging.AppLogger) *UpdateHandler
NewUpdateHandler creates a new update handler.
func (*UpdateHandler) Apply ¶
func (h *UpdateHandler) Apply(w http.ResponseWriter, r *http.Request)
Apply starts the opkg upgrade process. POST /api/system/update/apply
@Summary Apply system update
@Tags update
@Produce json
@Security CookieAuth
@Success 200 {object} UpdateApplyResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /system/update/apply [post]
func (*UpdateHandler) Changelog ¶
func (h *UpdateHandler) Changelog(w http.ResponseWriter, r *http.Request)
Changelog returns changelog entries. Two modes:
- Range: from and to both supplied → entries in (from, to], newest-first.
- Minor line: only to supplied → all entries with the same major.minor as to, with version <= to (used when no upgrade is pending).
GET /api/system/update/changelog?from=2.7.5&to=2.8.0 GET /api/system/update/changelog?to=2.8.1
@Summary Update changelog
@Tags update
@Produce json
@Security CookieAuth
@Param from query string false "From version"
@Param to query string true "To version"
@Success 200 {object} ChangelogResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /system/update/changelog [get]
func (*UpdateHandler) Check ¶
func (h *UpdateHandler) Check(w http.ResponseWriter, r *http.Request)
Check returns cached update info or triggers a fresh check. GET /api/system/update/check?force=true
@Summary Update check
@Tags update
@Produce json
@Security CookieAuth
@Param force query boolean false "Force refresh from upstream"
@Success 200 {object} UpdateCheckResponse
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /system/update/check [get]
type UpdateInfoData ¶
type UpdateInfoData struct {
Available bool `json:"available" example:"false"`
CurrentVersion string `json:"currentVersion" example:"2.5.0"`
LatestVersion string `json:"latestVersion,omitempty" example:"2.5.0"`
CheckedAt string `json:"checkedAt" example:"2024-01-15T10:00:00Z"`
Checking bool `json:"checking" example:"false"`
}
UpdateInfoData mirrors frontend UpdateInfo.
type UpdatePeerRequestDTO ¶
type UpdatePeerRequestDTO struct {
Description string `json:"description" example:"My Phone"`
TunnelIP string `json:"tunnelIP" example:"10.10.0.2/32"`
DNS string `json:"dns,omitempty" example:"8.8.8.8"`
}
UpdatePeerRequestDTO is the swagger-visible body for PUT /managed-servers/{id}/peers/{pubkey}.
type UpdateServerRequestDTO ¶
type UpdateServerRequestDTO struct {
Address string `json:"address" example:"10.10.0.1"`
Mask string `json:"mask" example:"255.255.255.0"`
ListenPort int `json:"listenPort" example:"51821"`
Description *string `json:"description,omitempty" example:"My WG Server"`
Endpoint *string `json:"endpoint,omitempty" example:"203.0.113.42:51821"`
DNS *string `json:"dns,omitempty" example:"8.8.8.8"`
MTU *int `json:"mtu,omitempty" example:"1420"`
}
UpdateServerRequestDTO is the swagger-visible body for PUT /managed-servers/{id}.
type UpdateSettingsDTO ¶
type UpdateSettingsDTO struct {
CheckEnabled bool `json:"checkEnabled" example:"true"`
Channel string `json:"channel" example:"stable" enums:"stable,develop"`
}
UpdateSettingsDTO mirrors frontend UpdateSettings.
type UpdateSubscriptionRequest ¶
type UpdateSubscriptionRequest struct {
Label *string `json:"label,omitempty" example:"Demo Provider Updated"`
URL *string `json:"url,omitempty" example:"https://example.com/subscriptions/demo.txt"`
Headers *[]SubscriptionHeader `json:"headers,omitempty"`
RefreshHours *int `json:"refreshHours,omitempty"`
Enabled *bool `json:"enabled,omitempty"`
Mode *string `json:"mode,omitempty" example:"selector"`
URLTest *SubscriptionURLTestDTO `json:"urlTest,omitempty"`
}
UpdateSubscriptionRequest is the body for PUT /api/singbox/subscriptions/update. All fields are optional; absent fields leave the stored value unchanged.
type WANHandler ¶
type WANHandler struct {
// contains filtered or unexported fields
}
WANHandler serves WAN status queries. WAN up/down events are handled by HookHandler (/api/hook/ndms layer=ipv4).
func NewWANHandler ¶
func NewWANHandler(svc TunnelService, appLogger logging.AppLogger) *WANHandler
NewWANHandler creates a new WAN status handler.
func (*WANHandler) GetStatus ¶
func (h *WANHandler) GetStatus(w http.ResponseWriter, r *http.Request)
GetStatus returns current WAN interface state. GET /api/wan/status
@Summary WAN status
@Tags wan
@Produce json
@Security CookieAuth
@Success 200 {object} WANStatusEnvelope
@Failure 400 {object} APIErrorEnvelope
@Failure 500 {object} APIErrorEnvelope
@Router /wan/status [get]
type WANIPData ¶
type WANIPData struct {
IP string `json:"ip" example:"203.0.113.42"`
}
WANIPData is the data for GET /servers/wan-ip.
type WANIPResponse ¶
type WANIPResponse struct {
Success bool `json:"success" example:"true"`
Data WANIPData `json:"data"`
}
WANIPResponse is the envelope for GET /servers/wan-ip.
type WANInterfaceDTO ¶
type WANInterfaceDTO struct {
Name string `json:"name" example:"ISP1"`
Label string `json:"label" example:"Home Internet"`
State string `json:"state" example:"up"`
}
WANInterfaceDTO mirrors frontend WANInterface.
type WANInterfaceStatusDTO ¶
type WANInterfaceStatusDTO struct {
Up bool `json:"up" example:"true"`
Label string `json:"label" example:"Home Internet"`
}
WANInterfaceStatusDTO is a single WAN interface status.
type WANInterfaceStatusItemDTO ¶
type WANInterfaceStatusItemDTO struct {
Up bool `json:"up" example:"true"`
Label string `json:"label" example:"Home Internet"`
}
WANInterfaceStatusDTO is a single WAN interface status entry.
type WANInterfacesResponse ¶
type WANInterfacesResponse struct {
Success bool `json:"success" example:"true"`
Data []WANInterfaceDTO `json:"data"`
}
WANInterfacesResponse is the envelope for GET /system/wan-interfaces.
type WANStatusEnvelope ¶
type WANStatusEnvelope struct {
Success bool `json:"success" example:"true"`
Data struct {
AnyWANUp bool `json:"anyWANUp" example:"true"`
} `json:"data"`
}
WANStatusEnvelope is the swagger-friendly envelope for GET /wan/status. (The actual handler uses the local WANStatusResponse which embeds wanpkg types.)
type WANStatusResponse ¶
type WANStatusResponse struct {
Interfaces map[string]wanpkg.InterfaceStatus `json:"interfaces"`
AnyWANUp bool `json:"anyWANUp"`
}
WANStatusResponse is the response format for WAN status queries.
type WireguardServerConfigDTO ¶
type WireguardServerConfigDTO struct {
PublicKey string `json:"publicKey" example:"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE="`
ListenPort int `json:"listenPort" example:"51820"`
MTU int `json:"mtu" example:"1420"`
Address string `json:"address" example:"10.0.1.1"`
Peers []WireguardServerConfigPeerDTO `json:"peers"`
}
WireguardServerConfigDTO mirrors frontend WireguardServerConfig.
type WireguardServerConfigPeerDTO ¶
type WireguardServerConfigPeerDTO struct {
PublicKey string `json:"publicKey" example:"DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD="`
Description string `json:"description" example:"Phone"`
AllowedIPs []string `json:"allowedIPs" example:"10.0.1.2/32"`
Address string `json:"address" example:"10.0.1.2"`
}
WireguardServerConfigPeerDTO mirrors frontend WireguardServerPeerConfig.
type WireguardServerDTO ¶
type WireguardServerDTO struct {
ID string `json:"id" example:"Wireguard0"`
InterfaceName string `json:"interfaceName" example:"Wireguard0"`
Description string `json:"description" example:"Wireguard VPN Server"`
Status string `json:"status" example:"up"`
Connected bool `json:"connected" example:"true"`
MTU int `json:"mtu" example:"1420"`
Address string `json:"address" example:"10.0.1.1"`
Mask string `json:"mask" example:"255.255.255.0"`
PublicKey string `json:"publicKey" example:"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE="`
ListenPort int `json:"listenPort" example:"51820"`
Peers []WireguardServerPeerDTO `json:"peers"`
NATEnabled bool `json:"natEnabled,omitempty" example:"true"`
NATMode string `json:"natMode,omitempty" example:"full"`
Policy string `json:"policy,omitempty" example:"Policy0"`
KeenDNSDomain string `json:"keenDnsDomain,omitempty" example:"home.keenetic.pro"`
// Endpoint is the user-configured connect host for client .conf files.
// Empty = WAN IP at generation time.
Endpoint string `json:"endpoint,omitempty" example:"203.0.113.42"`
BuiltIn bool `json:"builtIn,omitempty" example:"true"`
// NATModeKnown/PolicyKnown are false when the corresponding NDMS read
// failed (e.g. transient router error). The frontend must render an
// "unknown" state instead of trusting the zero-valued NATMode/Policy,
// which would otherwise read as a fabricated "none".
NATModeKnown bool `json:"natModeKnown" example:"true"`
PolicyKnown bool `json:"policyKnown" example:"true"`
// Enabled reflects NDMS admin intent (summary.layer.conf == "running").
// Status/connected alone are unreliable for the on/off toggle.
Enabled bool `json:"enabled" example:"true"`
EnabledKnown bool `json:"enabledKnown" example:"true"`
}
WireguardServerDTO mirrors frontend WireguardServer.
type WireguardServerPeerDTO ¶
type WireguardServerPeerDTO struct {
PublicKey string `json:"publicKey" example:"DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD="`
Description string `json:"description" example:"Phone"`
Endpoint string `json:"endpoint" example:"1.2.3.4:12345"`
AllowedIPs []string `json:"allowedIPs" example:"10.0.1.2/32"`
RxBytes int64 `json:"rxBytes" example:"1048576"`
TxBytes int64 `json:"txBytes" example:"524288"`
LastHandshake string `json:"lastHandshake" example:"2024-01-15T10:30:00Z"`
Online bool `json:"online" example:"true"`
Enabled bool `json:"enabled" example:"true"`
ConfAvailable bool `json:"confAvailable,omitempty" example:"true"`
}
WireguardServerPeerDTO mirrors frontend WireguardServerPeer.
Source Files
¶
- accesspolicy.go
- amnezia_cp.go
- amnezia_cp_dto.go
- api_common.go
- auth.go
- awg_outbounds.go
- bootstatus.go
- clientroutes.go
- connections.go
- control.go
- deviceproxy.go
- diagnostics.go
- dns_proxy_info.go
- dns_rewrites.go
- dnscheck.go
- dnsroute.go
- download.go
- events.go
- external.go
- health.go
- helpers.go
- hook.go
- hydraroute.go
- import.go
- logging.go
- managed.go
- managed_backup.go
- managed_peers.go
- monitoring.go
- ndms.go
- pingcheck.go
- presets.go
- publish.go
- referenced.go
- resolve.go
- routing.go
- server_peers.go
- servers.go
- servers_settings.go
- settings.go
- signature.go
- singbox.go
- singbox_clash.go
- singbox_config.go
- singbox_connections.go
- singbox_fakeip_config.go
- singbox_inspector.go
- singbox_proxies.go
- singbox_router.go
- singbox_router_dns.go
- snapshot.go
- staticroute.go
- subscription.go
- system.go
- systemtunnels.go
- terminal.go
- testing.go
- tunnels.go
- update.go
- wan.go