diff --git a/core/models/payload.go b/core/models/payload.go index c92af9b17..0e756def2 100644 --- a/core/models/payload.go +++ b/core/models/payload.go @@ -62,6 +62,7 @@ type RequestDetails struct { Query map[string][]string Body string Headers map[string][]string + rawQuery string } func NewRequestDetailsFromHttpRequest(req *http.Request) (RequestDetails, error) { @@ -93,6 +94,7 @@ func NewRequestDetailsFromHttpRequest(req *http.Request) (RequestDetails, error) Query: req.URL.Query(), Body: string(reqBody), Headers: req.Header, + rawQuery: req.URL.RawQuery, } for key, value := range requestDetails.Query { @@ -272,3 +274,7 @@ func (r *ResponseDetails) ConvertToResponseDetailsViewV4() v2.ResponseDetailsVie TransitionsState: r.TransitionsState, } } + +func (this RequestDetails) GetRawQuery() string { + return this.rawQuery +} diff --git a/core/modes/capture_mode.go b/core/modes/capture_mode.go index 014344026..665383872 100644 --- a/core/modes/capture_mode.go +++ b/core/modes/capture_mode.go @@ -52,7 +52,7 @@ func (this CaptureMode) Process(request *http.Request, details models.RequestDet return ReturnErrorAndLog(request, err, &pair, "There was an error when applying middleware to http request", Capture) } - modifiedRequest, err := ReconstructRequest(pair) + modifiedRequest, err := ReconstructRequestForPassThrough(pair) if err != nil { return ReturnErrorAndLog(request, err, &pair, "There was an error when applying middleware to http request", Capture) } diff --git a/core/modes/modes.go b/core/modes/modes.go index fddffb85c..1230bb9fa 100644 --- a/core/modes/modes.go +++ b/core/modes/modes.go @@ -71,6 +71,30 @@ func ReconstructRequest(pair models.RequestResponsePair) (*http.Request, error) return newRequest, nil } + +// ReconstructRequest replaces original request with details provided in Constructor Payload.RequestMatcher +func ReconstructRequestForPassThrough(pair models.RequestResponsePair) (*http.Request, error) { + if pair.Request.Destination == "" { + return nil, fmt.Errorf("failed to reconstruct request, destination not specified") + } + + newRequest, err := http.NewRequest( + pair.Request.Method, + fmt.Sprintf("%s://%s%s", pair.Request.Scheme, pair.Request.Destination, pair.Request.Path), + bytes.NewBuffer([]byte(pair.Request.Body))) + + if err != nil { + return nil, err + } + + newRequest.Method = pair.Request.Method + + newRequest.URL.RawQuery = pair.Request.GetRawQuery() + newRequest.Header = pair.Request.Headers + + return newRequest, nil +} + // ReconstructResponse changes original response with details provided in Constructor Payload.Response func ReconstructResponse(request *http.Request, pair models.RequestResponsePair) *http.Response { response := &http.Response{} diff --git a/functional-tests/core/ft_capture_mode_test.go b/functional-tests/core/ft_capture_mode_test.go index 21b76e014..f5e13fc34 100644 --- a/functional-tests/core/ft_capture_mode_test.go +++ b/functional-tests/core/ft_capture_mode_test.go @@ -284,6 +284,25 @@ var _ = Describe("When I run Hoverfly", func() { Expect(payload.RequestResponsePairs[0].RequestMatcher.Body.XmlMatch).To(Equal(util.StringToPointer(``))) }) + + It("Should pass through the original query", func() { + + var capturedRequestQuery string + + fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + capturedRequestQuery = r.URL.RawQuery + + w.Write([]byte("okay")) + })) + + defer fakeServer.Close() + + request, _ := sling.New().Post(fakeServer.URL + "?z=1&y=2&x=3").Request() + request.URL.RawQuery = "z=1&y=2&x=3" + hoverfly.ProxyRequest(request) + + Expect(capturedRequestQuery).To(Equal("z=1&y=2&x=3")) + }) }) }) }) diff --git a/functional-tests/functional_tests.go b/functional-tests/functional_tests.go index 159806e5f..8a4e56888 100644 --- a/functional-tests/functional_tests.go +++ b/functional-tests/functional_tests.go @@ -214,6 +214,11 @@ func (this Hoverfly) Proxy(r *sling.Sling) *http.Response { req, err := r.Request() Expect(err).To(BeNil()) + return this.ProxyRequest(req) +} + +func (this Hoverfly) ProxyRequest(req *http.Request) *http.Response { + proxy, _ := url.Parse(this.proxyUrl) proxyHttpClient := &http.Client{ Transport: &http.Transport{