fix(nodes): bind form-encoded posts and skip node inbounds in central xray

The Node model only carried `json:` tags, so when the panel's axios
posted form-encoded bodies to /panel/api/nodes/add and /test, Gin's
form binder produced a zero-valued Node — empty Name, empty Address,
Port=0 — surfacing as "node name is required" and a probe URL of
"https://:0/...". Add `form:` tags so add/test bind correctly.

Also skip inbounds with NodeID set when building the central xray
config; otherwise the central panel tried to listen on ports owned by
node-managed inbounds and xray-core failed to start with a bind
collision.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
MHSanaei 2026-05-10 11:32:06 +02:00
parent 14165fc54d
commit f70e131dfe
No known key found for this signature in database
GPG key ID: 7E4060F2FBE5AB7A
2 changed files with 12 additions and 9 deletions

View file

@ -128,15 +128,15 @@ type Setting struct {
// endpoint over HTTP using the per-node ApiToken to populate the runtime
// status fields below.
type Node struct {
Id int `json:"id" gorm:"primaryKey;autoIncrement"`
Name string `json:"name" gorm:"uniqueIndex"`
Remark string `json:"remark"`
Scheme string `json:"scheme"` // "https" | "http"
Address string `json:"address"` // host or IP
Port int `json:"port"`
BasePath string `json:"basePath"` // "/" or "/myprefix/"
ApiToken string `json:"apiToken"` // plaintext, matches existing tg/ldap pattern
Enable bool `json:"enable" gorm:"default:true"`
Id int `json:"id" form:"id" gorm:"primaryKey;autoIncrement"`
Name string `json:"name" form:"name" gorm:"uniqueIndex"`
Remark string `json:"remark" form:"remark"`
Scheme string `json:"scheme" form:"scheme"`
Address string `json:"address" form:"address"`
Port int `json:"port" form:"port"`
BasePath string `json:"basePath" form:"basePath"`
ApiToken string `json:"apiToken" form:"apiToken"`
Enable bool `json:"enable" form:"enable" gorm:"default:true"`
// Heartbeat-updated fields. UpdatedAt advances on every probe even when
// the row is otherwise unchanged so the UI's "last seen" tooltip is

View file

@ -113,6 +113,9 @@ func (s *XrayService) GetXrayConfig() (*xray.Config, error) {
if !inbound.Enable {
continue
}
if inbound.NodeID != nil {
continue
}
// get settings clients
settings := map[string]any{}
json.Unmarshal([]byte(inbound.Settings), &settings)