refactor: extract generic graphql client

This commit is contained in:
2026-05-31 19:01:26 +02:00
parent 2b761127a0
commit 7f45e62dce
2 changed files with 142 additions and 47 deletions

79
pkg/graphql.go Normal file
View File

@@ -0,0 +1,79 @@
package graphql
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
)
type Error struct {
Message string `json:"message"`
}
type Response[T any] struct {
Data T `json:"data"`
Errors []Error `json:"errors"`
}
type PostOptions struct {
Headers map[string]string
BodyMax int64
}
func Post[T any](ctx context.Context, httpClient *http.Client, url string, query string, variables any, opts PostOptions) (T, error) {
var zero T
payload := map[string]any{
"query": query,
"variables": variables,
}
body, err := json.Marshal(payload)
if err != nil {
return zero, fmt.Errorf("graphql: marshal payload: %w", err)
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body))
if err != nil {
return zero, fmt.Errorf("graphql: create request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
for k, v := range opts.Headers {
req.Header.Set(k, v)
}
resp, err := httpClient.Do(req)
if err != nil {
return zero, fmt.Errorf("graphql: execute request: %w", err)
}
defer func() { _ = resp.Body.Close() }()
max := opts.BodyMax
if max <= 0 {
max = 2 << 20
}
respBody, err := io.ReadAll(io.LimitReader(resp.Body, max))
if err != nil {
return zero, fmt.Errorf("graphql: read response: %w", err)
}
if resp.StatusCode != http.StatusOK {
return zero, fmt.Errorf("graphql: status %d", resp.StatusCode)
}
var parsed Response[T]
if err := json.Unmarshal(respBody, &parsed); err != nil {
return zero, fmt.Errorf("graphql: decode response: %w", err)
}
if len(parsed.Errors) > 0 {
return zero, fmt.Errorf("graphql: %s", parsed.Errors[0].Message)
}
return parsed.Data, nil
}