From 549bf6dbe47e40c2f09ca1346ba424b7210f1942 Mon Sep 17 00:00:00 2001 From: Haitao Pan Date: Mon, 13 Apr 2026 19:28:35 +0800 Subject: [PATCH] Remove bridge bootstrap consume lane --- internal/acp/bootstrap.go | 117 --------------------------------- internal/acp/bootstrap_test.go | 70 -------------------- internal/acp/server.go | 6 +- 3 files changed, 2 insertions(+), 191 deletions(-) delete mode 100644 internal/acp/bootstrap_test.go diff --git a/internal/acp/bootstrap.go b/internal/acp/bootstrap.go index 3191981..d15f93e 100644 --- a/internal/acp/bootstrap.go +++ b/internal/acp/bootstrap.go @@ -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 == "" { diff --git a/internal/acp/bootstrap_test.go b/internal/acp/bootstrap_test.go deleted file mode 100644 index 6e51b43..0000000 --- a/internal/acp/bootstrap_test.go +++ /dev/null @@ -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) - } -} diff --git a/internal/acp/server.go b/internal/acp/server.go index 086bfc3..1c71e91 100644 --- a/internal/acp/server.go +++ b/internal/acp/server.go @@ -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":