refactor(openflare): unify protocol API responses to Wavelet format

Migrate Agent/Relay/Tunnel handlers from compat {success,message,data}
to response.OK and response.Abort* with real HTTP status codes. Remove
the compat package and update openflare-agent, openflare-relay, and
openflared clients to parse {error_msg,data}.
This commit is contained in:
ryan
2026-06-19 11:23:12 +08:00
parent 42ca0ec642
commit 33b4123444
18 changed files with 230 additions and 358 deletions
@@ -5,7 +5,6 @@ package integration
import (
"context"
"encoding/json"
"net/http"
"testing"
@@ -93,22 +92,9 @@ func TestAgentRelayFlaredProtocol(t *testing.T) {
})
assert.Equal(t, http.StatusOK, rec.Code)
envelope := decodeEnvelope(t, rec)
assert.True(t, envelope.Success)
var heartbeatBody struct {
Success bool `json:"success"`
Data any `json:"data"`
AgentSettings any `json:"agent_settings"`
}
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &heartbeatBody))
assert.True(t, heartbeatBody.Success)
assert.NotNil(t, heartbeatBody.AgentSettings)
stored, err := model.GetOpenFlareNodeByNodeID(ctx, edge.NodeID)
require.NoError(t, err)
assert.Equal(t, "online", stored.Status)
assert.Equal(t, "0.1.0", stored.Version)
resp := requireAPIOK(t, rec)
data := unmarshalAPIMap(t, resp.Data)
assert.NotNil(t, data["agent_settings"])
})
t.Run("create tunnel_relay node and relay heartbeat", func(t *testing.T) {
@@ -130,14 +116,12 @@ func TestAgentRelayFlaredProtocol(t *testing.T) {
})
assert.Equal(t, http.StatusOK, rec.Code)
envelope := decodeEnvelope(t, rec)
assert.True(t, envelope.Success)
resp := requireAPIOK(t, rec)
var heartbeatData struct {
RelayConfig map[string]any `json:"relay_config"`
RelaySettings map[string]any `json:"relay_settings"`
}
unmarshalEnvelopeData(t, envelope.Data, &heartbeatData)
unmarshalAPIData(t, resp.Data, &heartbeatData)
assert.NotNil(t, heartbeatData.RelayConfig)
assert.NotNil(t, heartbeatData.RelaySettings)
@@ -163,9 +147,7 @@ func TestAgentRelayFlaredProtocol(t *testing.T) {
"X-Tunnel-Token": clientNode.AccessToken,
})
assert.Equal(t, http.StatusOK, rec.Code)
envelope := decodeEnvelope(t, rec)
assert.True(t, envelope.Success)
requireAPIOK(t, rec)
stored, err := model.GetOpenFlareNodeByNodeID(ctx, clientNode.NodeID)
require.NoError(t, err)
@@ -187,11 +169,9 @@ func TestAgentRelayFlaredProtocol(t *testing.T) {
})
assert.Equal(t, http.StatusOK, rec.Code)
envelope := decodeEnvelope(t, rec)
assert.True(t, envelope.Success)
resp := requireAPIOK(t, rec)
var registration agent.RegistrationResponse
unmarshalEnvelopeData(t, envelope.Data, &registration)
unmarshalAPIData(t, resp.Data, &registration)
assert.NotEmpty(t, registration.NodeID)
assert.NotEmpty(t, registration.AccessToken)
assert.Equal(t, "discovered-edge", registration.Name)
@@ -218,11 +198,9 @@ func TestAgentRelayFlaredProtocol(t *testing.T) {
})
assert.Equal(t, http.StatusOK, rec.Code)
envelope := decodeEnvelope(t, rec)
assert.True(t, envelope.Success)
resp := requireAPIOK(t, rec)
var applyLog model.OpenFlareApplyLog
unmarshalEnvelopeData(t, envelope.Data, &applyLog)
unmarshalAPIData(t, resp.Data, &applyLog)
assert.Equal(t, edge.NodeID, applyLog.NodeID)
assert.Equal(t, "success", applyLog.Result)
assert.Equal(t, "20260618-001", applyLog.Version)
@@ -232,4 +210,4 @@ func TestAgentRelayFlaredProtocol(t *testing.T) {
assert.Equal(t, "online", stored.Status)
assert.Equal(t, "20260618-001", stored.CurrentVersion)
})
}
}
@@ -222,10 +222,8 @@ func TestCoreChainMigrationFlow(t *testing.T) {
})
require.Equal(t, http.StatusOK, rec.Code)
envelope := decodeEnvelope(t, rec)
require.True(t, envelope.Success, envelope.Message)
data := unmarshalEnvelopeMap(t, envelope.Data)
resp := requireAPIOK(t, rec)
data := unmarshalAPIMap(t, resp.Data)
assert.Equal(t, nodePublicID, data["node_id"])
assert.Equal(t, configVersion, data["version"])
assert.Equal(t, "success", data["result"])
@@ -10,7 +10,6 @@ import (
"net/http/httptest"
"testing"
"github.com/Rain-kl/Wavelet/internal/apps/openflare/compat"
"github.com/Rain-kl/Wavelet/internal/common/response"
v1 "github.com/Rain-kl/Wavelet/internal/router/v1"
ofrouter "github.com/Rain-kl/Wavelet/internal/router/v1/openflare"
@@ -34,14 +33,6 @@ func requireAPIOK(t *testing.T, rec *httptest.ResponseRecorder) response.Any {
return resp
}
func decodeEnvelope(t *testing.T, rec *httptest.ResponseRecorder) compat.Envelope {
t.Helper()
var envelope compat.Envelope
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &envelope))
return envelope
}
func unmarshalAPIData(t *testing.T, data any, target any) {
t.Helper()
@@ -50,11 +41,6 @@ func unmarshalAPIData(t *testing.T, data any, target any) {
require.NoError(t, json.Unmarshal(payload, target))
}
func unmarshalEnvelopeData(t *testing.T, data any, target any) {
t.Helper()
unmarshalAPIData(t, data, target)
}
func unmarshalAPIMap(t *testing.T, data any) map[string]any {
t.Helper()
@@ -63,11 +49,6 @@ func unmarshalAPIMap(t *testing.T, data any) map[string]any {
return result
}
func unmarshalEnvelopeMap(t *testing.T, data any) map[string]any {
t.Helper()
return unmarshalAPIMap(t, data)
}
func unmarshalAPISlice(t *testing.T, data any) []any {
t.Helper()
@@ -76,11 +57,6 @@ func unmarshalAPISlice(t *testing.T, data any) []any {
return result
}
func unmarshalEnvelopeSlice(t *testing.T, data any) []any {
t.Helper()
return unmarshalAPISlice(t, data)
}
func mountOpenFlareTestRoutes(engine *gin.Engine) {
api := engine.Group("/api")
apiV1 := api.Group("/v1")
@@ -120,19 +96,8 @@ func performJSONRequest(
return rec
}
func performLegacyRequest(
t *testing.T,
engine http.Handler,
method, path string,
body any,
headers map[string]string,
) *httptest.ResponseRecorder {
t.Helper()
return performJSONRequest(t, engine, method, path, body, headers)
}
func adminAuthHeaders(token string) map[string]string {
return map[string]string{
"X-Access-Token": token,
}
}
}
@@ -108,7 +108,7 @@ func TestSecurityWAFTLSMigrationFlow(t *testing.T) {
)
t.Run("WAF rule group create", func(t *testing.T) {
rec := performLegacyRequest(t, engine, http.MethodPost, apiPath("/waf/rule-groups"), map[string]any{
rec := performJSONRequest(t, engine, http.MethodPost, apiPath("/waf/rule-groups"), map[string]any{
"name": "edge-security",
"enabled": true,
"block_status_code": 403,
@@ -129,7 +129,7 @@ func TestSecurityWAFTLSMigrationFlow(t *testing.T) {
})
t.Run("WAF rule group list includes global and custom groups", func(t *testing.T) {
rec := performLegacyRequest(t, engine, http.MethodGet, apiPath("/waf/rule-groups"), nil, adminAuthHeaders(seed.Token))
rec := performJSONRequest(t, engine, http.MethodGet, apiPath("/waf/rule-groups"), nil, adminAuthHeaders(seed.Token))
require.Equal(t, http.StatusOK, rec.Code)
resp := requireAPIOK(t, rec)
@@ -154,7 +154,7 @@ func TestSecurityWAFTLSMigrationFlow(t *testing.T) {
})
t.Run("WAF rule group get detail", func(t *testing.T) {
rec := performLegacyRequest(
rec := performJSONRequest(
t,
engine,
http.MethodGet,
@@ -171,7 +171,7 @@ func TestSecurityWAFTLSMigrationFlow(t *testing.T) {
})
t.Run("WAF rule group update", func(t *testing.T) {
rec := performLegacyRequest(
rec := performJSONRequest(
t,
engine,
http.MethodPost,
@@ -193,7 +193,7 @@ func TestSecurityWAFTLSMigrationFlow(t *testing.T) {
})
t.Run("WAF IP group create", func(t *testing.T) {
rec := performLegacyRequest(t, engine, http.MethodPost, apiPath("/waf/ip-groups"), map[string]any{
rec := performJSONRequest(t, engine, http.MethodPost, apiPath("/waf/ip-groups"), map[string]any{
"name": "blocked-ips",
"type": "manual",
"enabled": true,
@@ -211,7 +211,7 @@ func TestSecurityWAFTLSMigrationFlow(t *testing.T) {
})
t.Run("create proxy route for WAF binding", func(t *testing.T) {
rec := performLegacyRequest(t, engine, http.MethodPost, apiPath("/proxy-routes/"), map[string]any{
rec := performJSONRequest(t, engine, http.MethodPost, apiPath("/proxy-routes/"), map[string]any{
"site_name": "security-site",
"domain": "security.example.com",
"origin_url": "http://origin.security.internal:8080",
@@ -227,7 +227,7 @@ func TestSecurityWAFTLSMigrationFlow(t *testing.T) {
})
t.Run("bind WAF rule group to proxy route", func(t *testing.T) {
rec := performLegacyRequest(
rec := performJSONRequest(
t,
engine,
http.MethodPost,
@@ -250,7 +250,7 @@ func TestSecurityWAFTLSMigrationFlow(t *testing.T) {
})
t.Run("verify site rule groups binding", func(t *testing.T) {
rec := performLegacyRequest(
rec := performJSONRequest(
t,
engine,
http.MethodGet,
@@ -275,7 +275,7 @@ func TestSecurityWAFTLSMigrationFlow(t *testing.T) {
t.Run("create TLS certificate with PEM", func(t *testing.T) {
certPEM, keyPEM := generateSelfSignedCertificatePair(t, []string{"security.example.com"})
rec := performLegacyRequest(t, engine, http.MethodPost, apiPath("/tls-certificates/"), map[string]any{
rec := performJSONRequest(t, engine, http.MethodPost, apiPath("/tls-certificates/"), map[string]any{
"name": "security-cert",
"cert_pem": certPEM,
"key_pem": keyPEM,
@@ -292,7 +292,7 @@ func TestSecurityWAFTLSMigrationFlow(t *testing.T) {
})
t.Run("create managed domain", func(t *testing.T) {
rec := performLegacyRequest(t, engine, http.MethodPost, apiPath("/managed-domains/"), map[string]any{
rec := performJSONRequest(t, engine, http.MethodPost, apiPath("/managed-domains/"), map[string]any{
"domain": "security.example.com",
"cert_id": certID,
"enabled": true,
@@ -310,7 +310,7 @@ func TestSecurityWAFTLSMigrationFlow(t *testing.T) {
})
t.Run("create DNS account", func(t *testing.T) {
rec := performLegacyRequest(t, engine, http.MethodPost, apiPath("/dns-accounts/"), map[string]any{
rec := performJSONRequest(t, engine, http.MethodPost, apiPath("/dns-accounts/"), map[string]any{
"name": "cloudflare-dns",
"type": "cloudflare",
"authorization": "test-api-token-value",
@@ -330,7 +330,7 @@ func TestSecurityWAFTLSMigrationFlow(t *testing.T) {
})
t.Run("WAF rule group delete", func(t *testing.T) {
rec := performLegacyRequest(
rec := performJSONRequest(
t,
engine,
http.MethodPost,
@@ -341,7 +341,7 @@ func TestSecurityWAFTLSMigrationFlow(t *testing.T) {
require.Equal(t, http.StatusOK, rec.Code)
requireAPIOK(t, rec)
detailRec := performLegacyRequest(
detailRec := performJSONRequest(
t,
engine,
http.MethodGet,