package centrifugo import ( "bytes" "encoding/json" "fmt" "io" "net/http" "time" ) // Client Centrifugo 客戶端 type Client struct { apiURL string apiKey string client *http.Client } // NewClient 創建新的 Centrifugo 客戶端 func NewClient(apiURL, apiKey string) *Client { return &Client{ apiURL: apiURL, apiKey: apiKey, client: &http.Client{ Timeout: 5 * time.Second, }, } } // PublishRequest Centrifugo 發布請求 type PublishRequest struct { Channel string `json:"channel"` Data interface{} `json:"data"` } // PublishResponse Centrifugo 發布響應 type PublishResponse struct { Error string `json:"error,omitempty"` Result interface{} `json:"result,omitempty"` } // Publish 發布訊息到指定頻道 func (c *Client) Publish(channel string, data []byte) error { req := PublishRequest{ Channel: channel, Data: json.RawMessage(data), } return c.publishJSON(req) } // PublishJSON 發布 JSON 訊息到指定頻道 func (c *Client) PublishJSON(channel string, data interface{}) error { req := PublishRequest{ Channel: channel, Data: data, } return c.publishJSON(req) } func (c *Client) publishJSON(req PublishRequest) error { body, err := json.Marshal(req) if err != nil { return fmt.Errorf("failed to marshal request: %w", err) } httpReq, err := http.NewRequest("POST", c.apiURL+"/publish", bytes.NewReader(body)) if err != nil { return fmt.Errorf("failed to create request: %w", err) } httpReq.Header.Set("Content-Type", "application/json") if c.apiKey != "" { httpReq.Header.Set("Authorization", "apikey "+c.apiKey) } resp, err := c.client.Do(httpReq) if err != nil { return fmt.Errorf("failed to send request: %w", err) } defer resp.Body.Close() respBody, err := io.ReadAll(resp.Body) if err != nil { return fmt.Errorf("failed to read response: %w", err) } if resp.StatusCode != http.StatusOK { return fmt.Errorf("centrifugo returned status %d: %s", resp.StatusCode, string(respBody)) } var publishResp PublishResponse if err := json.Unmarshal(respBody, &publishResp); err != nil { return fmt.Errorf("failed to unmarshal response: %w", err) } if publishResp.Error != "" { return fmt.Errorf("centrifugo error: %s", publishResp.Error) } return nil }