Skip to content

Commit

Permalink
#27 Added support for slice struct & map on SetBody
Browse files Browse the repository at this point in the history
  • Loading branch information
jeevatkm committed Apr 30, 2016
1 parent 94596ee commit 2a99289
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 8 deletions.
9 changes: 7 additions & 2 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -771,13 +771,18 @@ func IsStringEmpty(str string) bool {
// DetectContentType method is used to figure out `Request.Body` content type for request header
func DetectContentType(body interface{}) string {
contentType := plainTextType
switch kindOf(body) {
kind := kindOf(body)
switch kind {
case reflect.Struct, reflect.Map:
contentType = jsonContentType
case reflect.String:
contentType = plainTextType
default:
contentType = http.DetectContentType(body.([]byte))
if b, ok := body.([]byte); ok {
contentType = http.DetectContentType(b)
} else if kind == reflect.Slice {
contentType = jsonContentType
}
}

return contentType
Expand Down
11 changes: 6 additions & 5 deletions middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,14 +301,15 @@ func handleRequestBody(c *Client, r *Request) (err error) {
if reader, ok := r.Body.(io.Reader); ok {
r.bodyBuf = &bytes.Buffer{}
r.bodyBuf.ReadFrom(reader)
} else if IsJSONType(contentType) && (kind == reflect.Struct || kind == reflect.Map) {
} else if b, ok := r.Body.([]byte); ok {
bodyBytes = b
} else if s, ok := r.Body.(string); ok {
bodyBytes = []byte(s)
} else if IsJSONType(contentType) &&
(kind == reflect.Struct || kind == reflect.Map || kind == reflect.Slice) {
bodyBytes, err = json.Marshal(r.Body)
} else if IsXMLType(contentType) && (kind == reflect.Struct) {
bodyBytes, err = xml.Marshal(r.Body)
} else if b, ok := r.Body.(string); ok {
bodyBytes = []byte(b)
} else if b, ok := r.Body.([]byte); ok {
bodyBytes = b
}

if bodyBytes == nil && r.bodyBuf == nil {
Expand Down
140 changes: 139 additions & 1 deletion resty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func TestPostJSONBytesSuccess(t *testing.T) {

c := dc()
c.SetHeader(hdrContentTypeKey, jsonContentType).
SetHeaders(map[string]string{hdrUserAgentKey: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) go-resty v0.1", hdrAcceptKey: jsonContentType})
SetHeaders(map[string]string{hdrUserAgentKey: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) go-resty v0.7", hdrAcceptKey: jsonContentType})

resp, err := c.R().
SetBody([]byte(`{"username":"testuser", "password":"testpass"}`)).
Expand Down Expand Up @@ -1001,6 +1001,81 @@ func TestDetectContentTypeForPointer(t *testing.T) {
logResponse(t, resp)
}

type ExampleUser struct {
FirstName string `json:"frist_name"`
LastName string `json:"last_name"`
ZipCode string `json:"zip_code"`
}

func TestDetectContentTypeForPointerWithSlice(t *testing.T) {
ts := createPostServer(t)
defer ts.Close()

users := &[]ExampleUser{
ExampleUser{FirstName: "firstname1", LastName: "lastname1", ZipCode: "10001"},
ExampleUser{FirstName: "firstname2", LastName: "lastname3", ZipCode: "10002"},
ExampleUser{FirstName: "firstname3", LastName: "lastname3", ZipCode: "10003"},
}

resp, err := dclr().
SetBody(users).
Post(ts.URL + "/users")

assertError(t, err)
assertEqual(t, http.StatusAccepted, resp.StatusCode())

t.Logf("Result Success: %q", resp)

logResponse(t, resp)
}

func TestDetectContentTypeForPointerWithSliceMap(t *testing.T) {
ts := createPostServer(t)
defer ts.Close()

usersmap := map[string]interface{}{
"user1": ExampleUser{FirstName: "firstname1", LastName: "lastname1", ZipCode: "10001"},
"user2": &ExampleUser{FirstName: "firstname2", LastName: "lastname3", ZipCode: "10002"},
"user3": ExampleUser{FirstName: "firstname3", LastName: "lastname3", ZipCode: "10003"},
}

var users []map[string]interface{}
users = append(users, usersmap)

resp, err := dclr().
SetBody(&users).
Post(ts.URL + "/usersmap")

assertError(t, err)
assertEqual(t, http.StatusAccepted, resp.StatusCode())

t.Logf("Result Success: %q", resp)

logResponse(t, resp)
}

func TestDetectContentTypeForSlice(t *testing.T) {
ts := createPostServer(t)
defer ts.Close()

users := []ExampleUser{
ExampleUser{FirstName: "firstname1", LastName: "lastname1", ZipCode: "10001"},
ExampleUser{FirstName: "firstname2", LastName: "lastname3", ZipCode: "10002"},
ExampleUser{FirstName: "firstname3", LastName: "lastname3", ZipCode: "10003"},
}

resp, err := dclr().
SetBody(users).
Post(ts.URL + "/users")

assertError(t, err)
assertEqual(t, http.StatusAccepted, resp.StatusCode())

t.Logf("Result Success: %q", resp)

logResponse(t, resp)
}

func TestSetQueryStringTypical(t *testing.T) {
ts := createGetServer(t)
defer ts.Close()
Expand Down Expand Up @@ -1249,6 +1324,7 @@ func createPostServer(t *testing.T) *httptest.Server {
err := jd.Decode(user)
w.Header().Set(hdrContentTypeKey, jsonContentType)
if err != nil {
t.Logf("Error: %#v", err)
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{ "id": "bad_request", "message": "Unable to read user info" }`))
return
Expand All @@ -1274,6 +1350,7 @@ func createPostServer(t *testing.T) *httptest.Server {

w.Header().Set(hdrContentTypeKey, "application/xml")
if err != nil {
t.Logf("Error: %v", err)
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?>`))
w.Write([]byte(`<AuthError><Id>bad_request</Id><Message>Unable to read user info</Message></AuthError>`))
Expand All @@ -1296,6 +1373,67 @@ func createPostServer(t *testing.T) *httptest.Server {
return
}
}

if r.URL.Path == "/users" {
// JSON
if IsJSONType(r.Header.Get(hdrContentTypeKey)) {
var users []ExampleUser
jd := json.NewDecoder(r.Body)
err := jd.Decode(&users)
w.Header().Set(hdrContentTypeKey, jsonContentType)
if err != nil {
t.Logf("Error: %v", err)
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{ "id": "bad_request", "message": "Unable to read user info" }`))
return
}

// logic check, since we are excepting to reach 3 records
if len(users) != 3 {
t.Log("Error: Excepted count of 3 records")
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{ "id": "bad_request", "message": "Expected record count doesn't match" }`))
return
}

eu := users[2]
if eu.FirstName == "firstname3" && eu.ZipCode == "10003" {
w.WriteHeader(http.StatusAccepted)
w.Write([]byte(`{ "message": "Accepted" }`))
}

return
}
}

if r.URL.Path == "/usersmap" {
// JSON
if IsJSONType(r.Header.Get(hdrContentTypeKey)) {
var users []map[string]interface{}
jd := json.NewDecoder(r.Body)
err := jd.Decode(&users)
w.Header().Set(hdrContentTypeKey, jsonContentType)
if err != nil {
t.Logf("Error: %v", err)
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{ "id": "bad_request", "message": "Unable to read user info" }`))
return
}

// logic check, since we are excepting to reach 1 map records
if len(users) != 1 {
t.Log("Error: Excepted count of 1 map records")
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{ "id": "bad_request", "message": "Expected record count doesn't match" }`))
return
}

w.WriteHeader(http.StatusAccepted)
w.Write([]byte(`{ "message": "Accepted" }`))

return
}
}
}
})

Expand Down

0 comments on commit 2a99289

Please sign in to comment.