-
-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into feat/support-not-linux
- Loading branch information
Showing
25 changed files
with
714 additions
and
169 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# myshoes-sdk-go | ||
|
||
The Go SDK for myshoes | ||
|
||
## Usage | ||
|
||
```go | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
"log" | ||
"net/http" | ||
|
||
"github.com/whywaita/myshoes/api/myshoes" | ||
) | ||
|
||
func main() { | ||
// Set customized HTTP Client | ||
customHTTPClient := http.DefaultClient | ||
// Set customized logger | ||
customLogger := log.New(io.Discard, "", log.LstdFlags) | ||
|
||
client, err := myshoes.NewClient("https://example.com", customHTTPClient, customLogger) | ||
if err != nil { | ||
// ... | ||
} | ||
|
||
targets, err := client.ListTarget(context.Background()) | ||
if err != nil { | ||
// ... | ||
} | ||
|
||
fmt.Println(targets) | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package myshoes | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
"log" | ||
"net/http" | ||
"net/url" | ||
"path" | ||
"strings" | ||
) | ||
|
||
// Client is a client for myshoes | ||
type Client struct { | ||
HTTPClient http.Client | ||
URL *url.URL | ||
|
||
UserAgent string | ||
Logger *log.Logger | ||
} | ||
|
||
const ( | ||
defaultUserAgent = "myshoes-sdk-go" | ||
) | ||
|
||
// NewClient create a Client | ||
func NewClient(endpoint string, client *http.Client, logger *log.Logger) (*Client, error) { | ||
u, err := url.Parse(endpoint) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to parse endpoint: %w", err) | ||
} | ||
|
||
httpClient := client | ||
if httpClient == nil { | ||
httpClient = http.DefaultClient | ||
} | ||
l := logger | ||
if l == nil { | ||
// Default is discard logger | ||
l = log.New(io.Discard, "", log.LstdFlags) | ||
} | ||
|
||
return &Client{ | ||
HTTPClient: *httpClient, | ||
URL: u, | ||
|
||
Logger: logger, | ||
}, nil | ||
} | ||
|
||
func (c *Client) newRequest(ctx context.Context, method, spath string, body io.Reader) (*http.Request, error) { | ||
u := *c.URL | ||
u.Path = path.Join(c.URL.Path, spath) | ||
|
||
req, err := http.NewRequestWithContext(ctx, method, u.String(), body) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to create a new HTTP request: %w", err) | ||
} | ||
|
||
ua := c.UserAgent | ||
if strings.EqualFold(ua, "") { | ||
ua = defaultUserAgent | ||
} | ||
req.Header.Set("User-Agent", ua) | ||
|
||
req.Header.Set("Content-Type", "application/json") | ||
|
||
return req, nil | ||
} | ||
|
||
// Error values | ||
var ( | ||
errCreateRequest = "failed to create request: %w" | ||
errRequest = "failed to request: %w" | ||
errDecodeBody = "failed to decodeBody: %w" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package myshoes | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
|
||
"github.com/whywaita/myshoes/pkg/web" | ||
) | ||
|
||
func decodeBody(resp *http.Response, out interface{}) error { | ||
defer resp.Body.Close() | ||
|
||
decoder := json.NewDecoder(resp.Body) | ||
return decoder.Decode(out) | ||
} | ||
|
||
func decodeErrorBody(resp *http.Response) error { | ||
var e web.ErrorResponse | ||
|
||
if err := decodeBody(resp, &e); err != nil { | ||
return fmt.Errorf(errDecodeBody, err) | ||
} | ||
|
||
return fmt.Errorf("%s", e.Error) | ||
} | ||
|
||
func (c *Client) request(req *http.Request, out interface{}) error { | ||
c.Logger.Printf("Do request: %+v", req) | ||
resp, err := c.HTTPClient.Do(req) | ||
if err != nil { | ||
return fmt.Errorf("failed to do HTTP request: %w", err) | ||
} | ||
|
||
switch { | ||
case resp.StatusCode == http.StatusNoContent: | ||
return nil | ||
case resp.StatusCode >= 400: | ||
return decodeErrorBody(resp) | ||
} | ||
|
||
if err := decodeBody(resp, out); err != nil { | ||
return fmt.Errorf(errDecodeBody, err) | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package myshoes | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
|
||
"github.com/whywaita/myshoes/pkg/web" | ||
) | ||
|
||
// CreateTarget create a target | ||
func (c *Client) CreateTarget(ctx context.Context, param web.TargetCreateParam) (*web.UserTarget, error) { | ||
spath := "/target" | ||
|
||
jb, err := json.Marshal(param) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to json.Marshal: %w", err) | ||
} | ||
|
||
req, err := c.newRequest(ctx, http.MethodPost, spath, bytes.NewBuffer(jb)) | ||
if err != nil { | ||
return nil, fmt.Errorf(errCreateRequest, err) | ||
} | ||
|
||
var target web.UserTarget | ||
if err := c.request(req, &target); err != nil { | ||
return nil, fmt.Errorf(errRequest, err) | ||
} | ||
|
||
return &target, nil | ||
} | ||
|
||
// GetTarget get a target | ||
func (c *Client) GetTarget(ctx context.Context, targetID string) (*web.UserTarget, error) { | ||
spath := fmt.Sprintf("/target/%s", targetID) | ||
|
||
req, err := c.newRequest(ctx, http.MethodGet, spath, nil) | ||
if err != nil { | ||
return nil, fmt.Errorf(errCreateRequest, err) | ||
} | ||
|
||
var target web.UserTarget | ||
if err := c.request(req, &target); err != nil { | ||
return nil, fmt.Errorf(errRequest, err) | ||
} | ||
|
||
return &target, nil | ||
} | ||
|
||
// UpdateTarget update a target | ||
func (c *Client) UpdateTarget(ctx context.Context, targetID string, param web.TargetCreateParam) (*web.UserTarget, error) { | ||
spath := fmt.Sprintf("/target/%s", targetID) | ||
|
||
jb, err := json.Marshal(param) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to json.Marshal: %w", err) | ||
} | ||
|
||
req, err := c.newRequest(ctx, http.MethodPost, spath, bytes.NewBuffer(jb)) | ||
if err != nil { | ||
return nil, fmt.Errorf(errCreateRequest, err) | ||
} | ||
|
||
var target web.UserTarget | ||
if err := c.request(req, &target); err != nil { | ||
return nil, fmt.Errorf(errRequest, err) | ||
} | ||
|
||
return &target, nil | ||
} | ||
|
||
// DeleteTarget delete a target | ||
func (c *Client) DeleteTarget(ctx context.Context, targetID string) error { | ||
spath := fmt.Sprintf("/target/%s", targetID) | ||
|
||
req, err := c.newRequest(ctx, http.MethodDelete, spath, nil) | ||
if err != nil { | ||
return fmt.Errorf(errCreateRequest, err) | ||
} | ||
|
||
var i interface{} // this endpoint return N/A | ||
if err := c.request(req, &i); err != nil { | ||
return fmt.Errorf(errRequest, err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// ListTarget get a list of target | ||
func (c *Client) ListTarget(ctx context.Context) ([]web.UserTarget, error) { | ||
spath := "/target" | ||
|
||
req, err := c.newRequest(ctx, http.MethodGet, spath, nil) | ||
if err != nil { | ||
return nil, fmt.Errorf(errCreateRequest, err) | ||
} | ||
|
||
var targets []web.UserTarget | ||
if err := c.request(req, targets); err != nil { | ||
return nil, fmt.Errorf(errRequest, err) | ||
} | ||
|
||
return targets, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.