Files
RenewCMS/internal/infrastructure/mcpserver/client.go
T

78 lines
1.6 KiB
Go

package mcpserver
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"time"
)
const (
requestTimeout = 60 * time.Second
maxResponseSize = 8 << 20
)
type Client struct {
baseURL string
apiKey string
http *http.Client
}
type Response struct {
Status int
Body string
}
func NewClient(baseURL string, apiKey string, httpClient *http.Client) *Client {
if httpClient == nil {
httpClient = &http.Client{Timeout: requestTimeout}
}
return &Client{baseURL: strings.TrimRight(baseURL, "/"), apiKey: apiKey, http: httpClient}
}
func (c *Client) Do(ctx context.Context, method string, path string, query url.Values, body []byte, contentType string) (Response, error) {
target := c.baseURL + path
if len(query) > 0 {
target += "?" + query.Encode()
}
req, err := http.NewRequestWithContext(ctx, method, target, bytes.NewReader(body))
if err != nil {
return Response{}, err
}
if c.apiKey != "" {
req.Header.Set("Authorization", "Bearer "+c.apiKey)
}
if contentType != "" {
req.Header.Set("Content-Type", contentType)
}
res, err := c.http.Do(req)
if err != nil {
return Response{}, err
}
defer res.Body.Close()
raw, err := io.ReadAll(io.LimitReader(res.Body, maxResponseSize))
if err != nil {
return Response{}, err
}
return Response{Status: res.StatusCode, Body: string(raw)}, nil
}
func (r Response) Failed() bool {
return r.Status < 200 || r.Status > 299
}
func (r Response) Describe() string {
text := strings.TrimSpace(r.Body)
if r.Status == http.StatusNoContent || text == "" {
return fmt.Sprintf("HTTP %d", r.Status)
}
if r.Failed() {
return fmt.Sprintf("HTTP %d: %s", r.Status, text)
}
return text
}