// JsonRequest JSON encodes and sends the object in reqData.ReqValue (if any) to the specified URL. // Optional method arguments are passed using the RequestData object. // Relevant RequestData fields: // ReqHeaders: additional HTTP header values to add to the request. // ExpectedStatus: the allowed HTTP response status values, else an error is returned. // ReqValue: the data object to send. // RespValue: the data object to decode the result into. func (c *Client) JsonRequest(method, url string, reqData *RequestData) (err error) { err = nil var body []byte if reqData.Params != nil { url += "?" + reqData.Params.Encode() } if sbody, ok := reqData.ReqValue.(string); ok { body = []byte(sbody) } else if reqData.ReqValue != nil { body, err = json.Marshal(reqData.ReqValue) if err != nil { err = errors.Newf(err, "failed marshalling the request body") return } } headers := c.createHeaders(reqData.ReqHeaders, contentTypeJSON) respBody, statusCode, err := c.sendRequest( method, url, bytes.NewReader(body), len(body), headers, reqData.ExpectedStatus) reqData.StatusCode = statusCode log.Tracef("%s:%s", method, url) if err != nil { return } err = unmarshallResponse(respBody, reqData) return }
func unmarshallResponse(respBody io.ReadCloser, reqData *RequestData) (err error) { defer respBody.Close() respData, err := ioutil.ReadAll(respBody) if err != nil { err = errors.Newf(err, "failed reading the response body") return } if len(respData) > 0 { if reqData.RespValue != nil { err = json.Unmarshal(respData, &reqData.RespValue) if err != nil { err = errors.Newf(err, "failed unmarshaling the response body: %s", respData) } } } return }
func (c *Client) sendRateLimitedRequest(method, URL string, headers http.Header, reqReader io.Reader, /*reqData []byte,*/ ) (resp *http.Response, err error) { for i := 0; i < c.maxSendAttempts; i++ { /* * var reqReader io.Reader * if reqData != nil { * reqReader = bytes.NewReader(reqData) * } */ req, err := http.NewRequest(method, URL, reqReader) if err != nil { err = errors.Newf(err, "failed creating the request %s", URL) return nil, err } for header, values := range headers { for _, value := range values { req.Header.Add(header, value) } } resp, err = c.Do(req) log.Tracef("%s: %s", method, URL) if err != nil { return nil, errors.Newf(err, "failed executing the request %s", URL) } if resp.StatusCode != http.StatusRequestEntityTooLarge || resp.Header.Get("Retry-After") == "" { return resp, nil } resp.Body.Close() retryAfter, err := strconv.ParseFloat(resp.Header.Get("Retry-After"), 32) if err != nil { return nil, errors.Newf(err, "Invalid Retry-After header %s", URL) } if retryAfter == 0 { return nil, errors.Newf(err, "Resource limit exeeded at URL %s", URL) } log.Debugf("Too many requests, retrying in %dms.", int(retryAfter*1000)) time.Sleep(time.Duration(retryAfter) * time.Second) } return nil, errors.Newf(err, "Maximum number of attempts (%d) reached sending request to %s", c.maxSendAttempts, URL) }
func (c *Client) PlainRequest(method, url string, reqData *RequestData) (resp []byte, err error) { err = nil var body []byte if reqData.Params != nil { url += "?" + reqData.Params.Encode() } if sbody, ok := reqData.ReqValue.(string); ok { body = []byte(sbody) } else if reqData.ReqValue != nil { body, err = json.Marshal(reqData.ReqValue) if err != nil { err = errors.Newf(err, "failed marshalling the request body") return } } headers := c.createHeaders(reqData.ReqHeaders, "text/plain") respBody, statusCode, err := c.sendRequest(method, url, bytes.NewReader(body), len(body), headers, reqData.ExpectedStatus) reqData.StatusCode = statusCode resp, err = ioutil.ReadAll(respBody) return }