123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- package upstream
- import (
- "net/http"
- "sort"
- "github.com/0xJacky/Nginx-UI/internal/upstream"
- "github.com/0xJacky/Nginx-UI/model"
- "github.com/0xJacky/Nginx-UI/query"
- "github.com/gin-gonic/gin"
- "github.com/uozi-tech/cosy"
- "github.com/uozi-tech/cosy/logger"
- )
- // SocketInfo represents a socket with its configuration and health status
- type SocketInfo struct {
- Socket string `json:"socket"` // host:port
- Host string `json:"host"` // hostname/IP
- Port string `json:"port"` // port number
- Type string `json:"type"` // proxy_pass, grpc_pass, or upstream
- IsConsul bool `json:"is_consul"` // whether this is a consul service
- UpstreamName string `json:"upstream_name"` // which upstream this belongs to (if any)
- LastCheck string `json:"last_check"` // last time health check was performed
- Status *upstream.Status `json:"status"` // health check status
- Enabled bool `json:"enabled"` // whether health check is enabled
- }
- // GetSocketList returns all sockets with their configuration and health status
- func GetSocketList(c *gin.Context) {
- service := upstream.GetUpstreamService()
- // Get all target infos
- targets := service.GetTargetInfos()
- // Get availability map
- availabilityMap := service.GetAvailabilityMap()
- // Get all socket configurations from database
- u := query.UpstreamConfig
- configs, err := u.Find()
- if err != nil {
- cosy.ErrHandler(c, err)
- return
- }
- // Create a map for quick lookup of enabled status
- configMap := make(map[string]bool)
- for _, config := range configs {
- configMap[config.Socket] = config.Enabled
- }
- // Build response
- result := make([]SocketInfo, 0, len(targets))
- for _, target := range targets {
- socketAddr := formatSocketAddress(target.Host, target.Port)
- // Get enabled status from database, default to true if not found
- enabled := true
- if val, exists := configMap[socketAddr]; exists {
- enabled = val
- }
- // Get health status
- var status *upstream.Status
- if s, exists := availabilityMap[socketAddr]; exists {
- status = s
- }
- // Find which upstream this belongs to
- upstreamName := findUpstreamForSocket(service, target.ProxyTarget)
- info := SocketInfo{
- Socket: socketAddr,
- Host: target.Host,
- Port: target.Port,
- Type: target.Type,
- IsConsul: target.IsConsul,
- UpstreamName: upstreamName,
- LastCheck: target.LastSeen.Format("2006-01-02 15:04:05"),
- Status: status,
- Enabled: enabled,
- }
- result = append(result, info)
- }
- // Sort by socket address for stable ordering
- sort.Slice(result, func(i, j int) bool {
- return result[i].Socket < result[j].Socket
- })
- c.JSON(http.StatusOK, gin.H{
- "data": result,
- })
- }
- // UpdateSocketConfigRequest represents the request body for updating socket config
- type UpdateSocketConfigRequest struct {
- Enabled bool `json:"enabled"`
- }
- // UpdateSocketConfig updates the enabled status of a socket
- func UpdateSocketConfig(c *gin.Context) {
- socket := c.Param("socket")
- var req UpdateSocketConfigRequest
- if err := c.ShouldBindJSON(&req); err != nil {
- cosy.ErrHandler(c, err)
- return
- }
- u := query.UpstreamConfig
- // Check if config exists
- config, err := u.Where(u.Socket.Eq(socket)).First()
- if err != nil {
- // Create new config if not found
- config = &model.UpstreamConfig{
- Socket: socket,
- Enabled: req.Enabled,
- }
- if err := u.Create(config); err != nil {
- logger.Error("Failed to create socket config:", err)
- cosy.ErrHandler(c, err)
- return
- }
- // Invalidate cache after creating new config
- service := upstream.GetUpstreamService()
- service.InvalidateDisabledSocketsCache()
- } else {
- // Update existing config
- if _, err := u.Where(u.Socket.Eq(socket)).Update(u.Enabled, req.Enabled); err != nil {
- logger.Error("Failed to update socket config:", err)
- cosy.ErrHandler(c, err)
- return
- }
- }
- // Invalidate the disabled sockets cache to ensure changes take effect immediately
- service := upstream.GetUpstreamService()
- service.InvalidateDisabledSocketsCache()
- c.JSON(http.StatusOK, gin.H{
- "message": "Socket config updated successfully",
- })
- }
- // findUpstreamForSocket finds which upstream a socket belongs to
- func findUpstreamForSocket(service *upstream.Service, target upstream.ProxyTarget) string {
- socketAddr := formatSocketAddress(target.Host, target.Port)
- upstreams := service.GetAllUpstreamDefinitions()
- for name, upstream := range upstreams {
- for _, server := range upstream.Servers {
- serverAddr := formatSocketAddress(server.Host, server.Port)
- if serverAddr == socketAddr {
- return name
- }
- }
- }
- return ""
- }
|