fix error response for web APIs

This commit is contained in:
ginuerzh 2024-06-04 22:05:13 +08:00
parent 754b2fdeac
commit 118ee91c95
31 changed files with 730 additions and 249 deletions

View File

@ -169,6 +169,10 @@ func registerConfig(config *gin.RouterGroup) {
config.PUT("/observers/:observer", updateObserver) config.PUT("/observers/:observer", updateObserver)
config.DELETE("/observers/:observer", deleteObserver) config.DELETE("/observers/:observer", deleteObserver)
config.POST("/recorders", createRecorder)
config.PUT("/recorders/:recorder", updateRecorder)
config.DELETE("/recorders/:recorder", deleteRecorder)
config.POST("/sds", createSD) config.POST("/sds", createSD)
config.PUT("/sds/:sd", updateSD) config.PUT("/sds/:sd", updateSD)
config.DELETE("/sds/:sd", deleteSD) config.DELETE("/sds/:sd", deleteSD)

View File

@ -144,7 +144,7 @@ func saveConfig(ctx *gin.Context) {
if err != nil { if err != nil {
writeError(ctx, &Error{ writeError(ctx, &Error{
statusCode: http.StatusInternalServerError, statusCode: http.StatusInternalServerError,
Code: 40005, Code: ErrCodeSaveConfigFailed,
Msg: fmt.Sprintf("create file: %s", err.Error()), Msg: fmt.Sprintf("create file: %s", err.Error()),
}) })
return return
@ -154,8 +154,8 @@ func saveConfig(ctx *gin.Context) {
if err := config.Global().Write(f, req.Format); err != nil { if err := config.Global().Write(f, req.Format); err != nil {
writeError(ctx, &Error{ writeError(ctx, &Error{
statusCode: http.StatusInternalServerError, statusCode: http.StatusInternalServerError,
Code: 40006, Code: ErrCodeSaveConfigFailed,
Msg: fmt.Sprintf("write: %s", err.Error()), Msg: fmt.Sprintf("save config: %s", err.Error()),
}) })
return return
} }

View File

@ -1,7 +1,9 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
@ -35,15 +37,21 @@ func createAdmission(ctx *gin.Context) {
var req createAdmissionRequest var req createAdmissionRequest
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if req.Data.Name == "" { name := strings.TrimSpace(req.Data.Name)
writeError(ctx, ErrInvalid) if name == "" {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeInvalid, "admission name is required"))
return
}
if registry.AdmissionRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("admission %s already exists", name)))
return return
} }
v := parser.ParseAdmission(&req.Data) v := parser.ParseAdmission(&req.Data)
if err := registry.AdmissionRegistry().Register(req.Data.Name, v); err != nil { if err := registry.AdmissionRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("admission %s already exists", name)))
return return
} }
@ -87,25 +95,27 @@ func updateAdmission(ctx *gin.Context) {
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if !registry.AdmissionRegistry().IsRegistered(req.Admission) { name := strings.TrimSpace(req.Admission)
writeError(ctx, ErrNotFound)
if !registry.AdmissionRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("admission %s not found", name)))
return return
} }
req.Data.Name = req.Admission req.Data.Name = name
v := parser.ParseAdmission(&req.Data) v := parser.ParseAdmission(&req.Data)
registry.AdmissionRegistry().Unregister(req.Admission) registry.AdmissionRegistry().Unregister(name)
if err := registry.AdmissionRegistry().Register(req.Admission, v); err != nil { if err := registry.AdmissionRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("admission %s already exists", name)))
return return
} }
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
for i := range c.Admissions { for i := range c.Admissions {
if c.Admissions[i].Name == req.Admission { if c.Admissions[i].Name == name {
c.Admissions[i] = &req.Data c.Admissions[i] = &req.Data
break break
} }
@ -145,17 +155,19 @@ func deleteAdmission(ctx *gin.Context) {
var req deleteAdmissionRequest var req deleteAdmissionRequest
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
if !registry.AdmissionRegistry().IsRegistered(req.Admission) { name := strings.TrimSpace(req.Admission)
writeError(ctx, ErrNotFound)
if !registry.AdmissionRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("admission %s not found", name)))
return return
} }
registry.AdmissionRegistry().Unregister(req.Admission) registry.AdmissionRegistry().Unregister(name)
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
admissiones := c.Admissions admissiones := c.Admissions
c.Admissions = nil c.Admissions = nil
for _, s := range admissiones { for _, s := range admissiones {
if s.Name == req.Admission { if s.Name == name {
continue continue
} }
c.Admissions = append(c.Admissions, s) c.Admissions = append(c.Admissions, s)

View File

@ -1,7 +1,9 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
@ -35,14 +37,20 @@ func createAuther(ctx *gin.Context) {
var req createAutherRequest var req createAutherRequest
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if req.Data.Name == "" { name := strings.TrimSpace(req.Data.Name)
writeError(ctx, ErrInvalid) if name == "" {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeInvalid, "auther name is required"))
return
}
if registry.AutherRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("auther %s already exists", name)))
return return
} }
v := parser.ParseAuther(&req.Data) v := parser.ParseAuther(&req.Data)
if err := registry.AutherRegistry().Register(req.Data.Name, v); err != nil { if err := registry.AutherRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("auther %s already exists", name)))
return return
} }
@ -86,24 +94,26 @@ func updateAuther(ctx *gin.Context) {
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if !registry.AutherRegistry().IsRegistered(req.Auther) { name := strings.TrimSpace(req.Auther)
writeError(ctx, ErrNotFound)
if !registry.AutherRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("auther %s not found", name)))
return return
} }
req.Data.Name = req.Auther req.Data.Name = name
v := parser.ParseAuther(&req.Data) v := parser.ParseAuther(&req.Data)
registry.AutherRegistry().Unregister(req.Auther) registry.AutherRegistry().Unregister(name)
if err := registry.AutherRegistry().Register(req.Auther, v); err != nil { if err := registry.AutherRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("auther %s already exists", name)))
return return
} }
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
for i := range c.Authers { for i := range c.Authers {
if c.Authers[i].Name == req.Auther { if c.Authers[i].Name == name {
c.Authers[i] = &req.Data c.Authers[i] = &req.Data
break break
} }
@ -143,17 +153,19 @@ func deleteAuther(ctx *gin.Context) {
var req deleteAutherRequest var req deleteAutherRequest
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
if !registry.AutherRegistry().IsRegistered(req.Auther) { name := strings.TrimSpace(req.Auther)
writeError(ctx, ErrNotFound)
if !registry.AutherRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("auther %s not found", name)))
return return
} }
registry.AutherRegistry().Unregister(req.Auther) registry.AutherRegistry().Unregister(name)
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
authers := c.Authers authers := c.Authers
c.Authers = nil c.Authers = nil
for _, s := range authers { for _, s := range authers {
if s.Name == req.Auther { if s.Name == name {
continue continue
} }
c.Authers = append(c.Authers, s) c.Authers = append(c.Authers, s)

View File

@ -1,7 +1,9 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
@ -35,15 +37,21 @@ func createBypass(ctx *gin.Context) {
var req createBypassRequest var req createBypassRequest
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if req.Data.Name == "" { name := strings.TrimSpace(req.Data.Name)
writeError(ctx, ErrInvalid) if name == "" {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeInvalid, "bypass name is required"))
return
}
if registry.BypassRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("bypass %s already exists", name)))
return return
} }
v := parser.ParseBypass(&req.Data) v := parser.ParseBypass(&req.Data)
if err := registry.BypassRegistry().Register(req.Data.Name, v); err != nil { if err := registry.BypassRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("bypass %s already exists", name)))
return return
} }
@ -87,25 +95,27 @@ func updateBypass(ctx *gin.Context) {
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if !registry.BypassRegistry().IsRegistered(req.Bypass) { name := strings.TrimSpace(req.Bypass)
writeError(ctx, ErrNotFound)
if !registry.BypassRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("bypass %s not found", name)))
return return
} }
req.Data.Name = req.Bypass req.Data.Name = name
v := parser.ParseBypass(&req.Data) v := parser.ParseBypass(&req.Data)
registry.BypassRegistry().Unregister(req.Bypass) registry.BypassRegistry().Unregister(name)
if err := registry.BypassRegistry().Register(req.Bypass, v); err != nil { if err := registry.BypassRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("bypass %s already exists", name)))
return return
} }
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
for i := range c.Bypasses { for i := range c.Bypasses {
if c.Bypasses[i].Name == req.Bypass { if c.Bypasses[i].Name == name {
c.Bypasses[i] = &req.Data c.Bypasses[i] = &req.Data
break break
} }
@ -145,17 +155,19 @@ func deleteBypass(ctx *gin.Context) {
var req deleteBypassRequest var req deleteBypassRequest
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
if !registry.BypassRegistry().IsRegistered(req.Bypass) { name := strings.TrimSpace(req.Bypass)
writeError(ctx, ErrNotFound)
if !registry.BypassRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("bypass %s not found", name)))
return return
} }
registry.BypassRegistry().Unregister(req.Bypass) registry.BypassRegistry().Unregister(name)
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
bypasses := c.Bypasses bypasses := c.Bypasses
c.Bypasses = nil c.Bypasses = nil
for _, s := range bypasses { for _, s := range bypasses {
if s.Name == req.Bypass { if s.Name == name {
continue continue
} }
c.Bypasses = append(c.Bypasses, s) c.Bypasses = append(c.Bypasses, s)

View File

@ -1,7 +1,9 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-gost/core/logger" "github.com/go-gost/core/logger"
@ -36,19 +38,25 @@ func createChain(ctx *gin.Context) {
var req createChainRequest var req createChainRequest
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if req.Data.Name == "" { name := strings.TrimSpace(req.Data.Name)
writeError(ctx, ErrInvalid) if name == "" {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeInvalid, "chain name is required"))
return
}
if registry.ChainRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("chain %s already exists", name)))
return return
} }
v, err := parser.ParseChain(&req.Data, logger.Default()) v, err := parser.ParseChain(&req.Data, logger.Default())
if err != nil { if err != nil {
writeError(ctx, ErrCreate) writeError(ctx, NewError(http.StatusInternalServerError, ErrCodeFailed, fmt.Sprintf("create chain %s failed: %s", name, err.Error())))
return return
} }
if err := registry.ChainRegistry().Register(req.Data.Name, v); err != nil { if err := registry.ChainRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("chain %s already exists", name)))
return return
} }
@ -93,29 +101,31 @@ func updateChain(ctx *gin.Context) {
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if !registry.ChainRegistry().IsRegistered(req.Chain) { name := strings.TrimSpace(req.Chain)
writeError(ctx, ErrNotFound)
if !registry.ChainRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("chain %s not found", name)))
return return
} }
req.Data.Name = req.Chain req.Data.Name = name
v, err := parser.ParseChain(&req.Data, logger.Default()) v, err := parser.ParseChain(&req.Data, logger.Default())
if err != nil { if err != nil {
writeError(ctx, ErrCreate) writeError(ctx, NewError(http.StatusInternalServerError, ErrCodeFailed, fmt.Sprintf("create chain %s failed: %s", name, err.Error())))
return return
} }
registry.ChainRegistry().Unregister(req.Chain) registry.ChainRegistry().Unregister(name)
if err := registry.ChainRegistry().Register(req.Chain, v); err != nil { if err := registry.ChainRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("chain %s already exists", name)))
return return
} }
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
for i := range c.Chains { for i := range c.Chains {
if c.Chains[i].Name == req.Chain { if c.Chains[i].Name == name {
c.Chains[i] = &req.Data c.Chains[i] = &req.Data
break break
} }
@ -155,17 +165,19 @@ func deleteChain(ctx *gin.Context) {
var req deleteChainRequest var req deleteChainRequest
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
if !registry.ChainRegistry().IsRegistered(req.Chain) { name := strings.TrimSpace(req.Chain)
writeError(ctx, ErrNotFound)
if !registry.ChainRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("chain %s not found", name)))
return return
} }
registry.ChainRegistry().Unregister(req.Chain) registry.ChainRegistry().Unregister(name)
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
chains := c.Chains chains := c.Chains
c.Chains = nil c.Chains = nil
for _, s := range chains { for _, s := range chains {
if s.Name == req.Chain { if s.Name == name {
continue continue
} }
c.Chains = append(c.Chains, s) c.Chains = append(c.Chains, s)

View File

@ -1,7 +1,9 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
@ -35,15 +37,20 @@ func createConnLimiter(ctx *gin.Context) {
var req createConnLimiterRequest var req createConnLimiterRequest
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if req.Data.Name == "" { name := strings.TrimSpace(req.Data.Name)
writeError(ctx, ErrInvalid) if name == "" {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeInvalid, "limiter name is required"))
return
}
if registry.ConnLimiterRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("limiter %s already exists", name)))
return return
} }
v := parser.ParseConnLimiter(&req.Data) v := parser.ParseConnLimiter(&req.Data)
if err := registry.ConnLimiterRegistry().Register(name, v); err != nil {
if err := registry.ConnLimiterRegistry().Register(req.Data.Name, v); err != nil { writeError(ctx, NewError(http.StatusInternalServerError, ErrCodeFailed, fmt.Sprintf("create limmiter %s failed: %s", name, err.Error())))
writeError(ctx, ErrDup)
return return
} }
@ -87,25 +94,27 @@ func updateConnLimiter(ctx *gin.Context) {
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if !registry.ConnLimiterRegistry().IsRegistered(req.Limiter) { name := strings.TrimSpace(req.Limiter)
writeError(ctx, ErrNotFound)
if !registry.ConnLimiterRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("limiter %s not found", name)))
return return
} }
req.Data.Name = req.Limiter req.Data.Name = name
v := parser.ParseConnLimiter(&req.Data) v := parser.ParseConnLimiter(&req.Data)
registry.ConnLimiterRegistry().Unregister(req.Limiter) registry.ConnLimiterRegistry().Unregister(name)
if err := registry.ConnLimiterRegistry().Register(req.Limiter, v); err != nil { if err := registry.ConnLimiterRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("limiter %s already exists", name)))
return return
} }
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
for i := range c.CLimiters { for i := range c.CLimiters {
if c.CLimiters[i].Name == req.Limiter { if c.CLimiters[i].Name == name {
c.CLimiters[i] = &req.Data c.CLimiters[i] = &req.Data
break break
} }
@ -145,17 +154,19 @@ func deleteConnLimiter(ctx *gin.Context) {
var req deleteConnLimiterRequest var req deleteConnLimiterRequest
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
if !registry.ConnLimiterRegistry().IsRegistered(req.Limiter) { name := strings.TrimSpace(req.Limiter)
writeError(ctx, ErrNotFound)
if !registry.ConnLimiterRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("limiter %s not found", name)))
return return
} }
registry.ConnLimiterRegistry().Unregister(req.Limiter) registry.ConnLimiterRegistry().Unregister(name)
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
limiteres := c.CLimiters limiteres := c.CLimiters
c.CLimiters = nil c.CLimiters = nil
for _, s := range limiteres { for _, s := range limiteres {
if s.Name == req.Limiter { if s.Name == name {
continue continue
} }
c.CLimiters = append(c.CLimiters, s) c.CLimiters = append(c.CLimiters, s)

View File

@ -1,7 +1,9 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-gost/core/logger" "github.com/go-gost/core/logger"
@ -36,19 +38,25 @@ func createHop(ctx *gin.Context) {
var req createHopRequest var req createHopRequest
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if req.Data.Name == "" { name := strings.TrimSpace(req.Data.Name)
writeError(ctx, ErrInvalid) if name == "" {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeInvalid, "hop name is required"))
return
}
if registry.HopRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("hop %s already exists", name)))
return return
} }
v, err := parser.ParseHop(&req.Data, logger.Default()) v, err := parser.ParseHop(&req.Data, logger.Default())
if err != nil { if err != nil {
writeError(ctx, ErrCreate) writeError(ctx, NewError(http.StatusInternalServerError, ErrCodeFailed, fmt.Sprintf("create hop %s failed: %s", name, err.Error())))
return return
} }
if err := registry.HopRegistry().Register(req.Data.Name, v); err != nil { if err := registry.HopRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("hop %s already exists", name)))
return return
} }
@ -93,29 +101,30 @@ func updateHop(ctx *gin.Context) {
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if !registry.HopRegistry().IsRegistered(req.Hop) { name := strings.TrimSpace(req.Hop)
writeError(ctx, ErrNotFound) if !registry.HopRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("hop %s not found", name)))
return return
} }
req.Data.Name = req.Hop req.Data.Name = name
v, err := parser.ParseHop(&req.Data, logger.Default()) v, err := parser.ParseHop(&req.Data, logger.Default())
if err != nil { if err != nil {
writeError(ctx, ErrCreate) writeError(ctx, NewError(http.StatusInternalServerError, ErrCodeFailed, fmt.Sprintf("create hop %s failed: %s", name, err.Error())))
return return
} }
registry.HopRegistry().Unregister(req.Hop) registry.HopRegistry().Unregister(name)
if err := registry.HopRegistry().Register(req.Hop, v); err != nil { if err := registry.HopRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("hop %s already exists", name)))
return return
} }
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
for i := range c.Hops { for i := range c.Hops {
if c.Hops[i].Name == req.Hop { if c.Hops[i].Name == name {
c.Hops[i] = &req.Data c.Hops[i] = &req.Data
break break
} }
@ -155,17 +164,19 @@ func deleteHop(ctx *gin.Context) {
var req deleteHopRequest var req deleteHopRequest
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
if !registry.HopRegistry().IsRegistered(req.Hop) { name := strings.TrimSpace(req.Hop)
writeError(ctx, ErrNotFound)
if !registry.HopRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("hop %s not found", name)))
return return
} }
registry.HopRegistry().Unregister(req.Hop) registry.HopRegistry().Unregister(name)
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
hops := c.Hops hops := c.Hops
c.Hops = nil c.Hops = nil
for _, s := range hops { for _, s := range hops {
if s.Name == req.Hop { if s.Name == name {
continue continue
} }
c.Hops = append(c.Hops, s) c.Hops = append(c.Hops, s)

View File

@ -1,7 +1,9 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
@ -35,15 +37,21 @@ func createHosts(ctx *gin.Context) {
var req createHostsRequest var req createHostsRequest
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if req.Data.Name == "" { name := strings.TrimSpace(req.Data.Name)
writeError(ctx, ErrInvalid) if name == "" {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeInvalid, "hosts name is required"))
return
}
if registry.HostsRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("hosts %s already exists", name)))
return return
} }
v := parser.ParseHostMapper(&req.Data) v := parser.ParseHostMapper(&req.Data)
if err := registry.HostsRegistry().Register(req.Data.Name, v); err != nil { if err := registry.HostsRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("hosts %s already exists", name)))
return return
} }
@ -87,25 +95,27 @@ func updateHosts(ctx *gin.Context) {
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if !registry.HostsRegistry().IsRegistered(req.Hosts) { name := strings.TrimSpace(req.Hosts)
writeError(ctx, ErrNotFound)
if !registry.HostsRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("hosts %s not found", name)))
return return
} }
req.Data.Name = req.Hosts req.Data.Name = name
v := parser.ParseHostMapper(&req.Data) v := parser.ParseHostMapper(&req.Data)
registry.HostsRegistry().Unregister(req.Hosts) registry.HostsRegistry().Unregister(name)
if err := registry.HostsRegistry().Register(req.Hosts, v); err != nil { if err := registry.HostsRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("hosts %s already exists", name)))
return return
} }
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
for i := range c.Hosts { for i := range c.Hosts {
if c.Hosts[i].Name == req.Hosts { if c.Hosts[i].Name == name {
c.Hosts[i] = &req.Data c.Hosts[i] = &req.Data
break break
} }
@ -145,17 +155,19 @@ func deleteHosts(ctx *gin.Context) {
var req deleteHostsRequest var req deleteHostsRequest
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
if !registry.HostsRegistry().IsRegistered(req.Hosts) { name := strings.TrimSpace(req.Hosts)
writeError(ctx, ErrNotFound)
if !registry.HostsRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("hosts %s not found", name)))
return return
} }
registry.HostsRegistry().Unregister(req.Hosts) registry.HostsRegistry().Unregister(name)
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
hosts := c.Hosts hosts := c.Hosts
c.Hosts = nil c.Hosts = nil
for _, s := range hosts { for _, s := range hosts {
if s.Name == req.Hosts { if s.Name == name {
continue continue
} }
c.Hosts = append(c.Hosts, s) c.Hosts = append(c.Hosts, s)

View File

@ -1,7 +1,9 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
@ -35,15 +37,21 @@ func createIngress(ctx *gin.Context) {
var req createIngressRequest var req createIngressRequest
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if req.Data.Name == "" { name := strings.TrimSpace(req.Data.Name)
writeError(ctx, ErrInvalid) if name == "" {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeInvalid, "ingress name is required"))
return
}
if registry.IngressRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("ingress %s already exists", name)))
return return
} }
v := parser.ParseIngress(&req.Data) v := parser.ParseIngress(&req.Data)
if err := registry.IngressRegistry().Register(req.Data.Name, v); err != nil { if err := registry.IngressRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("ingress %s already exists", name)))
return return
} }
@ -87,25 +95,27 @@ func updateIngress(ctx *gin.Context) {
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if !registry.IngressRegistry().IsRegistered(req.Ingress) { name := strings.TrimSpace(req.Ingress)
writeError(ctx, ErrNotFound)
if !registry.IngressRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("ingress %s not found", name)))
return return
} }
req.Data.Name = req.Ingress req.Data.Name = name
v := parser.ParseIngress(&req.Data) v := parser.ParseIngress(&req.Data)
registry.IngressRegistry().Unregister(req.Ingress) registry.IngressRegistry().Unregister(name)
if err := registry.IngressRegistry().Register(req.Ingress, v); err != nil { if err := registry.IngressRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("ingress %s already exists", name)))
return return
} }
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
for i := range c.Ingresses { for i := range c.Ingresses {
if c.Ingresses[i].Name == req.Ingress { if c.Ingresses[i].Name == name {
c.Ingresses[i] = &req.Data c.Ingresses[i] = &req.Data
break break
} }
@ -145,17 +155,19 @@ func deleteIngress(ctx *gin.Context) {
var req deleteIngressRequest var req deleteIngressRequest
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
if !registry.IngressRegistry().IsRegistered(req.Ingress) { name := strings.TrimSpace(req.Ingress)
writeError(ctx, ErrNotFound)
if !registry.IngressRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("ingress %s not found", name)))
return return
} }
registry.IngressRegistry().Unregister(req.Ingress) registry.IngressRegistry().Unregister(name)
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
ingresses := c.Ingresses ingresses := c.Ingresses
c.Ingresses = nil c.Ingresses = nil
for _, s := range ingresses { for _, s := range ingresses {
if s.Name == req.Ingress { if s.Name == name {
continue continue
} }
c.Ingresses = append(c.Ingresses, s) c.Ingresses = append(c.Ingresses, s)

View File

@ -1,7 +1,9 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
@ -35,15 +37,21 @@ func createLimiter(ctx *gin.Context) {
var req createLimiterRequest var req createLimiterRequest
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if req.Data.Name == "" { name := strings.TrimSpace(req.Data.Name)
writeError(ctx, ErrInvalid) if name == "" {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeInvalid, "limiter name is required"))
return
}
if registry.TrafficLimiterRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("limiter %s already exists", name)))
return return
} }
v := parser.ParseTrafficLimiter(&req.Data) v := parser.ParseTrafficLimiter(&req.Data)
if err := registry.TrafficLimiterRegistry().Register(req.Data.Name, v); err != nil { if err := registry.TrafficLimiterRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("limiter %s already exists", name)))
return return
} }
@ -87,25 +95,27 @@ func updateLimiter(ctx *gin.Context) {
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if !registry.TrafficLimiterRegistry().IsRegistered(req.Limiter) { name := strings.TrimSpace(req.Limiter)
writeError(ctx, ErrNotFound)
if !registry.TrafficLimiterRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("limiter %s not found", name)))
return return
} }
req.Data.Name = req.Limiter req.Data.Name = name
v := parser.ParseTrafficLimiter(&req.Data) v := parser.ParseTrafficLimiter(&req.Data)
registry.TrafficLimiterRegistry().Unregister(req.Limiter) registry.TrafficLimiterRegistry().Unregister(name)
if err := registry.TrafficLimiterRegistry().Register(req.Limiter, v); err != nil { if err := registry.TrafficLimiterRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("limiter %s already exists", name)))
return return
} }
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
for i := range c.Limiters { for i := range c.Limiters {
if c.Limiters[i].Name == req.Limiter { if c.Limiters[i].Name == name {
c.Limiters[i] = &req.Data c.Limiters[i] = &req.Data
break break
} }
@ -145,17 +155,19 @@ func deleteLimiter(ctx *gin.Context) {
var req deleteLimiterRequest var req deleteLimiterRequest
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
if !registry.TrafficLimiterRegistry().IsRegistered(req.Limiter) { name := strings.TrimSpace(req.Limiter)
writeError(ctx, ErrNotFound)
if !registry.TrafficLimiterRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("limiter %s not found", name)))
return return
} }
registry.TrafficLimiterRegistry().Unregister(req.Limiter) registry.TrafficLimiterRegistry().Unregister(name)
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
limiteres := c.Limiters limiteres := c.Limiters
c.Limiters = nil c.Limiters = nil
for _, s := range limiteres { for _, s := range limiteres {
if s.Name == req.Limiter { if s.Name == name {
continue continue
} }
c.Limiters = append(c.Limiters, s) c.Limiters = append(c.Limiters, s)

View File

@ -1,7 +1,9 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
@ -35,15 +37,21 @@ func createObserver(ctx *gin.Context) {
var req createObserverRequest var req createObserverRequest
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if req.Data.Name == "" { name := strings.TrimSpace(req.Data.Name)
writeError(ctx, ErrInvalid) if name == "" {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeInvalid, "observer name is required"))
return
}
if registry.ObserverRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("observer %s already exists", name)))
return return
} }
v := parser.ParseObserver(&req.Data) v := parser.ParseObserver(&req.Data)
if err := registry.ObserverRegistry().Register(req.Data.Name, v); err != nil { if err := registry.ObserverRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("observer %s already exists", name)))
return return
} }
@ -87,25 +95,27 @@ func updateObserver(ctx *gin.Context) {
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if !registry.ObserverRegistry().IsRegistered(req.Observer) { name := strings.TrimSpace(req.Observer)
writeError(ctx, ErrNotFound)
if !registry.ObserverRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("observer %s not found", name)))
return return
} }
req.Data.Name = req.Observer req.Data.Name = name
v := parser.ParseObserver(&req.Data) v := parser.ParseObserver(&req.Data)
registry.ObserverRegistry().Unregister(req.Observer) registry.ObserverRegistry().Unregister(name)
if err := registry.ObserverRegistry().Register(req.Observer, v); err != nil { if err := registry.ObserverRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("observer %s already exists", name)))
return return
} }
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
for i := range c.Observers { for i := range c.Observers {
if c.Observers[i].Name == req.Observer { if c.Observers[i].Name == name {
c.Observers[i] = &req.Data c.Observers[i] = &req.Data
break break
} }
@ -145,17 +155,19 @@ func deleteObserver(ctx *gin.Context) {
var req deleteObserverRequest var req deleteObserverRequest
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
if !registry.ObserverRegistry().IsRegistered(req.Observer) { name := strings.TrimSpace(req.Observer)
writeError(ctx, ErrNotFound)
if !registry.ObserverRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("observer %s not found", name)))
return return
} }
registry.ObserverRegistry().Unregister(req.Observer) registry.ObserverRegistry().Unregister(name)
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
observers := c.Observers observers := c.Observers
c.Observers = nil c.Observers = nil
for _, s := range observers { for _, s := range observers {
if s.Name == req.Observer { if s.Name == name {
continue continue
} }
c.Observers = append(c.Observers, s) c.Observers = append(c.Observers, s)

View File

@ -1,7 +1,9 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
@ -35,15 +37,21 @@ func createRateLimiter(ctx *gin.Context) {
var req createRateLimiterRequest var req createRateLimiterRequest
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if req.Data.Name == "" { name := strings.TrimSpace(req.Data.Name)
writeError(ctx, ErrInvalid) if name == "" {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeInvalid, "limiter name is required"))
return
}
if registry.RateLimiterRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("limiter %s already exists", name)))
return return
} }
v := parser.ParseRateLimiter(&req.Data) v := parser.ParseRateLimiter(&req.Data)
if err := registry.RateLimiterRegistry().Register(req.Data.Name, v); err != nil { if err := registry.RateLimiterRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("limiter %s already exists", name)))
return return
} }
@ -87,25 +95,27 @@ func updateRateLimiter(ctx *gin.Context) {
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if !registry.RateLimiterRegistry().IsRegistered(req.Limiter) { name := strings.TrimSpace(req.Limiter)
writeError(ctx, ErrNotFound)
if !registry.RateLimiterRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("limiter %s not found", name)))
return return
} }
req.Data.Name = req.Limiter req.Data.Name = name
v := parser.ParseRateLimiter(&req.Data) v := parser.ParseRateLimiter(&req.Data)
registry.RateLimiterRegistry().Unregister(req.Limiter) registry.RateLimiterRegistry().Unregister(name)
if err := registry.RateLimiterRegistry().Register(req.Limiter, v); err != nil { if err := registry.RateLimiterRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("limiter %s already exists", name)))
return return
} }
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
for i := range c.RLimiters { for i := range c.RLimiters {
if c.RLimiters[i].Name == req.Limiter { if c.RLimiters[i].Name == name {
c.RLimiters[i] = &req.Data c.RLimiters[i] = &req.Data
break break
} }
@ -145,17 +155,19 @@ func deleteRateLimiter(ctx *gin.Context) {
var req deleteRateLimiterRequest var req deleteRateLimiterRequest
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
if !registry.RateLimiterRegistry().IsRegistered(req.Limiter) { name := strings.TrimSpace(req.Limiter)
writeError(ctx, ErrNotFound)
if !registry.RateLimiterRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("limiter %s not found", name)))
return return
} }
registry.RateLimiterRegistry().Unregister(req.Limiter) registry.RateLimiterRegistry().Unregister(name)
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
limiteres := c.RLimiters limiteres := c.RLimiters
c.RLimiters = nil c.RLimiters = nil
for _, s := range limiteres { for _, s := range limiteres {
if s.Name == req.Limiter { if s.Name == name {
continue continue
} }
c.RLimiters = append(c.RLimiters, s) c.RLimiters = append(c.RLimiters, s)

180
api/config_recorder.go Normal file
View File

@ -0,0 +1,180 @@
package api
import (
"fmt"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"github.com/go-gost/x/config"
parser "github.com/go-gost/x/config/parsing/recorder"
"github.com/go-gost/x/registry"
)
// swagger:parameters createRecorderRequest
type createRecorderRequest struct {
// in: body
Data config.RecorderConfig `json:"data"`
}
// successful operation.
// swagger:response createRecorderResponse
type createRecorderResponse struct {
Data Response
}
func createRecorder(ctx *gin.Context) {
// swagger:route POST /config/recorders Recorder createRecorderRequest
//
// Create a new recorder, the name of the recorder must be unique in recorder list.
//
// Security:
// basicAuth: []
//
// Responses:
// 200: createRecorderResponse
var req createRecorderRequest
ctx.ShouldBindJSON(&req.Data)
name := strings.TrimSpace(req.Data.Name)
if name == "" {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeInvalid, "recorder name is required"))
return
}
if registry.RecorderRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("recorder %s already exists", name)))
return
}
v := parser.ParseRecorder(&req.Data)
if err := registry.RecorderRegistry().Register(name, v); err != nil {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("recorder %s already exists", name)))
return
}
config.OnUpdate(func(c *config.Config) error {
c.Recorders = append(c.Recorders, &req.Data)
return nil
})
ctx.JSON(http.StatusOK, Response{
Msg: "OK",
})
}
// swagger:parameters updateRecorderRequest
type updateRecorderRequest struct {
// in: path
// required: true
Recorder string `uri:"recorder" json:"recorder"`
// in: body
Data config.RecorderConfig `json:"data"`
}
// successful operation.
// swagger:response updateRecorderResponse
type updateRecorderResponse struct {
Data Response
}
func updateRecorder(ctx *gin.Context) {
// swagger:route PUT /config/recorders/{recorder} Recorder updateRecorderRequest
//
// Update recorder by name, the recorder must already exist.
//
// Security:
// basicAuth: []
//
// Responses:
// 200: updateRecorderResponse
var req updateRecorderRequest
ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data)
name := strings.TrimSpace(req.Recorder)
if !registry.RecorderRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("recorder %s not found", name)))
return
}
req.Data.Name = name
v := parser.ParseRecorder(&req.Data)
registry.RecorderRegistry().Unregister(name)
if err := registry.RecorderRegistry().Register(name, v); err != nil {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("recorder %s already exists", name)))
return
}
config.OnUpdate(func(c *config.Config) error {
for i := range c.Recorders {
if c.Recorders[i].Name == name {
c.Recorders[i] = &req.Data
break
}
}
return nil
})
ctx.JSON(http.StatusOK, Response{
Msg: "OK",
})
}
// swagger:parameters deleteRecorderRequest
type deleteRecorderRequest struct {
// in: path
// required: true
Recorder string `uri:"recorder" json:"recorder"`
}
// successful operation.
// swagger:response deleteRecorderResponse
type deleteRecorderResponse struct {
Data Response
}
func deleteRecorder(ctx *gin.Context) {
// swagger:route DELETE /config/recorders/{recorder} Recorder deleteRecorderRequest
//
// Delete recorder by name.
//
// Security:
// basicAuth: []
//
// Responses:
// 200: deleteRecorderResponse
var req deleteRecorderRequest
ctx.ShouldBindUri(&req)
name := strings.TrimSpace(req.Recorder)
if !registry.RecorderRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("recorder %s not found", name)))
return
}
registry.RecorderRegistry().Unregister(name)
config.OnUpdate(func(c *config.Config) error {
recorders := c.Recorders
c.Recorders = nil
for _, s := range recorders {
if s.Name == name {
continue
}
c.Recorders = append(c.Recorders, s)
}
return nil
})
ctx.JSON(http.StatusOK, Response{
Msg: "OK",
})
}

View File

@ -1,7 +1,9 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
@ -35,19 +37,25 @@ func createResolver(ctx *gin.Context) {
var req createResolverRequest var req createResolverRequest
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if req.Data.Name == "" { name := strings.TrimSpace(req.Data.Name)
writeError(ctx, ErrInvalid) if name == "" {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeInvalid, "resolver name is required"))
return
}
if registry.ResolverRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("resolver %s already exists", name)))
return return
} }
v, err := parser.ParseResolver(&req.Data) v, err := parser.ParseResolver(&req.Data)
if err != nil { if err != nil {
writeError(ctx, ErrCreate) writeError(ctx, NewError(http.StatusInternalServerError, ErrCodeFailed, fmt.Sprintf("create resolver %s failed: %s", name, err.Error())))
return return
} }
if err := registry.ResolverRegistry().Register(req.Data.Name, v); err != nil { if err := registry.ResolverRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("resolver %s already exists", name)))
return return
} }
@ -91,29 +99,31 @@ func updateResolver(ctx *gin.Context) {
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if !registry.ResolverRegistry().IsRegistered(req.Resolver) { name := strings.TrimSpace(req.Resolver)
writeError(ctx, ErrNotFound)
if !registry.ResolverRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("resolver %s not found", name)))
return return
} }
req.Data.Name = req.Resolver req.Data.Name = name
v, err := parser.ParseResolver(&req.Data) v, err := parser.ParseResolver(&req.Data)
if err != nil { if err != nil {
writeError(ctx, ErrCreate) writeError(ctx, NewError(http.StatusInternalServerError, ErrCodeFailed, fmt.Sprintf("create resolver %s failed: %s", name, err.Error())))
return return
} }
registry.ResolverRegistry().Unregister(req.Resolver) registry.ResolverRegistry().Unregister(name)
if err := registry.ResolverRegistry().Register(req.Resolver, v); err != nil { if err := registry.ResolverRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("resolver %s already exists", name)))
return return
} }
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
for i := range c.Resolvers { for i := range c.Resolvers {
if c.Resolvers[i].Name == req.Resolver { if c.Resolvers[i].Name == name {
c.Resolvers[i] = &req.Data c.Resolvers[i] = &req.Data
break break
} }
@ -153,17 +163,19 @@ func deleteResolver(ctx *gin.Context) {
var req deleteResolverRequest var req deleteResolverRequest
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
if !registry.ResolverRegistry().IsRegistered(req.Resolver) { name := strings.TrimSpace(req.Resolver)
writeError(ctx, ErrNotFound)
if !registry.ResolverRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("resolver %s not found", name)))
return return
} }
registry.ResolverRegistry().Unregister(req.Resolver) registry.ResolverRegistry().Unregister(name)
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
resolvers := c.Resolvers resolvers := c.Resolvers
c.Resolvers = nil c.Resolvers = nil
for _, s := range resolvers { for _, s := range resolvers {
if s.Name == req.Resolver { if s.Name == name {
continue continue
} }
c.Resolvers = append(c.Resolvers, s) c.Resolvers = append(c.Resolvers, s)

View File

@ -1,7 +1,9 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
@ -35,15 +37,21 @@ func createRouter(ctx *gin.Context) {
var req createRouterRequest var req createRouterRequest
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if req.Data.Name == "" { name := strings.TrimSpace(req.Data.Name)
writeError(ctx, ErrInvalid) if name == "" {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeInvalid, "router name is required"))
return
}
if registry.RouterRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("router %s already exists", name)))
return return
} }
v := parser.ParseRouter(&req.Data) v := parser.ParseRouter(&req.Data)
if err := registry.RouterRegistry().Register(req.Data.Name, v); err != nil { if err := registry.RouterRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("router %s already exists", name)))
return return
} }
@ -87,25 +95,27 @@ func updateRouter(ctx *gin.Context) {
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if !registry.RouterRegistry().IsRegistered(req.Router) { name := strings.TrimSpace(req.Router)
writeError(ctx, ErrNotFound)
if !registry.RouterRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("router %s not found", name)))
return return
} }
req.Data.Name = req.Router req.Data.Name = name
v := parser.ParseRouter(&req.Data) v := parser.ParseRouter(&req.Data)
registry.RouterRegistry().Unregister(req.Router) registry.RouterRegistry().Unregister(name)
if err := registry.RouterRegistry().Register(req.Router, v); err != nil { if err := registry.RouterRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("router %s already exists", name)))
return return
} }
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
for i := range c.Routers { for i := range c.Routers {
if c.Routers[i].Name == req.Router { if c.Routers[i].Name == name {
c.Routers[i] = &req.Data c.Routers[i] = &req.Data
break break
} }
@ -145,17 +155,19 @@ func deleteRouter(ctx *gin.Context) {
var req deleteRouterRequest var req deleteRouterRequest
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
if !registry.RouterRegistry().IsRegistered(req.Router) { name := strings.TrimSpace(req.Router)
writeError(ctx, ErrNotFound)
if !registry.RouterRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("router %s not found", name)))
return return
} }
registry.RouterRegistry().Unregister(req.Router) registry.RouterRegistry().Unregister(name)
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
routeres := c.Routers routeres := c.Routers
c.Routers = nil c.Routers = nil
for _, s := range routeres { for _, s := range routeres {
if s.Name == req.Router { if s.Name == name {
continue continue
} }
c.Routers = append(c.Routers, s) c.Routers = append(c.Routers, s)

View File

@ -1,7 +1,9 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-gost/x/config" "github.com/go-gost/x/config"
@ -35,15 +37,21 @@ func createSD(ctx *gin.Context) {
var req createSDRequest var req createSDRequest
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if req.Data.Name == "" { name := strings.TrimSpace(req.Data.Name)
writeError(ctx, ErrInvalid) if name == "" {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeInvalid, "sd name is required"))
return
}
if registry.SDRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("sd %s already exists", name)))
return return
} }
v := parser.ParseSD(&req.Data) v := parser.ParseSD(&req.Data)
if err := registry.SDRegistry().Register(req.Data.Name, v); err != nil { if err := registry.SDRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("sd %s already exists", name)))
return return
} }
@ -87,25 +95,27 @@ func updateSD(ctx *gin.Context) {
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
if !registry.SDRegistry().IsRegistered(req.SD) { name := strings.TrimSpace(req.SD)
writeError(ctx, ErrNotFound)
if !registry.SDRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("sd %s not found", name)))
return return
} }
req.Data.Name = req.SD req.Data.Name = name
v := parser.ParseSD(&req.Data) v := parser.ParseSD(&req.Data)
registry.SDRegistry().Unregister(req.SD) registry.SDRegistry().Unregister(name)
if err := registry.SDRegistry().Register(req.SD, v); err != nil { if err := registry.SDRegistry().Register(name, v); err != nil {
writeError(ctx, ErrDup) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("sd %s already exists", name)))
return return
} }
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
for i := range c.SDs { for i := range c.SDs {
if c.SDs[i].Name == req.SD { if c.SDs[i].Name == name {
c.SDs[i] = &req.Data c.SDs[i] = &req.Data
break break
} }
@ -145,17 +155,19 @@ func deleteSD(ctx *gin.Context) {
var req deleteSDRequest var req deleteSDRequest
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
if !registry.SDRegistry().IsRegistered(req.SD) { name := strings.TrimSpace(req.SD)
writeError(ctx, ErrNotFound)
if !registry.SDRegistry().IsRegistered(name) {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("sd %s not found", name)))
return return
} }
registry.SDRegistry().Unregister(req.SD) registry.SDRegistry().Unregister(name)
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
sds := c.SDs sds := c.SDs
c.SDs = nil c.SDs = nil
for _, s := range sds { for _, s := range sds {
if s.Name == req.SD { if s.Name == name {
continue continue
} }
c.SDs = append(c.SDs, s) c.SDs = append(c.SDs, s)

View File

@ -102,28 +102,28 @@ func updateService(ctx *gin.Context) {
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
ctx.ShouldBindJSON(&req.Data) ctx.ShouldBindJSON(&req.Data)
service := strings.TrimSpace(req.Service) name := strings.TrimSpace(req.Service)
old := registry.ServiceRegistry().Get(service) old := registry.ServiceRegistry().Get(name)
if old == nil { if old == nil {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("service %s not found", service))) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("service %s not found", name)))
return return
} }
old.Close() old.Close()
req.Data.Name = service req.Data.Name = name
svc, err := parser.ParseService(&req.Data) svc, err := parser.ParseService(&req.Data)
if err != nil { if err != nil {
writeError(ctx, NewError(http.StatusInternalServerError, ErrCodeFailed, fmt.Sprintf("create service %s failed: %s", service, err.Error()))) writeError(ctx, NewError(http.StatusInternalServerError, ErrCodeFailed, fmt.Sprintf("create service %s failed: %s", name, err.Error())))
return return
} }
registry.ServiceRegistry().Unregister(req.Service) registry.ServiceRegistry().Unregister(name)
if err := registry.ServiceRegistry().Register(req.Service, svc); err != nil { if err := registry.ServiceRegistry().Register(name, svc); err != nil {
svc.Close() svc.Close()
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("service %s already exists", service))) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeDup, fmt.Sprintf("service %s already exists", name)))
return return
} }
@ -131,7 +131,7 @@ func updateService(ctx *gin.Context) {
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
for i := range c.Services { for i := range c.Services {
if c.Services[i].Name == req.Service { if c.Services[i].Name == name {
c.Services[i] = &req.Data c.Services[i] = &req.Data
break break
} }
@ -171,22 +171,22 @@ func deleteService(ctx *gin.Context) {
var req deleteServiceRequest var req deleteServiceRequest
ctx.ShouldBindUri(&req) ctx.ShouldBindUri(&req)
service := strings.TrimSpace(req.Service) name := strings.TrimSpace(req.Service)
svc := registry.ServiceRegistry().Get(service) svc := registry.ServiceRegistry().Get(name)
if svc == nil { if svc == nil {
writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("service %s not found", service))) writeError(ctx, NewError(http.StatusBadRequest, ErrCodeNotFound, fmt.Sprintf("service %s not found", name)))
return return
} }
registry.ServiceRegistry().Unregister(service) registry.ServiceRegistry().Unregister(name)
svc.Close() svc.Close()
config.OnUpdate(func(c *config.Config) error { config.OnUpdate(func(c *config.Config) error {
services := c.Services services := c.Services
c.Services = nil c.Services = nil
for _, s := range services { for _, s := range services {
if s.Name == req.Service { if s.Name == name {
continue continue
} }
c.Services = append(c.Services, s) c.Services = append(c.Services, s)

View File

@ -37,7 +37,11 @@ func mwBasicAuth(auther auth.Authenticator) gin.HandlerFunc {
u, p, _ := c.Request.BasicAuth() u, p, _ := c.Request.BasicAuth()
if _, ok := auther.Authenticate(c, u, p); !ok { if _, ok := auther.Authenticate(c, u, p); !ok {
c.Writer.Header().Set("WWW-Authenticate", "Basic") c.Writer.Header().Set("WWW-Authenticate", "Basic")
c.AbortWithStatus(http.StatusUnauthorized) c.JSON(http.StatusUnauthorized, Response{
Code: http.StatusUnauthorized,
Msg: "Unauthorized",
})
c.Abort()
} }
} }
} }

View File

@ -306,7 +306,10 @@ definitions:
type: string type: string
type: array type: array
x-go-name: Bypasses x-go-name: Bypasses
filter:
$ref: '#/definitions/NodeFilterConfig'
host: host:
description: DEPRECATED by filter.host
type: string type: string
x-go-name: Host x-go-name: Host
http: http:
@ -322,9 +325,11 @@ definitions:
type: string type: string
x-go-name: Network x-go-name: Network
path: path:
description: DEPRECATED by filter.path
type: string type: string
x-go-name: Path x-go-name: Path
protocol: protocol:
description: DEPRECATED by filter.protocol
type: string type: string
x-go-name: Protocol x-go-name: Protocol
tls: tls:
@ -333,7 +338,12 @@ definitions:
x-go-package: github.com/go-gost/x/config x-go-package: github.com/go-gost/x/config
ForwarderConfig: ForwarderConfig:
properties: properties:
hop:
description: the referenced hop name
type: string
x-go-name: Hop
name: name:
description: DEPRECATED by hop field
type: string type: string
x-go-name: Name x-go-name: Name
nodes: nodes:
@ -705,8 +715,6 @@ definitions:
addr: addr:
type: string type: string
x-go-name: Addr x-go-name: Addr
auth:
$ref: '#/definitions/AuthConfig'
bypass: bypass:
type: string type: string
x-go-name: Bypass x-go-name: Bypass
@ -719,9 +727,8 @@ definitions:
$ref: '#/definitions/ConnectorConfig' $ref: '#/definitions/ConnectorConfig'
dialer: dialer:
$ref: '#/definitions/DialerConfig' $ref: '#/definitions/DialerConfig'
host: filter:
type: string $ref: '#/definitions/NodeFilterConfig'
x-go-name: Host
hosts: hosts:
type: string type: string
x-go-name: Hosts x-go-name: Hosts
@ -740,12 +747,6 @@ definitions:
network: network:
type: string type: string
x-go-name: Network x-go-name: Network
path:
type: string
x-go-name: Path
protocol:
type: string
x-go-name: Protocol
resolver: resolver:
type: string type: string
x-go-name: Resolver x-go-name: Resolver
@ -755,6 +756,19 @@ definitions:
$ref: '#/definitions/TLSNodeConfig' $ref: '#/definitions/TLSNodeConfig'
type: object type: object
x-go-package: github.com/go-gost/x/config x-go-package: github.com/go-gost/x/config
NodeFilterConfig:
properties:
host:
type: string
x-go-name: Host
path:
type: string
x-go-name: Path
protocol:
type: string
x-go-name: Protocol
type: object
x-go-package: github.com/go-gost/x/config
ObserverConfig: ObserverConfig:
properties: properties:
name: name:
@ -1762,6 +1776,64 @@ paths:
summary: Update observer by name, the observer must already exist. summary: Update observer by name, the observer must already exist.
tags: tags:
- Observer - Observer
/config/recorders:
post:
operationId: createRecorderRequest
parameters:
- in: body
name: data
schema:
$ref: '#/definitions/RecorderConfig'
x-go-name: Data
responses:
"200":
$ref: '#/responses/createRecorderResponse'
security:
- basicAuth:
- '[]'
summary: Create a new recorder, the name of the recorder must be unique in recorder list.
tags:
- Recorder
/config/recorders/{recorder}:
delete:
operationId: deleteRecorderRequest
parameters:
- in: path
name: recorder
required: true
type: string
x-go-name: Recorder
responses:
"200":
$ref: '#/responses/deleteRecorderResponse'
security:
- basicAuth:
- '[]'
summary: Delete recorder by name.
tags:
- Recorder
put:
operationId: updateRecorderRequest
parameters:
- in: path
name: recorder
required: true
type: string
x-go-name: Recorder
- in: body
name: data
schema:
$ref: '#/definitions/RecorderConfig'
x-go-name: Data
responses:
"200":
$ref: '#/responses/updateRecorderResponse'
security:
- basicAuth:
- '[]'
summary: Update recorder by name, the recorder must already exist.
tags:
- Recorder
/config/resolvers: /config/resolvers:
post: post:
operationId: createResolverRequest operationId: createResolverRequest
@ -2121,6 +2193,12 @@ responses:
Data: {} Data: {}
schema: schema:
$ref: '#/definitions/Response' $ref: '#/definitions/Response'
createRecorderResponse:
description: successful operation.
headers:
Data: {}
schema:
$ref: '#/definitions/Response'
createResolverResponse: createResolverResponse:
description: successful operation. description: successful operation.
headers: headers:
@ -2211,6 +2289,12 @@ responses:
Data: {} Data: {}
schema: schema:
$ref: '#/definitions/Response' $ref: '#/definitions/Response'
deleteRecorderResponse:
description: successful operation.
headers:
Data: {}
schema:
$ref: '#/definitions/Response'
deleteResolverResponse: deleteResolverResponse:
description: successful operation. description: successful operation.
headers: headers:
@ -2313,6 +2397,12 @@ responses:
Data: {} Data: {}
schema: schema:
$ref: '#/definitions/Response' $ref: '#/definitions/Response'
updateRecorderResponse:
description: successful operation.
headers:
Data: {}
schema:
$ref: '#/definitions/Response'
updateResolverResponse: updateResolverResponse:
description: successful operation. description: successful operation.
headers: headers:

View File

@ -299,7 +299,7 @@ type RedisRecorder struct {
type RecorderObject struct { type RecorderObject struct {
Name string `json:"name"` Name string `json:"name"`
Record string `json:"record"` Record string `json:"record"`
Metadata map[string]any Metadata map[string]any `yaml:",omitempty" json:"metadata,omitempty"`
} }
type LimiterConfig struct { type LimiterConfig struct {

View File

@ -94,6 +94,10 @@ func (p *grpcPlugin) Select(ctx context.Context, opts ...hop.SelectOption) *chai
} }
func (p *grpcPlugin) Close() error { func (p *grpcPlugin) Close() error {
if p.conn == nil {
return nil
}
if closer, ok := p.conn.(io.Closer); ok { if closer, ok := p.conn.(io.Closer); ok {
return closer.Close() return closer.Close()
} }

View File

@ -71,6 +71,10 @@ func (p *grpcPlugin) Lookup(ctx context.Context, network, host string, opts ...h
} }
func (p *grpcPlugin) Close() error { func (p *grpcPlugin) Close() error {
if p.conn == nil {
return nil
}
if closer, ok := p.conn.(io.Closer); ok { if closer, ok := p.conn.(io.Closer); ok {
return closer.Close() return closer.Close()
} }

View File

@ -82,6 +82,10 @@ func (p *grpcPlugin) SetRule(ctx context.Context, rule *ingress.Rule, opts ...in
} }
func (p *grpcPlugin) Close() error { func (p *grpcPlugin) Close() error {
if p.conn == nil {
return nil
}
if closer, ok := p.conn.(io.Closer); ok { if closer, ok := p.conn.(io.Closer); ok {
return closer.Close() return closer.Close()
} }

View File

@ -95,6 +95,10 @@ func (p *grpcPlugin) Out(ctx context.Context, key string, opts ...traffic.Option
} }
func (p *grpcPlugin) Close() error { func (p *grpcPlugin) Close() error {
if p.conn == nil {
return nil
}
if closer, ok := p.conn.(io.Closer); ok { if closer, ok := p.conn.(io.Closer); ok {
return closer.Close() return closer.Close()
} }

View File

@ -33,6 +33,7 @@ func NewGRPCPlugin(name string, addr string, opts ...plugin.Option) observer.Obs
conn, err := plugin.NewGRPCConn(addr, &options) conn, err := plugin.NewGRPCConn(addr, &options)
if err != nil { if err != nil {
log.Error(err) log.Error(err)
return nil
} }
p := &grpcPlugin{ p := &grpcPlugin{

View File

@ -6,6 +6,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"strings"
"github.com/go-gost/core/logger" "github.com/go-gost/core/logger"
"github.com/go-gost/core/observer" "github.com/go-gost/core/observer"
@ -58,6 +59,9 @@ func NewHTTPPlugin(name string, url string, opts ...plugin.Option) observer.Obse
opt(&options) opt(&options)
} }
if !strings.HasPrefix(url, "http") {
url = "http://" + url
}
return &httpPlugin{ return &httpPlugin{
url: url, url: url,
client: plugin.NewHTTPClient(&options), client: plugin.NewHTTPClient(&options),

View File

@ -69,6 +69,10 @@ func (p *grpcPlugin) Record(ctx context.Context, b []byte, opts ...recorder.Reco
} }
func (p *grpcPlugin) Close() error { func (p *grpcPlugin) Close() error {
if p.conn == nil {
return nil
}
if closer, ok := p.conn.(io.Closer); ok { if closer, ok := p.conn.(io.Closer); ok {
return closer.Close() return closer.Close()
} }

View File

@ -70,6 +70,10 @@ func (p *grpcPlugin) Resolve(ctx context.Context, network, host string, opts ...
} }
func (p *grpcPlugin) Close() error { func (p *grpcPlugin) Close() error {
if p.conn == nil {
return nil
}
if closer, ok := p.conn.(io.Closer); ok { if closer, ok := p.conn.(io.Closer); ok {
return closer.Close() return closer.Close()
} }

View File

@ -63,6 +63,10 @@ func (p *grpcPlugin) GetRoute(ctx context.Context, dst net.IP, opts ...router.Op
} }
func (p *grpcPlugin) Close() error { func (p *grpcPlugin) Close() error {
if p.conn == nil {
return nil
}
if closer, ok := p.conn.(io.Closer); ok { if closer, ok := p.conn.(io.Closer); ok {
return closer.Close() return closer.Close()
} }

View File

@ -127,6 +127,10 @@ func (p *grpcPlugin) Get(ctx context.Context, name string) ([]*sd.Service, error
} }
func (p *grpcPlugin) Close() error { func (p *grpcPlugin) Close() error {
if p.conn == nil {
return nil
}
if closer, ok := p.conn.(io.Closer); ok { if closer, ok := p.conn.(io.Closer); ok {
return closer.Close() return closer.Close()
} }