Remove bridge bootstrap consume lane

This commit is contained in:
Haitao Pan 2026-04-13 19:28:35 +08:00
parent 647fa2e84a
commit 549bf6dbe4
3 changed files with 2 additions and 191 deletions

View File

@ -1,40 +1,13 @@
package acp
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
"xworkmate-bridge/internal/shared"
)
type bridgeBootstrapConsumeRequest struct {
Ticket string `json:"ticket"`
Bridge string `json:"bridge"`
}
type accountsBridgeBootstrapConsumeResponse struct {
TicketID string `json:"ticketId"`
TargetBridge string `json:"targetBridge"`
BridgeServerURL string `json:"BRIDGE_SERVER_URL"`
AuthMode string `json:"authMode"`
BridgeAuthToken string `json:"BRIDGE_AUTH_TOKEN"`
ExpiresAt string `json:"expiresAt"`
Scopes []string `json:"scopes"`
}
type bridgeBootstrapResponse struct {
SetupCode string `json:"setupCode"`
BridgeOrigin string `json:"bridgeOrigin"`
AuthMode string `json:"authMode"`
ExpiresAt string `json:"expiresAt"`
IssuedBy string `json:"issuedBy"`
Scopes []string `json:"scopes"`
}
func (s *Server) HandleBridgeBootstrapHealth(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
@ -48,96 +21,6 @@ func (s *Server) HandleBridgeBootstrapHealth(w http.ResponseWriter, r *http.Requ
})
}
func (s *Server) HandleBridgeBootstrapConsume(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
var req bridgeBootstrapConsumeRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "invalid request body", http.StatusBadRequest)
return
}
req.Ticket = strings.TrimSpace(req.Ticket)
req.Bridge = strings.TrimSpace(req.Bridge)
if req.Ticket == "" {
http.Error(w, "ticket is required", http.StatusBadRequest)
return
}
if req.Bridge == "" {
req.Bridge = bridgePublicBaseURL()
}
payload, status, err := consumeBootstrapFromAccounts(req)
if err != nil {
http.Error(w, err.Error(), status)
return
}
setupCodePayload := map[string]any{
"url": payload.BridgeServerURL,
"token": payload.BridgeAuthToken,
"BRIDGE_SERVER_URL": payload.BridgeServerURL,
"BRIDGE_AUTH_TOKEN": payload.BridgeAuthToken,
"authMode": payload.AuthMode,
"expiresAt": payload.ExpiresAt,
"bridgeOrigin": req.Bridge,
"issuedBy": "xworkmate-bridge",
}
setupCodeBytes, err := json.Marshal(setupCodePayload)
if err != nil {
http.Error(w, "failed to encode setup payload", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(bridgeBootstrapResponse{
SetupCode: string(setupCodeBytes),
BridgeOrigin: req.Bridge,
AuthMode: payload.AuthMode,
ExpiresAt: payload.ExpiresAt,
IssuedBy: "xworkmate-bridge",
Scopes: append([]string(nil), payload.Scopes...),
})
}
func consumeBootstrapFromAccounts(req bridgeBootstrapConsumeRequest) (accountsBridgeBootstrapConsumeResponse, int, error) {
baseURL := strings.TrimRight(strings.TrimSpace(shared.EnvOrDefault("ACCOUNTS_BASE_URL", "https://accounts.svc.plus")), "/")
if baseURL == "" {
return accountsBridgeBootstrapConsumeResponse{}, http.StatusInternalServerError, fmt.Errorf("accounts base url is not configured")
}
serviceToken := strings.TrimSpace(shared.EnvOrDefault("INTERNAL_SERVICE_TOKEN", ""))
if serviceToken == "" {
return accountsBridgeBootstrapConsumeResponse{}, http.StatusInternalServerError, fmt.Errorf("internal service token is not configured")
}
body, err := json.Marshal(req)
if err != nil {
return accountsBridgeBootstrapConsumeResponse{}, http.StatusInternalServerError, fmt.Errorf("failed to encode consume request")
}
httpReq, err := http.NewRequest(http.MethodPost, baseURL+"/api/internal/xworkmate/bridge/bootstrap/consume", bytes.NewReader(body))
if err != nil {
return accountsBridgeBootstrapConsumeResponse{}, http.StatusInternalServerError, fmt.Errorf("failed to create consume request")
}
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("X-Service-Token", serviceToken)
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Do(httpReq)
if err != nil {
return accountsBridgeBootstrapConsumeResponse{}, http.StatusBadGateway, fmt.Errorf("failed to contact accounts service")
}
defer func() {
_ = resp.Body.Close()
}()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return accountsBridgeBootstrapConsumeResponse{}, resp.StatusCode, fmt.Errorf("accounts bootstrap consume failed")
}
var payload accountsBridgeBootstrapConsumeResponse
if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil {
return accountsBridgeBootstrapConsumeResponse{}, http.StatusBadGateway, fmt.Errorf("failed to decode accounts bootstrap response")
}
return payload, http.StatusOK, nil
}
func bridgePublicBaseURL() string {
value := strings.TrimSpace(shared.EnvOrDefault("BRIDGE_PUBLIC_BASE_URL", "https://xworkmate-bridge.svc.plus"))
if value == "" {

View File

@ -1,70 +0,0 @@
package acp
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
)
func TestHandleBridgeBootstrapConsumeReturnsSetupCode(t *testing.T) {
accounts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/api/internal/xworkmate/bridge/bootstrap/consume" {
http.NotFound(w, r)
return
}
if got := r.Header.Get("X-Service-Token"); got != "internal-test-token" {
http.Error(w, "missing service token", http.StatusUnauthorized)
return
}
_ = json.NewEncoder(w).Encode(accountsBridgeBootstrapConsumeResponse{
TicketID: "ticket-1",
TargetBridge: "https://xworkmate-bridge.svc.plus",
BridgeServerURL: "https://xworkmate-bridge.svc.plus",
AuthMode: "shared-token",
BridgeAuthToken: "shared-token-value",
ExpiresAt: "2026-04-10T00:00:00Z",
Scopes: []string{"connect", "pairing.bootstrap"},
})
}))
defer accounts.Close()
t.Setenv("ACCOUNTS_BASE_URL", accounts.URL)
t.Setenv("INTERNAL_SERVICE_TOKEN", "internal-test-token")
t.Setenv("BRIDGE_PUBLIC_BASE_URL", "https://xworkmate-bridge.svc.plus")
server := NewServer()
body := bytes.NewBufferString(`{"ticket":"ticket-1","bridge":"https://xworkmate-bridge.svc.plus"}`)
request := httptest.NewRequest(http.MethodPost, "/bridge/bootstrap/consume", body)
recorder := httptest.NewRecorder()
server.HandleBridgeBootstrapConsume(recorder, request)
if recorder.Code != http.StatusOK {
t.Fatalf("expected consume success, got %d: %s", recorder.Code, recorder.Body.String())
}
var payload bridgeBootstrapResponse
if err := json.Unmarshal(recorder.Body.Bytes(), &payload); err != nil {
t.Fatalf("decode response: %v", err)
}
if payload.SetupCode == "" {
t.Fatalf("expected non-empty setup code")
}
var decoded map[string]any
if err := json.Unmarshal([]byte(payload.SetupCode), &decoded); err != nil {
t.Fatalf("decode setup code payload: %v", err)
}
if decoded["url"] != "https://xworkmate-bridge.svc.plus" {
t.Fatalf("expected bridge server url in setup payload, got %#v", decoded)
}
if decoded["token"] != "shared-token-value" {
t.Fatalf("expected bridge auth token in setup payload, got %#v", decoded)
}
if decoded["BRIDGE_SERVER_URL"] != "https://xworkmate-bridge.svc.plus" {
t.Fatalf("expected BRIDGE_SERVER_URL in setup payload, got %#v", decoded)
}
if decoded["BRIDGE_AUTH_TOKEN"] != "shared-token-value" {
t.Fatalf("expected BRIDGE_AUTH_TOKEN in setup payload, got %#v", decoded)
}
}

View File

@ -74,8 +74,8 @@ func Serve(args []string) error {
server := NewServer()
httpServer := &http.Server{
Addr: strings.TrimSpace(*listen),
Handler: server.Handler(),
Addr: strings.TrimSpace(*listen),
Handler: server.Handler(),
ReadTimeout: 30 * time.Second,
WriteTimeout: 5 * time.Minute,
IdleTimeout: 2 * time.Minute,
@ -119,8 +119,6 @@ func (s *Server) Handler() http.Handler {
})
case "/bridge/bootstrap/health":
s.HandleBridgeBootstrapHealth(w, r)
case "/bridge/bootstrap/consume":
s.HandleBridgeBootstrapConsume(w, r)
case "/acp/rpc":
s.HandleRPC(w, r)
case "/acp":