Files
Wormhole/internal/api/domain_forwards.go
T
rose_cat707 612d68f56f feat: Wormhole 内网穿透与反向代理网关
Go + Vue 管理台,SQLite 持久化;支持隧道/域名穿透、域名转发插件链、访客认证、
IP 规则、API Key、Docker 单镜像部署;配置通过 Web 系统设置管理,无需 YAML 文件。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 12:15:02 +08:00

145 lines
4.2 KiB
Go

package api
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/wormhole/wormhole/internal/auth"
"github.com/wormhole/wormhole/internal/forwardplugin"
"github.com/wormhole/wormhole/internal/store"
)
func (s *Server) listDomainForwards(c *gin.Context) {
if !auth.IsAdmin(getClaims(c).Role) {
c.JSON(http.StatusForbidden, gin.H{"error": "admin only"})
return
}
p := pageParams(c)
items, total, err := s.store.ListDomainForwardsPaged(p)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"items": items, "total": total})
}
func (s *Server) createDomainForward(c *gin.Context) {
if !auth.IsAdmin(getClaims(c).Role) {
c.JSON(http.StatusForbidden, gin.H{"error": "admin only"})
return
}
var req store.DomainForward
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "bad request"})
return
}
if err := store.ValidateDomainForward(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := s.store.RouteConflict(req.SourceHost, req.SourceLocation, 0, 0); err != nil {
c.JSON(http.StatusConflict, gin.H{"error": err.Error()})
return
}
if err := s.store.CreateDomainForward(&req); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
s.cache.UpsertDomainForward(&req)
c.JSON(http.StatusOK, req)
}
func (s *Server) updateDomainForward(c *gin.Context) {
if !auth.IsAdmin(getClaims(c).Role) {
c.JSON(http.StatusForbidden, gin.H{"error": "admin only"})
return
}
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
existing, err := s.store.GetDomainForwardByID(uint(id))
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
return
}
var req store.DomainForward
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "bad request"})
return
}
req.ID = existing.ID
if req.Socks5Pass == "" {
req.Socks5Pass = existing.Socks5Pass
}
if req.HTTPProxyPass == "" {
req.HTTPProxyPass = existing.HTTPProxyPass
}
if err := store.ValidateDomainForward(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := s.store.RouteConflict(req.SourceHost, req.SourceLocation, uint(id), 0); err != nil {
c.JSON(http.StatusConflict, gin.H{"error": err.Error()})
return
}
if err := s.store.UpdateDomainForward(&req); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
forwardplugin.InvalidateForwardCache(uint(id))
s.cache.UpsertDomainForward(&req)
c.JSON(http.StatusOK, req)
}
func (s *Server) deleteDomainForward(c *gin.Context) {
if !auth.IsAdmin(getClaims(c).Role) {
c.JSON(http.StatusForbidden, gin.H{"error": "admin only"})
return
}
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
if _, err := s.store.GetDomainForwardByID(uint(id)); err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
return
}
if err := s.store.DeleteDomainForward(uint(id)); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
forwardplugin.InvalidateForwardCache(uint(id))
s.cache.DeleteDomainForward(uint(id))
c.JSON(http.StatusOK, gin.H{"ok": true})
}
func (s *Server) pauseDomainForward(c *gin.Context) {
if !auth.IsAdmin(getClaims(c).Role) {
c.JSON(http.StatusForbidden, gin.H{"error": "admin only"})
return
}
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
existing, err := s.store.GetDomainForwardByID(uint(id))
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
return
}
existing.Status = false
_ = s.store.UpdateDomainForward(existing)
s.cache.UpsertDomainForward(existing)
c.JSON(http.StatusOK, gin.H{"ok": true})
}
func (s *Server) resumeDomainForward(c *gin.Context) {
if !auth.IsAdmin(getClaims(c).Role) {
c.JSON(http.StatusForbidden, gin.H{"error": "admin only"})
return
}
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
existing, err := s.store.GetDomainForwardByID(uint(id))
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
return
}
existing.Status = true
_ = s.store.UpdateDomainForward(existing)
s.cache.UpsertDomainForward(existing)
c.JSON(http.StatusOK, gin.H{"ok": true})
}