修复节点信息API
This commit is contained in:
@@ -2,7 +2,9 @@ package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -197,9 +199,19 @@ func NodeTidalabSubmit(c *gin.Context) {
|
||||
|
||||
func NodeAlive(c *gin.Context) {
|
||||
node := c.MustGet("node").(*model.Server)
|
||||
setNodeLastCheck(node)
|
||||
|
||||
if c.Request.Method == http.MethodGet {
|
||||
Success(c, true)
|
||||
return
|
||||
}
|
||||
|
||||
var payload map[string][]string
|
||||
if err := c.ShouldBindJSON(&payload); err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
Success(c, true)
|
||||
return
|
||||
}
|
||||
Fail(c, 400, "invalid payload")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,17 +1,24 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"xboard-go/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const nodeAuthPayloadKey = "_node_auth_payload"
|
||||
|
||||
func NodeAuth() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
token := c.Query("token")
|
||||
nodeID := c.Query("node_id")
|
||||
nodeType := service.NormalizeServerType(c.Query("node_type"))
|
||||
token := nodeAuthValue(c, "token")
|
||||
nodeID := nodeAuthValue(c, "node_id")
|
||||
nodeType := service.NormalizeServerType(nodeAuthValue(c, "node_type"))
|
||||
|
||||
if token == "" || nodeID == "" {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"message": "missing node credentials"})
|
||||
@@ -49,3 +56,98 @@ func NodeAuth() gin.HandlerFunc {
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func nodeAuthValue(c *gin.Context, key string) string {
|
||||
if value := strings.TrimSpace(c.Query(key)); value != "" {
|
||||
return value
|
||||
}
|
||||
|
||||
if value := strings.TrimSpace(c.PostForm(key)); value != "" {
|
||||
return value
|
||||
}
|
||||
|
||||
switch key {
|
||||
case "token":
|
||||
if value := strings.TrimSpace(c.GetHeader("X-Server-Token")); value != "" {
|
||||
return value
|
||||
}
|
||||
if auth := strings.TrimSpace(c.GetHeader("Authorization")); len(auth) > 7 && strings.EqualFold(auth[:7], "Bearer ") {
|
||||
return strings.TrimSpace(auth[7:])
|
||||
}
|
||||
case "node_id":
|
||||
if value := strings.TrimSpace(c.GetHeader("X-Node-Id")); value != "" {
|
||||
return value
|
||||
}
|
||||
case "node_type":
|
||||
if value := strings.TrimSpace(c.GetHeader("X-Node-Type")); value != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
payload := nodeAuthPayload(c)
|
||||
if payload == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return nodeAuthString(payload[key])
|
||||
}
|
||||
|
||||
func nodeAuthPayload(c *gin.Context) map[string]any {
|
||||
if cached, ok := c.Get(nodeAuthPayloadKey); ok {
|
||||
if payload, ok := cached.(map[string]any); ok {
|
||||
return payload
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if c.Request == nil || c.Request.Body == nil {
|
||||
c.Set(nodeAuthPayloadKey, map[string]any(nil))
|
||||
return nil
|
||||
}
|
||||
|
||||
contentType := strings.ToLower(c.GetHeader("Content-Type"))
|
||||
if !strings.Contains(contentType, "application/json") {
|
||||
c.Set(nodeAuthPayloadKey, map[string]any(nil))
|
||||
return nil
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
c.Request.Body = io.NopCloser(bytes.NewBuffer(nil))
|
||||
c.Set(nodeAuthPayloadKey, map[string]any(nil))
|
||||
return nil
|
||||
}
|
||||
c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
|
||||
|
||||
if len(bytes.TrimSpace(body)) == 0 {
|
||||
c.Set(nodeAuthPayloadKey, map[string]any(nil))
|
||||
return nil
|
||||
}
|
||||
|
||||
var payload map[string]any
|
||||
if err := json.Unmarshal(body, &payload); err != nil {
|
||||
c.Set(nodeAuthPayloadKey, map[string]any(nil))
|
||||
return nil
|
||||
}
|
||||
|
||||
c.Set(nodeAuthPayloadKey, payload)
|
||||
return payload
|
||||
}
|
||||
|
||||
func nodeAuthString(value any) string {
|
||||
switch typed := value.(type) {
|
||||
case string:
|
||||
return strings.TrimSpace(typed)
|
||||
case json.Number:
|
||||
return strings.TrimSpace(typed.String())
|
||||
default:
|
||||
if value == nil {
|
||||
return ""
|
||||
}
|
||||
text := strings.TrimSpace(fmt.Sprint(value))
|
||||
if text == "<nil>" {
|
||||
return ""
|
||||
}
|
||||
return text
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
|
||||
var serverTypeAliases = map[string]string{
|
||||
"v2ray": "vmess",
|
||||
"v2node": "",
|
||||
"hysteria2": "hysteria",
|
||||
}
|
||||
|
||||
@@ -117,10 +118,11 @@ func NormalizeServerType(serverType string) string {
|
||||
}
|
||||
|
||||
func IsValidServerType(serverType string) bool {
|
||||
if serverType == "" {
|
||||
normalized := NormalizeServerType(serverType)
|
||||
if normalized == "" {
|
||||
return true
|
||||
}
|
||||
_, ok := validServerTypes[NormalizeServerType(serverType)]
|
||||
_, ok := validServerTypes[normalized]
|
||||
return ok
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user