Remove bridge bootstrap consume lane
This commit is contained in:
parent
647fa2e84a
commit
549bf6dbe4
@ -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 == "" {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -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":
|
||||
|
||||
Loading…
Reference in New Issue
Block a user