Skip to content

Commit

Permalink
Remove bytecopy from GetBody
Browse files Browse the repository at this point in the history
req.Body is already populated, and this, even on the first call, will write the payload again.

Also adds a test guarding against the bug.

Closes #130

Signed-off-by: Bret Comnes <[email protected]>
  • Loading branch information
bcomnes committed Mar 1, 2019
1 parent 41e24cc commit 8399c68
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 3 deletions.
3 changes: 0 additions & 3 deletions client/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,6 @@ func (r *request) buildHTTP(mediaType, basePath string, producers map[string]run
return nil, err
}

if _, err := r.buf.Write(b.Bytes()); err != nil {
return nil, err
}
return ioutil.NopCloser(&b), nil
}

Expand Down
84 changes: 84 additions & 0 deletions client/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,14 @@ import (
"bytes"
"encoding/json"
"encoding/xml"
"errors"
"io"
"io/ioutil"
"mime"
"mime/multipart"
"net/http"
"net/http/httptest"
"net/url"
"os"
"path/filepath"
"strings"
Expand All @@ -29,6 +34,7 @@ import (
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

var testProducers = map[string]runtime.Producer{
Expand Down Expand Up @@ -509,3 +515,81 @@ func TestBuildRequest_BuildHTTP_EscapedPath(t *testing.T) {
assert.Equal(t, runtime.JSONMime, req.Header.Get(runtime.HeaderContentType))
}
}

type testReqFn func(*testing.T, *http.Request)

type testRoundTripper struct {
tr http.RoundTripper
testFn testReqFn
testHarness *testing.T
}

func (t *testRoundTripper) RoundTrip(req *http.Request) (resp *http.Response, err error) {
t.testFn(t.testHarness, req)
return t.tr.RoundTrip(req)
}

func TestGetBodyCallsBeforeRoundTrip(t *testing.T) {

server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.WriteHeader(http.StatusCreated)
_, err := rw.Write([]byte("test result"))
require.NoError(t, err)
}))
defer server.Close()
hu, _ := url.Parse(server.URL)

client := http.DefaultClient
transport := http.DefaultTransport

client.Transport = &testRoundTripper{
tr: transport,
testHarness: t,
testFn: func(t *testing.T, req *http.Request) {
// Read the body once before sending the request
body, err := req.GetBody()
require.NoError(t, err)
bodyContent, err := ioutil.ReadAll(io.Reader(body))
require.EqualValues(t, req.ContentLength, len(bodyContent))
require.NoError(t, err)
require.EqualValues(t, "\"test body\"\n", string(bodyContent))

// Read the body a second time before sending the request
body, err = req.GetBody()
require.NoError(t, err)
bodyContent, err = ioutil.ReadAll(io.Reader(body))
require.NoError(t, err)
require.EqualValues(t, req.ContentLength, len(bodyContent))
require.EqualValues(t, "\"test body\"\n", string(bodyContent))
},
}

rwrtr := runtime.ClientRequestWriterFunc(func(req runtime.ClientRequest, _ strfmt.Registry) error {
return req.SetBodyParam("test body")
})

operation := &runtime.ClientOperation{
ID: "getSites",
Method: "POST",
PathPattern: "/",
Params: rwrtr,
Client: client,
Reader: runtime.ClientResponseReaderFunc(func(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
if response.Code() == http.StatusCreated {
var result string
if err := consumer.Consume(response.Body(), &result); err != nil {
return nil, err
}
return result, nil
}
return nil, errors.New("Unexpected error code")
}),
}

openAPIClient := New(hu.Host, "/", []string{"http"})
res, err := openAPIClient.Submit(operation)

require.NoError(t, err)
actual := res.(string)
require.EqualValues(t, "test result", actual)
}

0 comments on commit 8399c68

Please sign in to comment.