mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-09-28 07:36:38 +08:00
fix: validate tunnel probe target before cleanup
This commit is contained in:
@@ -884,16 +884,7 @@ func (h *Handler) tunnelUpdate(w http.ResponseWriter, r *http.Request) {
|
||||
response.WriteJSON(w, response.ErrDefault("隧道ID不能为空"))
|
||||
return
|
||||
}
|
||||
oldEntryNodeIDs, _ := h.tunnelEntryNodeIDs(id)
|
||||
typeVal := asInt(req["type"], 1)
|
||||
oldTunnel, _ := h.getTunnelRecord(id)
|
||||
oldChainRows, _ := h.listChainNodesForTunnel(id)
|
||||
if oldTunnel != nil && oldTunnel.Type == 2 && typeVal != 2 {
|
||||
h.cleanupTunnelRuntime(id)
|
||||
}
|
||||
h.cleanupFederationRuntime(id)
|
||||
|
||||
now := time.Now().UnixMilli()
|
||||
ipPreference := asString(req["ipPreference"])
|
||||
probeTarget, probeTargetConfigured, err := parseTunnelProbeTargetFromRequest(req)
|
||||
if err != nil {
|
||||
@@ -906,6 +897,15 @@ func (h *Handler) tunnelUpdate(w http.ResponseWriter, r *http.Request) {
|
||||
probeTargetHost = probeTarget.Host
|
||||
probeTargetPort = probeTarget.Port
|
||||
}
|
||||
oldEntryNodeIDs, _ := h.tunnelEntryNodeIDs(id)
|
||||
oldTunnel, _ := h.getTunnelRecord(id)
|
||||
oldChainRows, _ := h.listChainNodesForTunnel(id)
|
||||
if oldTunnel != nil && oldTunnel.Type == 2 && typeVal != 2 {
|
||||
h.cleanupTunnelRuntime(id)
|
||||
}
|
||||
h.cleanupFederationRuntime(id)
|
||||
|
||||
now := time.Now().UnixMilli()
|
||||
localDomain := h.federationLocalDomain()
|
||||
|
||||
runtimeState, err := h.prepareTunnelCreateState(h.repo.DB(), req, typeVal, id)
|
||||
|
||||
@@ -99,6 +99,42 @@ func TestTunnelCreateRejectsInvalidProbeTarget(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTunnelUpdateInvalidProbeTargetDoesNotCleanFederationBindings(t *testing.T) {
|
||||
h := setupProbeTargetTunnelHandler(t)
|
||||
seedProbeTargetTunnel(t, h, 88, "existing", "old.example.com", 9443)
|
||||
seedProbeTargetFederationBinding(t, h, 88)
|
||||
body := bytes.NewReader([]byte(`{
|
||||
"id":88,
|
||||
"name":"existing",
|
||||
"type":1,
|
||||
"flow":1,
|
||||
"trafficRatio":1,
|
||||
"status":1,
|
||||
"inNodeId":[{"nodeId":10,"protocol":"tls"}],
|
||||
"probeTargetHost":"https://example.com",
|
||||
"probeTargetPort":443
|
||||
}`))
|
||||
|
||||
res := httptest.NewRecorder()
|
||||
h.tunnelUpdate(res, httptest.NewRequest(http.MethodPost, "/api/v1/tunnel/update", body))
|
||||
var payload struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
decodeProbeTargetResponse(t, res, &payload)
|
||||
if payload.Code == 0 || payload.Msg == "" {
|
||||
t.Fatalf("expected validation failure, got %+v", payload)
|
||||
}
|
||||
|
||||
bindings, err := h.repo.ListActiveFederationTunnelBindingsByTunnel(88)
|
||||
if err != nil {
|
||||
t.Fatalf("list federation bindings: %v", err)
|
||||
}
|
||||
if len(bindings) != 1 {
|
||||
t.Fatalf("expected federation binding to remain after invalid update, got %d", len(bindings))
|
||||
}
|
||||
}
|
||||
|
||||
func setupProbeTargetTunnelHandler(t *testing.T) *Handler {
|
||||
t.Helper()
|
||||
r, err := repo.Open(filepath.Join(t.TempDir(), "panel.db"))
|
||||
@@ -134,6 +170,17 @@ func seedProbeTargetTunnel(t *testing.T, h *Handler, id int64, name string, host
|
||||
}
|
||||
}
|
||||
|
||||
func seedProbeTargetFederationBinding(t *testing.T, h *Handler, tunnelID int64) {
|
||||
t.Helper()
|
||||
now := time.Now().UnixMilli()
|
||||
if err := h.repo.DB().Exec(`
|
||||
INSERT INTO federation_tunnel_binding(tunnel_id, node_id, chain_type, hop_inx, remote_url, resource_key, remote_binding_id, allocated_port, status, created_time, updated_time)
|
||||
VALUES(?, 10, 1, 0, 'http://peer.example', ?, 'remote-binding', 30001, 1, ?, ?)
|
||||
`, tunnelID, "probe-target-test-binding", now, now).Error; err != nil {
|
||||
t.Fatalf("insert federation binding: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func assertProbeTargetSuccess(t *testing.T, res *httptest.ResponseRecorder) {
|
||||
t.Helper()
|
||||
var payload struct {
|
||||
|
||||
Reference in New Issue
Block a user