mirror of
https://github.com/interviewstreet/go-jira.git
synced 2024-11-24 08:22:42 +02:00
Merge branch 'master' of https://github.com/andygrunwald/go-jira
# Conflicts: # issue.go
This commit is contained in:
commit
c75a2ca567
@ -71,6 +71,9 @@ func main() {
|
||||
|
||||
### Authenticate with session cookie
|
||||
|
||||
Some actions require an authenticated user.
|
||||
Here is an example with a session cookie authentification.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
@ -102,6 +105,8 @@ func main() {
|
||||
|
||||
### Call a not implemented API endpoint
|
||||
|
||||
Not all API endpoints of the JIRA API are implemented into *go-jira*.
|
||||
But you can call them anyway:
|
||||
Lets get all public projects of [Atlassian`s JIRA instance](https://jira.atlassian.com/).
|
||||
|
||||
```go
|
||||
|
@ -36,6 +36,10 @@ func TestAcquireSessionCookie_Fail(t *testing.T) {
|
||||
if res == true {
|
||||
t.Error("Expected error, but result was true")
|
||||
}
|
||||
|
||||
if testClient.Authentication.Authenticated() != false {
|
||||
t.Error("Expected false, but result was true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAcquireSessionCookie_Success(t *testing.T) {
|
||||
@ -65,4 +69,18 @@ func TestAcquireSessionCookie_Success(t *testing.T) {
|
||||
if res == false {
|
||||
t.Error("Expected result was true. Got false")
|
||||
}
|
||||
|
||||
if testClient.Authentication.Authenticated() != true {
|
||||
t.Error("Expected true, but result was false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthenticated_NotInit(t *testing.T) {
|
||||
// Skip setup() because we don't want a fully setup client
|
||||
testClient = new(Client)
|
||||
|
||||
// Test before we've attempted to authenticate
|
||||
if testClient.Authentication.Authenticated() != false {
|
||||
t.Error("Expected false, but result was true")
|
||||
}
|
||||
}
|
||||
|
22
errors.go
22
errors.go
@ -1,22 +0,0 @@
|
||||
package jira
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ErrorResponse reports one or more errors caused by an API request.
|
||||
type ErrorResponse struct {
|
||||
Response *http.Response // HTTP response that caused this error
|
||||
ErrorMessages []string `json:"errorMessages,omitempty"`
|
||||
Errors map[string]string `json:"errors,omitempty"`
|
||||
}
|
||||
|
||||
func (r *ErrorResponse) Error() string {
|
||||
if r.Response == nil {
|
||||
return fmt.Sprintf("%v %+v", r.ErrorMessages, r.Errors)
|
||||
}
|
||||
return fmt.Sprintf("%v %v: %d %v %+v",
|
||||
r.Response.Request.Method, r.Response.Request.URL,
|
||||
r.Response.StatusCode, r.ErrorMessages, r.Errors)
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
package jira
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestErrorResponse_Empty(t *testing.T) {
|
||||
u, _ := url.Parse("https://issues.apache.org/jira/browse/MESOS-5040")
|
||||
r := &http.Response{
|
||||
Request: &http.Request{
|
||||
Method: "POST",
|
||||
URL: u,
|
||||
},
|
||||
StatusCode: 200,
|
||||
}
|
||||
|
||||
mockData := []struct {
|
||||
Response ErrorResponse
|
||||
Expected string
|
||||
}{
|
||||
{
|
||||
Response: ErrorResponse{},
|
||||
Expected: "[] map[]",
|
||||
},
|
||||
{
|
||||
Response: ErrorResponse{
|
||||
ErrorMessages: []string{"foo", "bar"},
|
||||
},
|
||||
Expected: "[foo bar] map[]",
|
||||
},
|
||||
{
|
||||
Response: ErrorResponse{
|
||||
Errors: map[string]string{"Foo": "Bar"},
|
||||
},
|
||||
Expected: "[] map[Foo:Bar]",
|
||||
},
|
||||
{
|
||||
Response: ErrorResponse{
|
||||
ErrorMessages: []string{"foo", "bar"},
|
||||
Errors: map[string]string{"Foo": "Bar"},
|
||||
},
|
||||
Expected: "[foo bar] map[Foo:Bar]",
|
||||
},
|
||||
{
|
||||
Response: ErrorResponse{
|
||||
Response: r,
|
||||
},
|
||||
Expected: "POST https://issues.apache.org/jira/browse/MESOS-5040: 200 [] map[]",
|
||||
},
|
||||
{
|
||||
Response: ErrorResponse{
|
||||
Response: r,
|
||||
ErrorMessages: []string{"foo", "bar"},
|
||||
},
|
||||
Expected: "POST https://issues.apache.org/jira/browse/MESOS-5040: 200 [foo bar] map[]",
|
||||
},
|
||||
{
|
||||
Response: ErrorResponse{
|
||||
Response: r,
|
||||
Errors: map[string]string{"Foo": "Bar"},
|
||||
},
|
||||
Expected: "POST https://issues.apache.org/jira/browse/MESOS-5040: 200 [] map[Foo:Bar]",
|
||||
},
|
||||
{
|
||||
Response: ErrorResponse{
|
||||
Response: r,
|
||||
ErrorMessages: []string{"foo", "bar"},
|
||||
Errors: map[string]string{"Foo": "Bar"},
|
||||
},
|
||||
Expected: "POST https://issues.apache.org/jira/browse/MESOS-5040: 200 [foo bar] map[Foo:Bar]",
|
||||
},
|
||||
}
|
||||
|
||||
for _, data := range mockData {
|
||||
got := data.Response.Error()
|
||||
if got != data.Expected {
|
||||
t.Errorf("Response is different as expected. Expected \"%s\". Got \"%s\"", data.Expected, got)
|
||||
}
|
||||
}
|
||||
}
|
94
issue.go
94
issue.go
@ -1,7 +1,10 @@
|
||||
package jira
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@ -26,6 +29,19 @@ type Issue struct {
|
||||
Fields *IssueFields `json:"fields,omitempty"`
|
||||
}
|
||||
|
||||
// Attachment represents a JIRA attachment
|
||||
type Attachment struct {
|
||||
Self string `json:"self,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Filename string `json:"filename,omitempty"`
|
||||
Author *Assignee `json:"author,omitempty"`
|
||||
Created string `json:"created,omitempty"`
|
||||
Size int `json:"size,omitempty"`
|
||||
MimeType string `json:"mimeType,omitempty"`
|
||||
Content string `json:"content,omitempty"`
|
||||
Thumbnail string `json:"thumbnail,omitempty"`
|
||||
}
|
||||
|
||||
// IssueFields represents single fields of a JIRA issue.
|
||||
// Every JIRA issue has several fields attached.
|
||||
type IssueFields struct {
|
||||
@ -38,7 +54,6 @@ type IssueFields struct {
|
||||
// * "aggregatetimeoriginalestimate": null,
|
||||
// * "timeoriginalestimate": null,
|
||||
// * "timetracking": {},
|
||||
// * "attachment": [],
|
||||
// * "aggregatetimeestimate": null,
|
||||
// * "environment": null,
|
||||
// * "duedate": null,
|
||||
@ -65,6 +80,7 @@ type IssueFields struct {
|
||||
FixVersions []*FixVersion `json:"fixVersions,omitempty"`
|
||||
Labels []string `json:"labels,omitempty"`
|
||||
Subtasks []*Subtasks `json:"subtasks,omitempty"`
|
||||
Attachments []*Attachment `json:"attachment,omitempty"`
|
||||
}
|
||||
|
||||
// IssueType represents a type of a JIRA issue.
|
||||
@ -267,14 +283,14 @@ type IssueLinkType struct {
|
||||
|
||||
// Comment represents a comment by a person to an issue in JIRA.
|
||||
type Comment struct {
|
||||
Self string `json:"self"`
|
||||
Name string `json:"name"`
|
||||
Author Assignee `json:"author"`
|
||||
Body string `json:"body"`
|
||||
UpdateAuthor Assignee `json:"updateAuthor"`
|
||||
Updated string `json:"updated"`
|
||||
Created string `json:"created"`
|
||||
Visibility CommentVisibility `json:"visibility"`
|
||||
Self string `json:"self,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Author Assignee `json:"author,omitempty"`
|
||||
Body string `json:"body,omitempty"`
|
||||
UpdateAuthor Assignee `json:"updateAuthor,omitempty"`
|
||||
Updated string `json:"updated,omitempty"`
|
||||
Created string `json:"created,omitempty"`
|
||||
Visibility CommentVisibility `json:"visibility,omitempty"`
|
||||
}
|
||||
|
||||
// FixVersion represents a software release in which an issue is fixed.
|
||||
@ -292,8 +308,8 @@ type FixVersion struct {
|
||||
// CommentVisibility represents he visibility of a comment.
|
||||
// E.g. Type could be "role" and Value "Administrators"
|
||||
type CommentVisibility struct {
|
||||
Type string `json:"type"`
|
||||
Value string `json:"value"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Value string `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
// Get returns a full representation of the issue for the given issue key.
|
||||
@ -318,6 +334,62 @@ func (s *IssueService) Get(issueID string) (*Issue, *http.Response, error) {
|
||||
return issue, resp, nil
|
||||
}
|
||||
|
||||
// DownloadAttachment returns a http.Response of an attachment for a given attachmentID.
|
||||
// The attachment is in the http.Response.Body of the response.
|
||||
// This is an io.ReadCloser.
|
||||
// The caller should close the resp.Body.
|
||||
func (s *IssueService) DownloadAttachment(attachmentID string) (*http.Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("secure/attachment/%s/", attachmentID)
|
||||
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, nil)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// PostAttachment uploads r (io.Reader) as an attachment to a given attachmentID
|
||||
func (s *IssueService) PostAttachment(attachmentID string, r io.Reader, attachmentName string) (*[]Attachment, *http.Response, error) {
|
||||
apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/attachments", attachmentID)
|
||||
|
||||
b := new(bytes.Buffer)
|
||||
writer := multipart.NewWriter(b)
|
||||
|
||||
fw, err := writer.CreateFormFile("file", attachmentName)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if r != nil {
|
||||
// Copy the file
|
||||
if _, err = io.Copy(fw, r); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
writer.Close()
|
||||
|
||||
req, err := s.client.NewMultiPartRequest("POST", apiEndpoint, b)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
// PostAttachment response returns a JSON array (as multiple attachments can be posted)
|
||||
attachment := new([]Attachment)
|
||||
resp, err := s.client.Do(req, attachment)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
return attachment, resp, nil
|
||||
}
|
||||
|
||||
// Create creates an issue or a sub-task from a JSON representation.
|
||||
// Creating a sub-task is similar to creating a regular issue, with two important differences:
|
||||
// The issueType field must correspond to a sub-task issue type and you must provide a parent field in the issue create request containing the id or key of the parent issue.
|
||||
|
170
issue_test.go
170
issue_test.go
@ -2,8 +2,10 @@ package jira
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -135,6 +137,174 @@ func TestIssueFields(t *testing.T) {
|
||||
if !reflect.DeepEqual(issue.Fields.Labels, []string{"test"}) {
|
||||
t.Error("Expected labels for the returned issue")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Error given: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssueDownloadAttachment(t *testing.T) {
|
||||
var testAttachment = "Here is an attachment"
|
||||
|
||||
setup()
|
||||
defer teardown()
|
||||
testMux.HandleFunc("/secure/attachment/", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
testRequestURL(t, r, "/secure/attachment/10000/")
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(testAttachment))
|
||||
})
|
||||
|
||||
resp, err := testClient.Issue.DownloadAttachment("10000")
|
||||
if resp == nil {
|
||||
t.Error("Expected response. Response is nil")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
attachment, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Error("Expected attachment text", err)
|
||||
}
|
||||
if string(attachment) != testAttachment {
|
||||
t.Errorf("Expecting an attachment: %s", string(attachment))
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
t.Errorf("Expected Status code 200. Given %d", resp.StatusCode)
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("Error given: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssueDownloadAttachment_BadStatus(t *testing.T) {
|
||||
|
||||
setup()
|
||||
defer teardown()
|
||||
testMux.HandleFunc("/secure/attachment/", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "GET")
|
||||
testRequestURL(t, r, "/secure/attachment/10000/")
|
||||
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
})
|
||||
|
||||
resp, err := testClient.Issue.DownloadAttachment("10000")
|
||||
if resp == nil {
|
||||
t.Error("Expected response. Response is nil")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusForbidden {
|
||||
t.Errorf("Expected Status code %d. Given %d", http.StatusForbidden, resp.StatusCode)
|
||||
}
|
||||
if err == nil {
|
||||
t.Errorf("Error expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssuePostAttachment(t *testing.T) {
|
||||
var testAttachment = "Here is an attachment"
|
||||
|
||||
setup()
|
||||
defer teardown()
|
||||
testMux.HandleFunc("/rest/api/2/issue/10000/attachments", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "POST")
|
||||
testRequestURL(t, r, "/rest/api/2/issue/10000/attachments")
|
||||
status := http.StatusOK
|
||||
|
||||
file, _, err := r.FormFile("file")
|
||||
if err != nil {
|
||||
status = http.StatusNotAcceptable
|
||||
}
|
||||
if file == nil {
|
||||
status = http.StatusNoContent
|
||||
} else {
|
||||
|
||||
// Read the file into memory
|
||||
data, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
status = http.StatusInternalServerError
|
||||
}
|
||||
if string(data) != testAttachment {
|
||||
status = http.StatusNotAcceptable
|
||||
}
|
||||
|
||||
w.WriteHeader(status)
|
||||
fmt.Fprint(w, `[{"self":"http://jira/jira/rest/api/2/attachment/228924","id":"228924","filename":"example.jpg","author":{"self":"http://jira/jira/rest/api/2/user?username=test","name":"test","emailAddress":"test@test.com","avatarUrls":{"16x16":"http://jira/jira/secure/useravatar?size=small&avatarId=10082","48x48":"http://jira/jira/secure/useravatar?avatarId=10082"},"displayName":"Tester","active":true},"created":"2016-05-24T00:25:17.000-0700","size":32280,"mimeType":"image/jpeg","content":"http://jira/jira/secure/attachment/228924/example.jpg","thumbnail":"http://jira/jira/secure/thumbnail/228924/_thumb_228924.png"}]`)
|
||||
file.Close()
|
||||
}
|
||||
})
|
||||
|
||||
reader := strings.NewReader(testAttachment)
|
||||
|
||||
issue, resp, err := testClient.Issue.PostAttachment("10000", reader, "attachment")
|
||||
|
||||
if issue == nil {
|
||||
t.Error("Expected response. Response is nil")
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
t.Errorf("Expected Status code 200. Given %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Error given: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssuePostAttachment_NoResponse(t *testing.T) {
|
||||
var testAttachment = "Here is an attachment"
|
||||
|
||||
setup()
|
||||
defer teardown()
|
||||
testMux.HandleFunc("/rest/api/2/issue/10000/attachments", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "POST")
|
||||
testRequestURL(t, r, "/rest/api/2/issue/10000/attachments")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
})
|
||||
reader := strings.NewReader(testAttachment)
|
||||
|
||||
_, _, err := testClient.Issue.PostAttachment("10000", reader, "attachment")
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("Error expected: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssuePostAttachment_NoFilename(t *testing.T) {
|
||||
var testAttachment = "Here is an attachment"
|
||||
|
||||
setup()
|
||||
defer teardown()
|
||||
testMux.HandleFunc("/rest/api/2/issue/10000/attachments", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "POST")
|
||||
testRequestURL(t, r, "/rest/api/2/issue/10000/attachments")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprint(w, `[{"self":"http://jira/jira/rest/api/2/attachment/228924","id":"228924","filename":"example.jpg","author":{"self":"http://jira/jira/rest/api/2/user?username=test","name":"test","emailAddress":"test@test.com","avatarUrls":{"16x16":"http://jira/jira/secure/useravatar?size=small&avatarId=10082","48x48":"http://jira/jira/secure/useravatar?avatarId=10082"},"displayName":"Tester","active":true},"created":"2016-05-24T00:25:17.000-0700","size":32280,"mimeType":"image/jpeg","content":"http://jira/jira/secure/attachment/228924/example.jpg","thumbnail":"http://jira/jira/secure/thumbnail/228924/_thumb_228924.png"}]`)
|
||||
})
|
||||
reader := strings.NewReader(testAttachment)
|
||||
|
||||
_, _, err := testClient.Issue.PostAttachment("10000", reader, "")
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Error expected: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssuePostAttachment_NoAttachment(t *testing.T) {
|
||||
|
||||
setup()
|
||||
defer teardown()
|
||||
testMux.HandleFunc("/rest/api/2/issue/10000/attachments", func(w http.ResponseWriter, r *http.Request) {
|
||||
testMethod(t, r, "POST")
|
||||
testRequestURL(t, r, "/rest/api/2/issue/10000/attachments")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprint(w, `[{"self":"http://jira/jira/rest/api/2/attachment/228924","id":"228924","filename":"example.jpg","author":{"self":"http://jira/jira/rest/api/2/user?username=test","name":"test","emailAddress":"test@test.com","avatarUrls":{"16x16":"http://jira/jira/secure/useravatar?size=small&avatarId=10082","48x48":"http://jira/jira/secure/useravatar?avatarId=10082"},"displayName":"Tester","active":true},"created":"2016-05-24T00:25:17.000-0700","size":32280,"mimeType":"image/jpeg","content":"http://jira/jira/secure/attachment/228924/example.jpg","thumbnail":"http://jira/jira/secure/thumbnail/228924/_thumb_228924.png"}]`)
|
||||
})
|
||||
|
||||
_, _, err := testClient.Issue.PostAttachment("10000", nil, "attachment")
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Error given: %s", err)
|
||||
}
|
||||
|
41
jira.go
41
jira.go
@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
@ -92,6 +91,34 @@ func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Requ
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// NewMultiPartRequest creates an API request including a multi-part file.
|
||||
// A relative URL can be provided in urlStr, in which case it is resolved relative to the baseURL of the Client.
|
||||
// Relative URLs should always be specified without a preceding slash.
|
||||
// If specified, the value pointed to by buf is a multipart form.
|
||||
func (c *Client) NewMultiPartRequest(method, urlStr string, buf *bytes.Buffer) (*http.Request, error) {
|
||||
rel, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u := c.baseURL.ResolveReference(rel)
|
||||
|
||||
req, err := http.NewRequest(method, u.String(), buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set required headers
|
||||
req.Header.Set("X-Atlassian-Token", "nocheck")
|
||||
|
||||
// Set session cookie if there is one
|
||||
if c.Authentication.Authenticated() {
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", c.session.Session.Name, c.session.Session.Value))
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// Do sends an API request and returns the API response.
|
||||
// The API response is JSON decoded and stored in the value pointed to by v, or returned as an error if an API error has occurred.
|
||||
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
|
||||
@ -118,17 +145,13 @@ func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
|
||||
|
||||
// CheckResponse checks the API response for errors, and returns them if present.
|
||||
// A response is considered an error if it has a status code outside the 200 range.
|
||||
// API error responses are expected to have either no response body, or a JSON response body that maps to ErrorResponse.
|
||||
// Any other response body will be silently ignored.
|
||||
// The caller is responsible to analyze the response body.
|
||||
// The body can contain JSON (if the error is intended) or xml (sometimes JIRA just failes).
|
||||
func CheckResponse(r *http.Response) error {
|
||||
if c := r.StatusCode; 200 <= c && c <= 299 {
|
||||
return nil
|
||||
}
|
||||
|
||||
errorResponse := &ErrorResponse{Response: r}
|
||||
data, err := ioutil.ReadAll(r.Body)
|
||||
if err == nil && data != nil {
|
||||
json.Unmarshal(data, errorResponse)
|
||||
}
|
||||
return errorResponse
|
||||
err := fmt.Errorf("Request failed. Please analyze the request body for more details. Status code: %d", r.StatusCode)
|
||||
return err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user