Skip to content

Commit fb2d20e

Browse files
authored
Merge pull request #8 from fastbill/response-headers
Add possibility to retrieve response headers
2 parents 34acce2 + 667a70e commit fb2d20e

File tree

3 files changed

+68
-4
lines changed

3 files changed

+68
-4
lines changed

README.md

+20-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,26 @@ err := request.Do(params, result)
3737
```
3838
All parameters besides the `URL` and the `Method` are optional and can be omitted.
3939

40-
If you want to retrieve the response body as a string, e.g. for debugging or testing purposes, you can use `DoWithStringResponse` instead.
40+
### Accessing the response headers
41+
If you need access to the headers of the http response, you can initialize a header map and pass it as a third argument to `Do`.
42+
It will then be populated with the response headers that the server returns.
43+
44+
```go
45+
responseHeaders := http.Header{}
46+
err := request.Do(params, result, responseHeaders)
47+
```
48+
49+
### Using a custom http client
50+
If you want to supply a custom http client to use for the request, you can use `DoWithCustomClient`.
51+
The client needs to be of type `*http.Client`.
52+
53+
```go
54+
err := request.DoWithCustomClient(params, result)
55+
```
56+
57+
### Retrieving the response as a string
58+
If you want to retrieve the response body as a string, e.g. for debugging or testing purposes, you can use `DoWithStringResponse`.
59+
4160
```go
4261
result, err := request.DoWithStringResponse(params)
4362
```

request.go

+29-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package request
33
import (
44
"bytes"
55
"encoding/json"
6+
"errors"
67
"fmt"
78
"io"
89
"io/ioutil"
@@ -50,9 +51,10 @@ type Params struct {
5051
ExpectedResponseCode int
5152
}
5253

53-
// Do executes the request as specified in the request params
54-
// The response body will be parsed into the provided struct
55-
func Do(params Params, responseBody interface{}) (returnErr error) {
54+
// Do executes the request as specified in the request params.
55+
// The response body will be parsed into the provided struct.
56+
// Optionally, the headers will be copied if a header map was provided.
57+
func Do(params Params, responseBody interface{}, responseHeaderArg ...http.Header) (returnErr error) {
5658
req, err := createRequest(params)
5759
if err != nil {
5860
return fmt.Errorf("failed to create request: %w", err)
@@ -75,6 +77,11 @@ func Do(params Params, responseBody interface{}) (returnErr error) {
7577
return err
7678
}
7779

80+
err = populateResponseHeader(res, responseHeaderArg)
81+
if err != nil {
82+
return err
83+
}
84+
7885
if responseBody == nil {
7986
return nil
8087
}
@@ -117,6 +124,8 @@ func DoWithStringResponse(params Params) (result string, returnErr error) {
117124

118125
// DoWithCustomClient is the same as Do but will make the request using the
119126
// supplied http.Client instead of the cachedClient.
127+
// TODO client should become the first parameter in the next major update
128+
// so we can add the response headers at the end. They are currently not supported.
120129
func DoWithCustomClient(params Params, responseBody interface{}, client *http.Client) (returnErr error) {
121130
req, err := createRequest(params)
122131
if err != nil {
@@ -244,3 +253,20 @@ func checkResponseCode(res *http.Response, expectedResponseCode int) error {
244253
func isSuccessCode(statusCode int) bool {
245254
return 200 <= statusCode && statusCode <= 299
246255
}
256+
257+
func populateResponseHeader(res *http.Response, responseHeaderArg []http.Header) error {
258+
if len(responseHeaderArg) == 0 { // go-staticcheck says no need to check for nil separately.
259+
return nil
260+
}
261+
262+
if len(responseHeaderArg) > 1 {
263+
return errors.New("too many arguments supplied")
264+
}
265+
266+
responseHeader := responseHeaderArg[0]
267+
for key, value := range res.Header {
268+
responseHeader[key] = value
269+
}
270+
271+
return nil
272+
}

request_test.go

+19
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,25 @@ func TestDoSuccessful(t *testing.T) {
8585
assert.Equal(t, "someValueOut", result.ResponseValue)
8686
})
8787

88+
t.Run("with response headers", func(t *testing.T) {
89+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
90+
w.Header().Set("SomeHeader1", "SomeHeaderValue1")
91+
w.Header().Add("SomeHeader2", "SomeHeaderValue2")
92+
}))
93+
defer ts.Close()
94+
95+
params := Params{
96+
URL: ts.URL,
97+
}
98+
99+
responseHeaders := http.Header{}
100+
err := Do(params, nil, responseHeaders)
101+
assert.NoError(t, err)
102+
assert.Len(t, responseHeaders, 4) // 2 custom headers + ContentLength + Date
103+
assert.Equal(t, "SomeHeaderValue1", responseHeaders.Get("SomeHeader1"))
104+
assert.Equal(t, "SomeHeaderValue2", responseHeaders.Get("SomeHeader2"))
105+
})
106+
88107
t.Run("map as request and response", func(t *testing.T) {
89108
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
90109
body, _ := ioutil.ReadAll(r.Body)

0 commit comments

Comments
 (0)