Skip to content

Commit

Permalink
#92 ability to add fallback content-type value for response auto unm…
Browse files Browse the repository at this point in the history
…arshalling (#95)
  • Loading branch information
jeevatkm authored Sep 13, 2017
1 parent c6d4218 commit 1ce8688
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 25 deletions.
6 changes: 3 additions & 3 deletions middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,9 @@ func requestLogger(c *Client, r *Request) error {
return nil
}

//
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
// Response Middleware(s)
//
//___________________________________

func responseLogger(c *Client, res *Response) error {
if c.Debug {
Expand Down Expand Up @@ -239,7 +239,7 @@ func responseLogger(c *Client, res *Response) error {

func parseResponseBody(c *Client, res *Response) (err error) {
// Handles only JSON or XML content type
ct := res.Header().Get(hdrContentTypeKey)
ct := firstNonEmpty(res.Header().Get(hdrContentTypeKey), res.Request.fallbackContentType)
if IsJSONType(ct) || IsXMLType(ct) {
// Considered as Result
if res.StatusCode() > 199 && res.StatusCode() < 300 {
Expand Down
15 changes: 13 additions & 2 deletions request.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,16 @@ func (r *Request) SetDoNotParseResponse(parse bool) *Request {
return r
}

//
// ExpectContentType method allows to provide fallback `Content-Type` for automatic unmarshalling
// when `Content-Type` response header is unavailable.
func (r *Request) ExpectContentType(contentType string) *Request {
r.fallbackContentType = contentType
return r
}

//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
// HTTP verb method starts here
//
//___________________________________

// Get method does GET HTTP request. It's defined in section 4.3.1 of RFC7231.
func (r *Request) Get(url string) (*Response, error) {
Expand Down Expand Up @@ -448,6 +455,10 @@ func (r *Request) Execute(method, url string) (*Response, error) {
return resp, err
}

//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
// Unexported methods
//___________________________________

func (r *Request) fmtBodyString() (body string) {
body = "***** NO CONTENT *****"
if isPayloadSupported(r.Method, r.client.AllowGetMethodPayload) {
Expand Down
19 changes: 10 additions & 9 deletions request16.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,16 @@ type Request struct {
RawRequest *http.Request
SRV *SRVRecord

client *Client
bodyBuf *bytes.Buffer
isMultiPart bool
isFormData bool
setContentLength bool
isSaveResponse bool
outputFile string
multipartFiles []*File
notParseResponse bool
client *Client
bodyBuf *bytes.Buffer
isMultiPart bool
isFormData bool
setContentLength bool
isSaveResponse bool
outputFile string
multipartFiles []*File
notParseResponse bool
fallbackContentType string
}

func (r *Request) addContextIfAvailable() {
Expand Down
21 changes: 11 additions & 10 deletions request17.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,17 @@ type Request struct {
RawRequest *http.Request
SRV *SRVRecord

client *Client
bodyBuf *bytes.Buffer
isMultiPart bool
isFormData bool
setContentLength bool
isSaveResponse bool
outputFile string
multipartFiles []*File
notParseResponse bool
ctx context.Context
client *Client
bodyBuf *bytes.Buffer
isMultiPart bool
isFormData bool
setContentLength bool
isSaveResponse bool
outputFile string
multipartFiles []*File
notParseResponse bool
ctx context.Context
fallbackContentType string
}

// SetContext method sets the context.Context for current Request. It allows
Expand Down
36 changes: 35 additions & 1 deletion resty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1111,7 +1111,6 @@ func TestContextInternal(t *testing.T) {

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

}

func TestSRV(t *testing.T) {
Expand Down Expand Up @@ -1193,6 +1192,28 @@ func TestRequestDoNotParseResponse(t *testing.T) {
SetDoNotParseResponse(false)
}

type noCtTest struct {
Response string `json:"response"`
}

func TestRequestExpectContentTypeTest(t *testing.T) {
ts := createGenServer(t)
defer ts.Close()

c := dc()
resp, err := c.R().
SetResult(noCtTest{}).
ExpectContentType("application/json").
Get(ts.URL + "/json-no-set")

assertError(t, err)
assertEqual(t, http.StatusOK, resp.StatusCode())
assertNotNil(t, resp.Result())
assertEqual(t, "json response no content type set", resp.Result().(*noCtTest).Response)

assertEqual(t, "", firstNonEmpty("", ""))
}

//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
// Testing Unexported methods
//___________________________________
Expand Down Expand Up @@ -1541,6 +1562,16 @@ func createGenServer(t *testing.T) *httptest.Server {
t.Logf("Method: %v", r.Method)
t.Logf("Path: %v", r.URL.Path)

if r.Method == MethodGet {
if r.URL.Path == "/json-no-set" {
// Set empty header value for testing, since Go server sets to
// text/plain; charset=utf-8
w.Header().Set(hdrContentTypeKey, "")
_, _ = w.Write([]byte(`{"response":"json response no content type set"}`))
}
return
}

if r.Method == MethodPut {
if r.URL.Path == "/plaintext" {
_, _ = w.Write([]byte("TestPut: plain text response"))
Expand All @@ -1551,17 +1582,20 @@ func createGenServer(t *testing.T) *httptest.Server {
w.Header().Set(hdrContentTypeKey, "application/xml")
_, _ = w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?><Response>XML response</Response>`))
}
return
}

if r.Method == MethodOptions && r.URL.Path == "/options" {
w.Header().Set("Access-Control-Allow-Origin", "localhost")
w.Header().Set("Access-Control-Allow-Methods", "PUT, PATCH")
w.Header().Set("Access-Control-Expose-Headers", "x-go-resty-id")
w.WriteHeader(http.StatusOK)
return
}

if r.Method == MethodPatch && r.URL.Path == "/patch" {
w.WriteHeader(http.StatusOK)
return
}
})

Expand Down
14 changes: 14 additions & 0 deletions util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) 2015-2017 Jeevanandam M ([email protected]), All rights reserved.
// resty source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.

package resty

func firstNonEmpty(v ...string) string {
for _, s := range v {
if !IsStringEmpty(s) {
return s
}
}
return ""
}

0 comments on commit 1ce8688

Please sign in to comment.