Files
goyomi/internal/httpclient/graphql.go
T
2026-05-11 06:48:23 +00:00

56 lines
1.2 KiB
Go
Executable File

package httpclient
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
)
type GraphQLRequest struct {
Query string `json:"query"`
Variables any `json:"variables,omitempty"`
}
type graphQLResponse[T any] struct {
Data T `json:"data"`
Errors []struct {
Message string `json:"message"`
} `json:"errors"`
}
// Post sends a GraphQL request and unmarshals the `data` field into T.
func Post[T any](ctx context.Context, client *http.Client, url string, req GraphQLRequest, headers map[string]string) (T, error) {
var zero T
body, err := json.Marshal(req)
if err != nil {
return zero, err
}
httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body))
if err != nil {
return zero, err
}
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("Accept", "application/json")
for k, v := range headers {
httpReq.Header.Set(k, v)
}
resp, err := client.Do(httpReq)
if err != nil {
return zero, err
}
defer resp.Body.Close()
var gqlResp graphQLResponse[T]
if err := json.NewDecoder(resp.Body).Decode(&gqlResp); err != nil {
return zero, err
}
if len(gqlResp.Errors) > 0 {
return zero, fmt.Errorf("graphql: %s", gqlResp.Errors[0].Message)
}
return gqlResp.Data, nil
}