Skip to content

Commit

Permalink
Add EncodeJSONRequest
Browse files Browse the repository at this point in the history
  • Loading branch information
willfaught committed Jan 17, 2017
1 parent da91884 commit f3a31a9
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 0 deletions.
19 changes: 19 additions & 0 deletions transport/http/client.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package http

import (
"bytes"
"encoding/json"
"io/ioutil"
"net/http"
"net/url"

Expand Down Expand Up @@ -113,3 +116,19 @@ func (c Client) Endpoint() endpoint.Endpoint {
return response, nil
}
}

// EncodeJSONRequest is an EncodeRequestFunc that serializes the request as a
// JSON object to the Request body. Many JSON-over-HTTP services can use it as
// a sensible default. If the request implements Headerer, the provided headers
// will be applied to the request.
func EncodeJSONRequest(c context.Context, r *http.Request, request interface{}) error {
r.Header.Set("Content-Type", "application/json; charset=utf-8")
if headerer, ok := request.(Headerer); ok {
for k := range headerer.Headers() {
r.Header.Set(k, headerer.Headers().Get(k))
}
}
var b bytes.Buffer
r.Body = ioutil.NopCloser(&b)
return json.NewEncoder(&b).Encode(request)
}
69 changes: 69 additions & 0 deletions transport/http/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package http_test

import (
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
Expand Down Expand Up @@ -140,10 +141,78 @@ func TestHTTPClientBufferedStream(t *testing.T) {
}
}

func TestEncodeJSONRequest(t *testing.T) {
var header http.Header
var body string

server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
b, err := ioutil.ReadAll(r.Body)
if err != nil && err != io.EOF {
t.Fatal(err)
}
header = r.Header
body = string(b)
}))

defer server.Close()

serverURL, err := url.Parse(server.URL)

if err != nil {
t.Fatal(err)
}

client := httptransport.NewClient(
"POST",
serverURL,
httptransport.EncodeJSONRequest,
func(context.Context, *http.Response) (interface{}, error) { return nil, nil },
).Endpoint()

for _, test := range []struct {
value interface{}
body string
}{
{nil, "null\n"},
{12, "12\n"},
{1.2, "1.2\n"},
{true, "true\n"},
{"test", "\"test\"\n"},
{enhancedRequest{Foo: "foo"}, "{\"foo\":\"foo\"}\n"},
} {
if _, err := client(context.Background(), test.value); err != nil {
t.Error(err)
continue
}

if body != test.body {
t.Errorf("%v: actual %#v, expected %#v", test.value, body, test.body)
}
}

if _, err := client(context.Background(), enhancedRequest{Foo: "foo"}); err != nil {
t.Fatal(err)
}

if _, ok := header["X-Edward"]; !ok {
t.Fatalf("X-Edward value: actual %v, expected %v", nil, []string{"Snowden"})
}

if v := header.Get("X-Edward"); v != "Snowden" {
t.Errorf("X-Edward string: actual %v, expected %v", v, "Snowden")
}
}

func mustParse(s string) *url.URL {
u, err := url.Parse(s)
if err != nil {
panic(err)
}
return u
}

type enhancedRequest struct {
Foo string `json:"foo"`
}

func (e enhancedRequest) Headers() http.Header { return http.Header{"X-Edward": []string{"Snowden"}} }

0 comments on commit f3a31a9

Please sign in to comment.