Skip to content

Instantly share code, notes, and snippets.

@lxdlam
Created October 23, 2023 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lxdlam/4c70cd8c654c04e99b50b1b043b43437 to your computer and use it in GitHub Desktop.
Save lxdlam/4c70cd8c654c04e99b50b1b043b43437 to your computer and use it in GitHub Desktop.
package http
import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"
)
type ClientConfig struct {
Endpoint string
Headers map[string]string
}
type Client struct {
client *http.Client
config *ClientConfig
}
func NewClient(config *ClientConfig) *Client {
return &Client{
client: &http.Client{},
config: config,
}
}
func (h *Client) URL(path string) string {
return h.config.Endpoint + path
}
func (h *Client) Do(req *http.Request) (*http.Response, error) {
for k, v := range h.config.Headers {
req.Header.Add(k, v)
}
return h.client.Do(req)
}
type httpOpt func(*http.Request)
func WithQuery(key, value string) httpOpt {
return func(req *http.Request) {
q := req.URL.Query()
q.Add(key, value)
req.URL.RawQuery = q.Encode()
}
}
type ClientFuncion[I, O any] func(context.Context, *I, ...httpOpt) (*O, error)
type ClientFunctionNoInput[O any] func(context.Context, ...httpOpt) (*O, error)
func Method[I, O any](client *Client, method, path string) ClientFuncion[I, O] {
return func(ctx context.Context, i *I, ho ...httpOpt) (*O, error) {
reqBody, err := json.Marshal(i)
if err != nil {
return nil, err
}
req, err := http.NewRequest(method, path, bytes.NewReader(reqBody))
if err != nil {
return nil, err
}
for _, o := range ho {
o(req)
}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
ret := new(O)
if err := json.Unmarshal(respBody, &ret); err != nil {
return nil, err
}
return ret, nil
}
}
func MethodEmitInput[O any](client *Client, method, path string) ClientFunctionNoInput[O] {
return func(ctx context.Context, ho ...httpOpt) (*O, error) {
req, err := http.NewRequest(method, path, nil)
if err != nil {
return nil, err
}
for _, o := range ho {
o(req)
}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
ret := new(O)
if err := json.Unmarshal(respBody, &ret); err != nil {
return nil, err
}
return ret, nil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment