mirror of
https://github.com/rclone/rclone.git
synced 2024-12-12 20:33:50 +08:00
136 lines
3.0 KiB
Go
136 lines
3.0 KiB
Go
package src
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
//Client struct
|
|
type Client struct {
|
|
token string
|
|
basePath string
|
|
HTTPClient *http.Client
|
|
}
|
|
|
|
//NewClient creates new client
|
|
func NewClient(token string, client ...*http.Client) *Client {
|
|
return newClientInternal(
|
|
token,
|
|
"https://cloud-api.yandex.com/v1/disk", //also "https://cloud-api.yandex.net/v1/disk" "https://cloud-api.yandex.ru/v1/disk"
|
|
client...)
|
|
}
|
|
|
|
func newClientInternal(token string, basePath string, client ...*http.Client) *Client {
|
|
c := &Client{
|
|
token: token,
|
|
basePath: basePath,
|
|
}
|
|
if len(client) != 0 {
|
|
c.HTTPClient = client[0]
|
|
} else {
|
|
c.HTTPClient = http.DefaultClient
|
|
}
|
|
return c
|
|
}
|
|
|
|
//ErrorHandler type
|
|
type ErrorHandler func(*http.Response) error
|
|
|
|
var defaultErrorHandler ErrorHandler = func(resp *http.Response) error {
|
|
if resp.StatusCode/100 == 5 {
|
|
return errors.New("server error")
|
|
}
|
|
|
|
if resp.StatusCode/100 == 4 {
|
|
var response DiskClientError
|
|
contents, _ := ioutil.ReadAll(resp.Body)
|
|
err := json.Unmarshal(contents, &response)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return response
|
|
}
|
|
|
|
if resp.StatusCode/100 == 3 {
|
|
return errors.New("redirect error")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (HTTPRequest *HTTPRequest) run(client *Client) ([]byte, error) {
|
|
var err error
|
|
values := make(url.Values)
|
|
if HTTPRequest.Parameters != nil {
|
|
for k, v := range HTTPRequest.Parameters {
|
|
values.Set(k, fmt.Sprintf("%v", v))
|
|
}
|
|
}
|
|
|
|
var req *http.Request
|
|
if HTTPRequest.Method == "POST" {
|
|
// TODO json serialize
|
|
req, err = http.NewRequest(
|
|
"POST",
|
|
client.basePath+HTTPRequest.Path,
|
|
strings.NewReader(values.Encode()))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// TODO
|
|
// req.Header.Set("Content-Type", "application/json")
|
|
} else {
|
|
req, err = http.NewRequest(
|
|
HTTPRequest.Method,
|
|
client.basePath+HTTPRequest.Path+"?"+values.Encode(),
|
|
nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
for headerName := range HTTPRequest.Headers {
|
|
var headerValues = HTTPRequest.Headers[headerName]
|
|
for _, headerValue := range headerValues {
|
|
req.Header.Set(headerName, headerValue)
|
|
}
|
|
}
|
|
return runRequest(client, req)
|
|
}
|
|
|
|
func runRequest(client *Client, req *http.Request) ([]byte, error) {
|
|
return runRequestWithErrorHandler(client, req, defaultErrorHandler)
|
|
}
|
|
|
|
func runRequestWithErrorHandler(client *Client, req *http.Request, errorHandler ErrorHandler) (out []byte, err error) {
|
|
resp, err := client.HTTPClient.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer CheckClose(resp.Body, &err)
|
|
|
|
return checkResponseForErrorsWithErrorHandler(resp, errorHandler)
|
|
}
|
|
|
|
func checkResponseForErrorsWithErrorHandler(resp *http.Response, errorHandler ErrorHandler) ([]byte, error) {
|
|
if resp.StatusCode/100 > 2 {
|
|
return nil, errorHandler(resp)
|
|
}
|
|
return ioutil.ReadAll(resp.Body)
|
|
}
|
|
|
|
// CheckClose is a utility function used to check the return from
|
|
// Close in a defer statement.
|
|
func CheckClose(c io.Closer, err *error) {
|
|
cerr := c.Close()
|
|
if *err == nil {
|
|
*err = cerr
|
|
}
|
|
}
|