diff --git a/go/paddlecloud/get.go b/go/paddlecloud/get.go index f2b8d17f..e43a4212 100644 --- a/go/paddlecloud/get.go +++ b/go/paddlecloud/get.go @@ -5,6 +5,7 @@ import ( "encoding/json" "flag" "fmt" + "net/url" "os" "strings" "text/tabwriter" @@ -60,8 +61,8 @@ func (p *GetCommand) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{ } func workers(jobname string) error { - queryMap := make(map[string]string) - queryMap["jobname"] = jobname + var queryMap url.Values + queryMap.Add("jobname", jobname) respBody, err := GetCall(config.ActiveConfig.Endpoint+"/api/v1/workers/", queryMap) if err != nil { fmt.Fprintf(os.Stderr, "error getting workers: %v\n", err) diff --git a/go/paddlecloud/logs.go b/go/paddlecloud/logs.go index 3110d7ed..11e372d1 100644 --- a/go/paddlecloud/logs.go +++ b/go/paddlecloud/logs.go @@ -5,6 +5,7 @@ import ( "encoding/json" "flag" "fmt" + "net/url" "os" "strconv" @@ -43,11 +44,12 @@ func (p *LogsCommand) Execute(_ context.Context, f *flag.FlagSet, _ ...interface f.Usage() return subcommands.ExitFailure } - queryMap := make(map[string]string) - queryMap["n"] = strconv.FormatInt(int64(p.n), 10) - queryMap["w"] = p.w - queryMap["jobname"] = f.Arg(0) + var queryMap url.Values + queryMap.Add("n", strconv.FormatInt(int64(p.n), 10)) + queryMap.Add("w", p.w) + queryMap.Add("jobname", f.Arg(0)) + respBody, err := GetCall(config.ActiveConfig.Endpoint+"/api/v1/logs", queryMap) if err != nil { fmt.Fprintf(os.Stderr, "call paddle cloud error %v", err) diff --git a/go/paddlecloud/restclient.go b/go/paddlecloud/restclient.go index 04daea66..85dcab58 100644 --- a/go/paddlecloud/restclient.go +++ b/go/paddlecloud/restclient.go @@ -8,22 +8,23 @@ import ( "io/ioutil" "mime/multipart" "net/http" + "net/url" "os" ) -// HTTPOK is ok status of http api call +// HTTPOK is ok status of http api call. const HTTPOK = "200 OK" -var httpTransport = &http.Transport{} +var httpClient = &http.Client{Transport: &http.Transport{}} func makeRequest(uri string, method string, body io.Reader, - contentType string, query map[string]string, + contentType string, query url.Values, authHeader map[string]string) (*http.Request, error) { req, err := http.NewRequest(method, uri, nil) if err != nil { return nil, err } - // default contentType is application/json + // default contentType is application/json. if len(contentType) == 0 { req.Header.Set("Content-Type", "application/json") } else { @@ -34,17 +35,15 @@ func makeRequest(uri string, method string, body io.Reader, req.Header.Set(k, v) } - q := req.URL.Query() - for k, v := range query { - q.Add(k, v) + if query != nil { + req.URL.RawQuery = query.Encode() } - req.URL.RawQuery = q.Encode() return req, nil } -// makeRequestToken use client token to make a authorized request +// makeRequestToken use client token to make a authorized request. func makeRequestToken(uri string, method string, body io.Reader, - contentType string, query map[string]string) (*http.Request, error) { + contentType string, query url.Values) (*http.Request, error) { // get client token token, err := token() if err != nil { @@ -55,11 +54,10 @@ func makeRequestToken(uri string, method string, body io.Reader, return makeRequest(uri, method, body, contentType, query, authHeader) } -// NOTE: add other request makers if we need other auth methods +// NOTE: add other request makers if we need other auth methods. func getResponse(req *http.Request) ([]byte, error) { - client := &http.Client{Transport: httpTransport} - resp, err := client.Do(req) + resp, err := httpClient.Do(req) if err != nil { return []byte{}, err } @@ -67,12 +65,12 @@ func getResponse(req *http.Request) ([]byte, error) { if resp.Status != HTTPOK { return []byte{}, errors.New("server error: " + resp.Status) } - // FIXME: add more resp.Status checks + // FIXME: add more resp.Status checks. return ioutil.ReadAll(resp.Body) } -// GetCall make a GET call to targetURL with k-v params of query -func GetCall(targetURL string, query map[string]string) ([]byte, error) { +// GetCall make a GET call to targetURL with query. +func GetCall(targetURL string, query url.Values) ([]byte, error) { req, err := makeRequestToken(targetURL, "GET", nil, "", query) if err != nil { return []byte{}, err @@ -80,7 +78,7 @@ func GetCall(targetURL string, query map[string]string) ([]byte, error) { return getResponse(req) } -// PostCall make a POST call to targetURL with a json body +// PostCall make a POST call to targetURL with a json body. func PostCall(targetURL string, jsonString []byte) ([]byte, error) { req, err := makeRequestToken(targetURL, "POST", bytes.NewBuffer(jsonString), "", nil) if err != nil { @@ -89,7 +87,7 @@ func PostCall(targetURL string, jsonString []byte) ([]byte, error) { return getResponse(req) } -// DeleteCall make a DELETE call to targetURL with a json body +// DeleteCall make a DELETE call to targetURL with a json body. func DeleteCall(targetURL string, jsonString []byte) ([]byte, error) { req, err := makeRequestToken(targetURL, "DELETE", bytes.NewBuffer(jsonString), "", nil) if err != nil { @@ -98,7 +96,7 @@ func DeleteCall(targetURL string, jsonString []byte) ([]byte, error) { return getResponse(req) } -// PostFile make a POST call to HTTP server to upload a file +// PostFile make a POST call to HTTP server to upload a file. func PostFile(targetURL string, filename string) ([]byte, error) { bodyBuf := &bytes.Buffer{} bodyWriter := multipart.NewWriter(bodyBuf) @@ -132,3 +130,44 @@ func PostFile(targetURL string, filename string) ([]byte, error) { } return getResponse(req) } + +// PostChunkData makes a POST call to HTTP server to upload chunkdata. +func PostChunk(targetURL string, + chunkName string, reader io.Reader, len int64, boundary string) ([]byte, error) { + body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + if err := writer.SetBoundary(boundary); err != nil { + return nil, err + } + + part, err := writer.CreateFormFile("chunk", chunkName) + if err != nil { + return nil, err + } + + _, err = io.CopyN(part, reader, len) + if err != nil { + return nil, err + } + + contentType := writer.FormDataContentType() + writer.Close() + + req, err := makeRequestToken(targetURL, "POST", body, contentType, nil) + if err != nil { + return []byte{}, err + } + + return getResponse(req) +} + +// GetChunkData makes a GET call to HTTP server to download chunk data. +func GetChunk(targetURL string, + query url.Values) (*http.Response, error) { + req, err := makeRequestToken(targetURL, "GET", nil, "", query) + if err != nil { + return nil, err + } + + return httpClient.Do(req) +}