Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Capture delay along with response #1154

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/handlers/v2/views.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type ModeArgumentsView struct {
Stateful bool `json:"stateful,omitempty"`
OverwriteDuplicate bool `json:"overwriteDuplicate,omitempty"`
CaptureOnMiss bool `json:"captureOnMiss,omitempty"`
CaptureDelay bool `json:"captureDelay,omitempty"`
}

type IsWebServerView struct {
Expand Down
12 changes: 7 additions & 5 deletions core/hoverfly_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"
"path/filepath"
"strings"
"time"

"github.com/SpectoLabs/hoverfly/core/errors"
v2 "github.com/SpectoLabs/hoverfly/core/handlers/v2"
Expand All @@ -19,19 +20,21 @@ import (
)

// DoRequest - performs request and returns response that should be returned to client and error
func (hf *Hoverfly) DoRequest(request *http.Request) (*http.Response, error) {
func (hf *Hoverfly) DoRequest(request *http.Request) (*http.Response, *time.Duration, error) {

// We can't have this set. And it only contains "/pkg/net/http/" anyway
request.RequestURI = ""

client, err := GetHttpClient(hf, request.Host)
if err != nil {
return nil, err
return nil, nil, err
}
start := time.Now()
resp, err := client.Do(request)
elapsed := time.Since(start)

if err != nil {
return nil, err
return nil, nil, err
}

resp.Header.Set("Hoverfly", "Was-Here")
Expand All @@ -40,8 +43,7 @@ func (hf *Hoverfly) DoRequest(request *http.Request) (*http.Response, error) {
resp.Header.Add("Hoverfly", "Forwarded")
}

return resp, nil

return resp, &elapsed, nil
}

// GetResponse returns stored response from cache
Expand Down
5 changes: 3 additions & 2 deletions core/hoverfly_funcs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ func Test_Hoverfly_DoRequest_DoesNotPanicWhenCannotMakeRequest(t *testing.T) {
request, err := http.NewRequest("GET", "w.specto.fake", ioutil.NopCloser(bytes.NewBuffer([]byte(""))))
Expect(err).To(BeNil())

response, err := unit.DoRequest(request)
response, time, err := unit.DoRequest(request)
Expect(response).To(BeNil())
Expect(time).To(BeNil())
Expect(err).ToNot(BeNil())
}

Expand All @@ -43,7 +44,7 @@ func Test_Hoverfly_DoRequest_FailedHTTP(t *testing.T) {
req, err := http.NewRequest("POST", "http://capture_body.com", body)
Expect(err).To(BeNil())

_, err = unit.DoRequest(req)
_, _, err = unit.DoRequest(req)
Expect(err).ToNot(BeNil())
}

Expand Down
1 change: 1 addition & 0 deletions core/hoverfly_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ func (hf *Hoverfly) SetModeWithArguments(modeView v2.ModeView) error {
Stateful: modeView.Arguments.Stateful,
OverwriteDuplicate: modeView.Arguments.OverwriteDuplicate,
CaptureOnMiss: modeView.Arguments.CaptureOnMiss,
CaptureDelay: modeView.Arguments.CaptureDelay,
}

hf.modeMap[hf.Cfg.GetMode()].SetArguments(modeArguments)
Expand Down
18 changes: 13 additions & 5 deletions core/modes/capture_mode.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"io/ioutil"
"net/http"
"time"

"github.com/SpectoLabs/hoverfly/core/models"
"github.com/SpectoLabs/hoverfly/core/util"
Expand All @@ -14,7 +15,7 @@ import (

type HoverflyCapture interface {
ApplyMiddleware(models.RequestResponsePair) (models.RequestResponsePair, error)
DoRequest(*http.Request) (*http.Response, error)
DoRequest(*http.Request) (*http.Response, *time.Duration, error)
Save(*models.RequestDetails, *models.ResponseDetails, *ModeArguments) error
}

Expand All @@ -30,6 +31,7 @@ func (this *CaptureMode) View() v2.ModeView {
Headers: this.Arguments.Headers,
Stateful: this.Arguments.Stateful,
OverwriteDuplicate: this.Arguments.OverwriteDuplicate,
CaptureDelay: this.Arguments.CaptureDelay,
},
}
}
Expand Down Expand Up @@ -59,18 +61,24 @@ func (this CaptureMode) Process(request *http.Request, details models.RequestDet
return ReturnErrorAndLog(request, err, &pair, "There was an error when preparing request for pass through", Capture)
}

response, err := this.Hoverfly.DoRequest(modifiedRequest)
response, duration, err := this.Hoverfly.DoRequest(modifiedRequest)
if err != nil {
return ReturnErrorAndLog(request, err, &pair, "There was an error when forwarding the request to the intended destination", Capture)
}

respBody, _ := util.GetResponseBody(response)
respHeaders := util.GetResponseHeaders(response)

delayInMs := 0
if this.Arguments.CaptureDelay {
delayInMs = int(duration.Milliseconds())
}

responseObj := &models.ResponseDetails{
Status: response.StatusCode,
Body: respBody,
Headers: respHeaders,
Status: response.StatusCode,
Body: respBody,
Headers: respHeaders,
FixedDelay: delayInMs,
}

if this.Arguments.Headers == nil {
Expand Down
8 changes: 5 additions & 3 deletions core/modes/capture_mode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io/ioutil"
"net/http"
"testing"
"time"

"github.com/SpectoLabs/hoverfly/core/models"
"github.com/SpectoLabs/hoverfly/core/modes"
Expand All @@ -25,10 +26,10 @@ func (this hoverflyCaptureStub) ApplyMiddleware(pair models.RequestResponsePair)
}

// DoRequest - Stub implementation of modes.HoverflyCapture interface
func (this hoverflyCaptureStub) DoRequest(request *http.Request) (*http.Response, error) {
func (this hoverflyCaptureStub) DoRequest(request *http.Request) (*http.Response, *time.Duration, error) {
response := &http.Response{}
if request.Host == "error.com" {
return nil, errors.New("Could not reach error.com")
return nil, nil, errors.New("Could not reach error.com")
}

response.StatusCode = 200
Expand All @@ -42,7 +43,8 @@ func (this hoverflyCaptureStub) DoRequest(request *http.Request) (*http.Response
response.Trailer.Set("X-Bin-Id", "xyz")
}

return response, nil
duration := 1 * time.Second
return response, &duration, nil
}

// Save - Stub implementation of modes.HoverflyCapture interface
Expand Down
6 changes: 3 additions & 3 deletions core/modes/diff_mode.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (

type HoverflyDiff interface {
GetResponse(models.RequestDetails) (*models.ResponseDetails, *errors.HoverflyError)
DoRequest(*http.Request) (*http.Response, error)
DoRequest(*http.Request) (*http.Response, *time.Duration, error)
AddDiff(requestView v2.SimpleRequestDefinitionView, diffReport v2.DiffReport)
}

Expand All @@ -44,7 +44,7 @@ func (this *DiffMode) SetArguments(arguments ModeArguments) {
this.Arguments = arguments
}

//TODO: We should only need one of these two parameters
// TODO: We should only need one of these two parameters
func (this *DiffMode) Process(request *http.Request, details models.RequestDetails) (ProcessResult, error) {
this.DiffReport = v2.DiffReport{Timestamp: time.Now().Format(time.RFC3339)}

Expand All @@ -60,7 +60,7 @@ func (this *DiffMode) Process(request *http.Request, details models.RequestDetai
return ReturnErrorAndLog(request, err, &actualPair, "There was an error when reconstructing the request.", Diff)
}

actualResponse, err := this.Hoverfly.DoRequest(modifiedRequest)
actualResponse, _, err := this.Hoverfly.DoRequest(modifiedRequest)
if err != nil {
return ReturnErrorAndLog(request, err, &actualPair, "There was an error when forwarding the request to the intended destination", Diff)
}
Expand Down
16 changes: 9 additions & 7 deletions core/modes/diff_mode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io/ioutil"
"net/http"
"testing"
"time"

"bytes"
"encoding/json"
Expand All @@ -17,40 +18,41 @@ import (

type hoverflyDiffStub struct{}

func (this hoverflyDiffStub) DoRequest(request *http.Request) (*http.Response, error) {
func (this hoverflyDiffStub) DoRequest(request *http.Request) (*http.Response, *time.Duration, error) {
duration := 1 * time.Second
switch request.Host {
case "error.com":
return nil, fmt.Errorf("Could not reach error.com")
return nil, nil, fmt.Errorf("Could not reach error.com")
case "positive-match-with-same-response.com":
return &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(bytes.NewBufferString("expected")),
Header: map[string][]string{"header": {"expected"}, "source": {"service"}},
}, nil
}, &duration, nil
case "positive-match-with-different-response.com":
return &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(bytes.NewBufferString("actual")),
Header: map[string][]string{"header": {"actual"}, "source": {"service"}},
}, nil
}, &duration, nil
case "negative-match.com":
return &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(bytes.NewBufferString("actual")),
Header: map[string][]string{"header": {"actual"}, "source": {"service"}},
}, nil
}, &duration, nil
case "positive-match-with-different-trailers.com":
return &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(bytes.NewBufferString("actual")),
Header: map[string][]string{"header": {"actual"}},
Trailer: map[string][]string{"trailer1": {"actual"}},
}, nil
}, &duration, nil
default:
return &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(bytes.NewBufferString("test")),
}, nil
}, &duration, nil
}
}

Expand Down
1 change: 1 addition & 0 deletions core/modes/modes.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type ModeArguments struct {
Stateful bool
OverwriteDuplicate bool
CaptureOnMiss bool
CaptureDelay bool
}

type ProcessResult struct {
Expand Down
5 changes: 3 additions & 2 deletions core/modes/modify_mode.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ package modes
import (
"io/ioutil"
"net/http"
"time"

"github.com/SpectoLabs/hoverfly/core/handlers/v2"
"github.com/SpectoLabs/hoverfly/core/models"
)

type HoverflyModify interface {
ApplyMiddleware(models.RequestResponsePair) (models.RequestResponsePair, error)
DoRequest(*http.Request) (*http.Response, error)
DoRequest(*http.Request) (*http.Response, *time.Duration, error)
}

type ModifyMode struct {
Expand All @@ -36,7 +37,7 @@ func (this ModifyMode) Process(request *http.Request, details models.RequestDeta
return ReturnErrorAndLog(request, err, &pair, "There was an error when rebuilding the modified http request", Modify)
}

resp, err := this.Hoverfly.DoRequest(modifiedRequest)
resp, _, err := this.Hoverfly.DoRequest(modifiedRequest)
if err != nil {
return ReturnErrorAndLog(request, err, &pair, "There was an error when forwarding the request to the intended destination", Modify)
}
Expand Down
8 changes: 5 additions & 3 deletions core/modes/modify_mode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io/ioutil"
"net/http"
"testing"
"time"

"github.com/SpectoLabs/hoverfly/core/models"
"github.com/SpectoLabs/hoverfly/core/modes"
Expand All @@ -14,18 +15,19 @@ import (

type hoverflyModifyStub struct{}

func (this hoverflyModifyStub) DoRequest(request *http.Request) (*http.Response, error) {
func (this hoverflyModifyStub) DoRequest(request *http.Request) (*http.Response, *time.Duration, error) {
response := &http.Response{}
if request.Host == "error.com" {
return nil, errors.New("Could not reach error.com")
return nil, nil, errors.New("Could not reach error.com")
}

request.Host = "modified.com"

response.StatusCode = 200
response.Body = ioutil.NopCloser(bytes.NewBufferString("test"))

return response, nil
duration := 1 * time.Second
return response, &duration, nil
}

func (this hoverflyModifyStub) ApplyMiddleware(pair models.RequestResponsePair) (models.RequestResponsePair, error) {
Expand Down
19 changes: 13 additions & 6 deletions core/modes/spy_mode.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package modes

import (
"net/http"
"time"

"github.com/SpectoLabs/hoverfly/core/errors"
v2 "github.com/SpectoLabs/hoverfly/core/handlers/v2"
Expand All @@ -15,7 +16,7 @@ import (
type HoverflySpy interface {
GetResponse(models.RequestDetails) (*models.ResponseDetails, *errors.HoverflyError)
ApplyMiddleware(models.RequestResponsePair) (models.RequestResponsePair, error)
DoRequest(*http.Request) (*http.Response, error)
DoRequest(*http.Request) (*http.Response, *time.Duration, error)
Save(*models.RequestDetails, *models.ResponseDetails, *ModeArguments) error
}

Expand All @@ -33,6 +34,7 @@ func (this *SpyMode) View() v2.ModeView {
Stateful: this.Arguments.Stateful,
Headers: this.Arguments.Headers,
OverwriteDuplicate: this.Arguments.OverwriteDuplicate,
CaptureDelay: this.Arguments.CaptureDelay,
},
}
}
Expand All @@ -50,6 +52,7 @@ func (this *SpyMode) SetArguments(arguments ModeArguments) {
Stateful: arguments.Stateful,
OverwriteDuplicate: arguments.OverwriteDuplicate,
CaptureOnMiss: arguments.CaptureOnMiss,
CaptureDelay: arguments.CaptureDelay,
}
}

Expand All @@ -67,17 +70,21 @@ func (this SpyMode) Process(request *http.Request, details models.RequestDetails
if err != nil {
return ReturnErrorAndLog(request, err, &pair, "There was an error when reconstructing the request.", Spy)
}
response, err := this.Hoverfly.DoRequest(modifiedRequest)
response, duration, err := this.Hoverfly.DoRequest(modifiedRequest)
if err == nil {

if this.Arguments.CaptureOnMiss {
respBody, _ := util.GetResponseBody(response)
respHeaders := util.GetResponseHeaders(response)

delayInMs := 0
if this.Arguments.CaptureDelay {
delayInMs = int(duration.Milliseconds())
}
responseObj := &models.ResponseDetails{
Status: response.StatusCode,
Body: respBody,
Headers: respHeaders,
Status: response.StatusCode,
Body: respBody,
Headers: respHeaders,
FixedDelay: delayInMs,
}
if this.Arguments.Headers == nil {
this.Arguments.Headers = []string{}
Expand Down
Loading
Loading