package client import ( "bytes" "encoding/json" "fmt" "io" "net/http" ) type APIClient struct { client *http.Client endpoint string } type Config struct { Endpoint string } type ClientError struct { error } var ErrorNotFound = &ClientError{fmt.Errorf("not found")} func NewAPIClient(conf Config) (*APIClient, error) { if conf.Endpoint == "" { return nil, fmt.Errorf("endpoint is required") } cli := APIClient{ client: http.DefaultClient, endpoint: conf.Endpoint, } return &cli, nil } func newRequest(method, path string, body io.Reader) (*http.Request, error) { req, err := http.NewRequest(method, path, body) if err != nil { return nil, err } req.Header.Set("Content-Type", "application/json") req.Header.Set("Accept", "application/json") req.Header.Set("User-Agent", "api-client-go:v0") return req, nil } func (c *APIClient) DoGET(path string) ([]byte, error) { req, err := newRequest("GET", c.endpoint+path, nil) if err != nil { return nil, err } resp, err := c.client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() if resp.StatusCode == http.StatusNotFound { return nil, ErrorNotFound } body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } if resp.StatusCode >= 400 { return nil, fmt.Errorf("unexpected status code %d: %s", resp.StatusCode, body) } return body, err } func (c *APIClient) DoPOST(path string, data interface{}) ([]byte, error) { dataBytes, err := json.Marshal(data) if err != nil { return nil, err } req, err := newRequest("POST", c.endpoint+path, bytes.NewBuffer(dataBytes)) if err != nil { return nil, err } resp, err := c.client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() if resp.StatusCode == http.StatusNotFound { return nil, ErrorNotFound } body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } if resp.StatusCode >= 400 { return nil, fmt.Errorf("unexpected status code %d: %s", resp.StatusCode, body) } return body, err } func (c *APIClient) DoPUT(path string, data interface{}) ([]byte, error) { dataBytes, err := json.Marshal(data) if err != nil { return nil, err } req, err := newRequest("PUT", c.endpoint+path, bytes.NewBuffer(dataBytes)) if err != nil { return nil, err } resp, err := c.client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() if resp.StatusCode == http.StatusNotFound { return nil, ErrorNotFound } body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } if resp.StatusCode >= 400 { return nil, fmt.Errorf("unexpected status code %d: %s", resp.StatusCode, body) } return body, err } func (c *APIClient) DoDELETE(path string) error { req, err := newRequest("DELETE", c.endpoint+path, nil) if err != nil { return err } resp, err := c.client.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode == http.StatusNotFound { return ErrorNotFound } body, err := io.ReadAll(resp.Body) if err != nil { return err } if resp.StatusCode >= 400 { return fmt.Errorf("unexpected status code %d: %s", resp.StatusCode, body) } return nil }
package client import ( "encoding/json" "strconv" "github.com/tcarreira/api-server/pkg/types" ) type peopleClient struct { client *APIClient } func (c *APIClient) People() *peopleClient { return &peopleClient{c} } func (c *peopleClient) Create(p *types.Person) error { data, err := c.client.DoPOST("/people", p) if err != nil { return err } var person types.Person err = json.Unmarshal(data, &person) if err != nil { return err } p.ID = person.ID // update the ID with server info return nil } func (c *peopleClient) Get(id int) (*types.Person, error) { data, err := c.client.DoGET("/people/" + strconv.Itoa(id)) if err != nil { return nil, err } var person types.Person err = json.Unmarshal(data, &person) if err != nil { return nil, err } return &person, nil } func (c *peopleClient) List() ([]*types.Person, error) { data, err := c.client.DoGET("/people") if err != nil { return nil, err } var people []*types.Person err = json.Unmarshal(data, &people) if err != nil { return nil, err } return people, nil } func (c *peopleClient) Update(id int, p *types.Person) error { data, err := c.client.DoPUT("/people/"+strconv.Itoa(id), p) if err != nil { return err } var person types.Person err = json.Unmarshal(data, &person) if err != nil { return err } p.ID = person.ID // update the ID with server info return nil } func (c *peopleClient) Delete(id int) error { return c.client.DoDELETE("/people/" + strconv.Itoa(id)) }
package client import ( "encoding/json" "strconv" "github.com/tcarreira/api-server/pkg/types" ) type petsClient struct { client *APIClient } func (c *APIClient) Pet() *petsClient { return &petsClient{c} } func (c *petsClient) Create(p *types.Pet) error { data, err := c.client.DoPOST("/pets", p) if err != nil { return err } var pet types.Pet err = json.Unmarshal(data, &pet) if err != nil { return err } p.ID = pet.ID // update the ID with server info return nil } func (c *petsClient) Get(id int) (*types.Pet, error) { data, err := c.client.DoGET("/pets/" + strconv.Itoa(id)) if err != nil { return nil, err } var pet types.Pet err = json.Unmarshal(data, &pet) if err != nil { return nil, err } return &pet, nil } func (c *petsClient) List() ([]*types.Pet, error) { data, err := c.client.DoGET("/pets") if err != nil { return nil, err } var pets []*types.Pet err = json.Unmarshal(data, &pets) if err != nil { return nil, err } return pets, nil } func (c *petsClient) Update(id int, p *types.Pet) error { data, err := c.client.DoPUT("/pets/"+strconv.Itoa(id), p) if err != nil { return err } var pet types.Pet err = json.Unmarshal(data, &pet) if err != nil { return err } p.ID = pet.ID // update the ID with server info return nil } func (c *petsClient) Delete(id int) error { return c.client.DoDELETE("/pets/" + strconv.Itoa(id)) }