Update the HTTP client for easy use by add more util functions

This commit is contained in:
Wenkai Yin 2017-12-16 06:45:59 +08:00
parent a736cb7b09
commit 260ef561c4
3 changed files with 99 additions and 149 deletions

View File

@ -15,16 +15,10 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"strings"
"github.com/vmware/harbor/src/adminserver/systeminfo/imagestorage"
common_http "github.com/vmware/harbor/src/common/http"
"github.com/vmware/harbor/src/common/http"
"github.com/vmware/harbor/src/common/http/modifier/auth"
"github.com/vmware/harbor/src/common/utils"
)
@ -54,14 +48,14 @@ func NewClient(baseURL string, cfg *Config) Client {
}
if cfg != nil {
authorizer := auth.NewSecretAuthorizer(cfg.Secret)
client.client = common_http.NewClient(nil, authorizer)
client.client = http.NewClient(nil, authorizer)
}
return client
}
type client struct {
baseURL string
client *common_http.Client
client *http.Client
}
// Config contains configurations needed for client
@ -69,19 +63,6 @@ type Config struct {
Secret string
}
// TODO refactor the codes with methods of common_http.Client
// do creates request and authorizes it if authorizer is not nil
func (c *client) do(method, relativePath string, body io.Reader) (*http.Response, error) {
url := c.baseURL + relativePath
req, err := http.NewRequest(method, url, body)
if err != nil {
return nil, err
}
return c.client.Do(req)
}
func (c *client) Ping() error {
addr := strings.Split(c.baseURL, "://")[1]
if !strings.Contains(addr, ":") {
@ -93,96 +74,32 @@ func (c *client) Ping() error {
// GetCfgs ...
func (c *client) GetCfgs() (map[string]interface{}, error) {
resp, err := c.do(http.MethodGet, "/api/configurations", nil)
if err != nil {
return nil, err
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to get configurations: %d %s",
resp.StatusCode, b)
}
url := c.baseURL + "/api/configurations"
cfgs := map[string]interface{}{}
if err = json.Unmarshal(b, &cfgs); err != nil {
if err := c.client.Get(url, &cfgs); err != nil {
return nil, err
}
return cfgs, nil
}
// UpdateCfgs ...
func (c *client) UpdateCfgs(cfgs map[string]interface{}) error {
data, err := json.Marshal(cfgs)
if err != nil {
return err
}
resp, err := c.do(http.MethodPut, "/api/configurations", bytes.NewReader(data))
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
return fmt.Errorf("failed to update configurations: %d %s",
resp.StatusCode, b)
}
return nil
url := c.baseURL + "/api/configurations"
return c.client.Put(url, cfgs)
}
// ResetCfgs ...
func (c *client) ResetCfgs() error {
resp, err := c.do(http.MethodPost, "/api/configurations/reset", nil)
if err != nil {
return err
}
if resp.StatusCode != http.StatusOK {
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
return fmt.Errorf("failed to reset configurations: %d %s",
resp.StatusCode, b)
}
return nil
url := c.baseURL + "/api/configurations/reset"
return c.client.Post(url)
}
// Capacity ...
func (c *client) Capacity() (*imagestorage.Capacity, error) {
resp, err := c.do(http.MethodGet, "/api/systeminfo/capacity", nil)
if err != nil {
return nil, err
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to get capacity: %d %s",
resp.StatusCode, b)
}
url := c.baseURL + "/api/systeminfo/capacity"
capacity := &imagestorage.Capacity{}
if err = json.Unmarshal(b, capacity); err != nil {
if err := c.client.Get(url, capacity); err != nil {
return nil, err
}
return capacity, nil
}

View File

@ -15,20 +15,25 @@
package http
import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"net/http"
"github.com/vmware/harbor/src/common/http/modifier"
)
// Client wraps net/http.Client with modifiers, modifiers the request before sending it
// Client is a util for common HTTP operations, such Get, Head, Post, Put and Delete.
// Use Do instead if those methods can not meet your requirement
type Client struct {
modifiers []modifier.Modifier
client *http.Client
}
// NewClient creates an instance of Client. Use net/http.Client as the default value
// if c is nil.
// NewClient creates an instance of Client.
// Use net/http.Client as the default value if c is nil.
// Modifiers modify the request before sending it.
func NewClient(c *http.Client, modifiers ...modifier.Modifier) *Client {
client := &Client{
client: c,
@ -54,48 +59,104 @@ func (c *Client) Do(req *http.Request) (*http.Response, error) {
}
// Get ...
func (c *Client) Get(url string) (*http.Response, error) {
func (c *Client) Get(url string, v ...interface{}) error {
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return nil, err
return err
}
return c.Do(req)
data, err := c.do(req)
if err != nil {
return err
}
if len(v) == 0 {
return nil
}
return json.Unmarshal(data, v[0])
}
// Head ...
func (c *Client) Head(url string) (*http.Response, error) {
func (c *Client) Head(url string) error {
req, err := http.NewRequest(http.MethodHead, url, nil)
if err != nil {
return nil, err
return err
}
return c.Do(req)
_, err = c.do(req)
return err
}
// Post ...
func (c *Client) Post(url, bodyType string, body io.Reader) (*http.Response, error) {
req, err := http.NewRequest(http.MethodPost, url, body)
if err != nil {
return nil, err
func (c *Client) Post(url string, v ...interface{}) error {
var reader io.Reader
if len(v) > 0 {
data, err := json.Marshal(v[0])
if err != nil {
return err
}
reader = bytes.NewReader(data)
}
req.Header.Set("Content-Type", bodyType)
return c.Do(req)
req, err := http.NewRequest(http.MethodPost, url, reader)
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
_, err = c.do(req)
return err
}
// Put ...
func (c *Client) Put(url, bodyType string, body io.Reader) (*http.Response, error) {
req, err := http.NewRequest(http.MethodPut, url, body)
if err != nil {
return nil, err
func (c *Client) Put(url string, v ...interface{}) error {
var reader io.Reader
if len(v) > 0 {
data := []byte{}
data, err := json.Marshal(v[0])
if err != nil {
return err
}
reader = bytes.NewReader(data)
}
req.Header.Set("Content-Type", bodyType)
return c.Do(req)
req, err := http.NewRequest(http.MethodPut, url, reader)
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
_, err = c.do(req)
return err
}
// Delete ...
func (c *Client) Delete(url string) (*http.Response, error) {
func (c *Client) Delete(url string) error {
req, err := http.NewRequest(http.MethodDelete, url, nil)
if err != nil {
return err
}
_, err = c.do(req)
return err
}
func (c *Client) do(req *http.Request) ([]byte, error) {
resp, err := c.Do(req)
if err != nil {
return nil, err
}
return c.Do(req)
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode < 200 || resp.StatusCode > 299 {
return nil, &Error{
Code: resp.StatusCode,
Message: string(data),
}
}
return data, nil
}

View File

@ -15,12 +15,7 @@
package client
import (
"bytes"
"encoding/json"
"io/ioutil"
"net/http"
commonhttp "github.com/vmware/harbor/src/common/http"
"github.com/vmware/harbor/src/common/http"
"github.com/vmware/harbor/src/common/http/modifier/auth"
"github.com/vmware/harbor/src/jobservice/api"
)
@ -33,7 +28,7 @@ type Client interface {
// DefaultClient provides a default implement for the interface Client
type DefaultClient struct {
endpoint string
client *commonhttp.Client
client *http.Client
}
// Config contains configuration items needed for DefaultClient
@ -48,7 +43,7 @@ func NewDefaultClient(endpoint string, cfg *Config) *DefaultClient {
}
if cfg != nil {
c.client = commonhttp.NewClient(nil, auth.NewSecretAuthorizer(cfg.Secret))
c.client = http.NewClient(nil, auth.NewSecretAuthorizer(cfg.Secret))
}
return c
@ -57,28 +52,5 @@ func NewDefaultClient(endpoint string, cfg *Config) *DefaultClient {
// SubmitReplicationJob submits a replication job to the jobservice
func (d *DefaultClient) SubmitReplicationJob(replication *api.ReplicationReq) error {
url := d.endpoint + "/api/jobs/replication"
buffer := &bytes.Buffer{}
if err := json.NewEncoder(buffer).Encode(replication); err != nil {
return err
}
resp, err := d.client.Post(url, "application/json", buffer)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
message, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
return &commonhttp.Error{
Code: resp.StatusCode,
Message: string(message),
}
}
return nil
return d.client.Post(url, replication)
}