Skip to content

Commit

Permalink
start adding post actions in for response
Browse files Browse the repository at this point in the history
  • Loading branch information
Kostas Petrakis authored and petkostas committed Jan 26, 2023
1 parent f1ecaf2 commit ce50a7d
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 13 deletions.
2 changes: 1 addition & 1 deletion core/handlers/v2/simulation_views_v5.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ type ResponseDetailsViewV5 struct {
BodyFile string `json:"bodyFile,omitempty"`
EncodedBody bool `json:"encodedBody"`
Headers map[string][]string `json:"headers,omitempty"`
PostActionHooks []interface{} `json:"postActionHooks"`
PostActionHooks []interface{} `json:"postActionHooks,omitempty"`
Templated bool `json:"templated"`
TransitionsState map[string]string `json:"transitionsState,omitempty"`
RemovesState []string `json:"removesState,omitempty"`
Expand Down
20 changes: 19 additions & 1 deletion core/handlers/v2/simulation_views_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,19 +127,37 @@ var postActionHooks = map[string]interface{}{
"method": map[string]interface{}{
"type": "string",
},
"destination": map[string]interface{}{
"type": "string",
},
"scheme": map[string]interface{}{
"type": "string",
"enum": []string{
"http",
"https",
},
},
"destination": map[string]interface{}{
"path": map[string]interface{}{
"type": "string",
},
"query": map[string]interface{}{
"type": "object",
"additionalProperties": map[string]interface{}{
"type": "array",
"items": map[string]interface{}{
"type": "string",
},
},
},
"headers": map[string]interface{}{
"$ref": "#/definitions/headers",
},
"body": map[string]interface{}{
"type": "string",
},
"encodedBody": map[string]interface{}{
"type": "boolean",
},
},
},
},
Expand Down
35 changes: 28 additions & 7 deletions core/hoverfly_funcs.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package hoverfly

import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
Expand Down Expand Up @@ -287,13 +288,6 @@ func (hf *Hoverfly) applyHeadersTemplating(requestDetails *models.RequestDetails
return headers, nil
}

// Triggers the related webhooks
func (hf *Hoverfly) executePostHooks(postActionHooks models.PostActionHooks) {
for _, postActionHook := range postActionHooks {
postActionHook.Execute()
}
}

// save gets request fingerprint, extracts request body, status code and headers, then saves it to cache
func (hf *Hoverfly) Save(request *models.RequestDetails, response *models.ResponseDetails, modeArgs *modes.ModeArguments) error {
body := []models.RequestFieldMatchers{
Expand Down Expand Up @@ -438,3 +432,30 @@ func (hf *Hoverfly) ApplyMiddleware(pair models.RequestResponsePair) (models.Req

return pair, nil
}

func (hf *Hoverfly) ApplyPostHooks(pair models.RequestResponsePair) (models.RequestResponsePair, error) {
if pair.Response.PostActionHooks != nil {
log.Debug("Post action hooks detected")
for _, postActionHook := range pair.Response.PostActionHooks {
postActionHookStruct := &models.PostActionHook{}
jsonBytes, err := json.Marshal(postActionHook)
if err != nil {
log.Error("Unable to convert post action hook to json")
continue
}

err = json.Unmarshal(jsonBytes, postActionHookStruct)
if err != nil {
log.Error("Unable to unmarshal json post action hook into struct")
continue
}
// For now response is not needed, see what else we could need from it.
_, err = postActionHookStruct.Execute()
if err != nil {
return pair, err
}
log.Debug("Executed Post action hook")
}
}
return pair, nil
}
24 changes: 22 additions & 2 deletions core/models/post_action_webhooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"bytes"
"fmt"
"net/http"

log "github.com/sirupsen/logrus"
)

type PostActionHook struct {
Expand All @@ -19,16 +21,34 @@ type ActionHookParameters struct {
Query map[string]interface{} `json:"query"`
Headers map[string][]string `json:"headers"`
Body string `json:"body"`
EncodedBody bool `json:"encodedBody"`
}

type PostActionHooks []PostActionHook

func (postActionHook *PostActionHook) Execute() (*http.Request, error) {
func (postActionHook *PostActionHook) Execute() (*http.Response, error) {
bodyBytes := []byte(postActionHook.Parameters.Body)
url := fmt.Sprintf("%s://%s%s", postActionHook.Parameters.Scheme, postActionHook.Parameters.Destination, postActionHook.Parameters.Path)
req, err := http.NewRequest(postActionHook.Parameters.Method, url, bytes.NewBuffer(bodyBytes))
if err != nil {
log.WithFields(log.Fields{
"destination": url,
"method": postActionHook.Parameters.Method,
"postHookName": postActionHook.Name,
"scheme": postActionHook.Parameters.Scheme,
}).Error("Failed to create request for post action hook")
return nil, err
}
res, err := http.DefaultClient.Do(req)
if err != nil {
log.WithFields(log.Fields{
"destination": url,
"method": postActionHook.Parameters.Method,
"postHookName": postActionHook.Name,
"scheme": postActionHook.Parameters.Scheme,
}).Error("Failed to send request for post action hook")
return nil, err
}
return req, nil
log.Debug("Successfully attempted request for post action hook")
return res, nil
}
6 changes: 6 additions & 0 deletions core/modes/simulate_mode.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
type HoverflySimulate interface {
GetResponse(models.RequestDetails) (*models.ResponseDetails, *errors.HoverflyError)
ApplyMiddleware(models.RequestResponsePair) (models.RequestResponsePair, error)
ApplyPostHooks(models.RequestResponsePair) (models.RequestResponsePair, error)
}

type SimulateMode struct {
Expand Down Expand Up @@ -54,6 +55,11 @@ func (this SimulateMode) Process(request *http.Request, details models.RequestDe
return ReturnErrorAndLog(request, err, &pair, "There was an error when executing middleware", Simulate)
}

pair, err = this.Hoverfly.ApplyPostHooks(pair)
if err != nil {
return ReturnErrorAndLog(request, err, &pair, "There was an error when executing the post hooks", Spy)
}

return newProcessResult(
ReconstructResponse(request, pair),
pair.Response.FixedDelay,
Expand Down
28 changes: 28 additions & 0 deletions core/modes/simulate_mode_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package modes_test

import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
Expand Down Expand Up @@ -33,6 +34,33 @@ func (this hoverflySimulateStub) ApplyMiddleware(pair models.RequestResponsePair
return pair, nil
}

func (this hoverflySimulateStub) ApplyPostHooks(pair models.RequestResponsePair) (models.RequestResponsePair, error) {
if pair.Response.PostActionHooks != nil {
for _, postActionHook := range pair.Response.PostActionHooks {
hookMap, ok := postActionHook.(map[string]interface{})
if !ok {
fmt.Println("Unable to convert post action hook to map[string]interface{}")
continue
}

postActionHookStruct := &models.PostActionHook{}
jsonBytes, err := json.Marshal(hookMap)
if err != nil {
fmt.Println("Unable to convert post action hook to json")
continue
}

err = json.Unmarshal(jsonBytes, postActionHookStruct)
if err != nil {
fmt.Println("Unable to unmarshal json into struct")
continue
}
postActionHookStruct.Execute()
}
}
return pair, nil
}

func Test_SimulateMode_WhenGivenAMatchingRequestItReturnsTheCorrectResponse(t *testing.T) {
RegisterTestingT(t)

Expand Down
9 changes: 7 additions & 2 deletions core/modes/spy_mode.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ import (
"net/http"

"github.com/SpectoLabs/hoverfly/core/errors"
v2 "github.com/SpectoLabs/hoverfly/core/handlers/v2"

log "github.com/sirupsen/logrus"

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

type HoverflySpy interface {
GetResponse(models.RequestDetails) (*models.ResponseDetails, *errors.HoverflyError)
ApplyMiddleware(models.RequestResponsePair) (models.RequestResponsePair, error)
ApplyPostHooks(models.RequestResponsePair) (models.RequestResponsePair, error)
DoRequest(*http.Request) (*http.Response, error)
}

Expand All @@ -39,7 +40,7 @@ func (this *SpyMode) SetArguments(arguments ModeArguments) {
}
}

//TODO: We should only need one of these two parameters
// TODO: We should only need one of these two parameters
func (this SpyMode) Process(request *http.Request, details models.RequestDetails) (ProcessResult, error) {
pair := models.RequestResponsePair{
Request: details,
Expand Down Expand Up @@ -68,6 +69,10 @@ func (this SpyMode) Process(request *http.Request, details models.RequestDetails
if err != nil {
return ReturnErrorAndLog(request, err, &pair, "There was an error when executing middleware", Spy)
}
pair, err = this.Hoverfly.ApplyPostHooks(pair)
if err != nil {
return ReturnErrorAndLog(request, err, &pair, "There was an error when executing the post hooks", Spy)
}

return newProcessResult(
ReconstructResponse(request, pair),
Expand Down
28 changes: 28 additions & 0 deletions core/modes/spy_mode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package modes_test

import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
Expand Down Expand Up @@ -47,6 +48,33 @@ func (this hoverflySpyStub) ApplyMiddleware(pair models.RequestResponsePair) (mo
return pair, nil
}

func (hf hoverflySpyStub) ApplyPostHooks(pair models.RequestResponsePair) (models.RequestResponsePair, error) {
if pair.Response.PostActionHooks != nil {
for _, postActionHook := range pair.Response.PostActionHooks {
hookMap, ok := postActionHook.(map[string]interface{})
if !ok {
fmt.Println("Unable to convert post action hook to map[string]interface{}")
continue
}

postActionHookStruct := &models.PostActionHook{}
jsonBytes, err := json.Marshal(hookMap)
if err != nil {
fmt.Println("Unable to convert post action hook to json")
continue
}

err = json.Unmarshal(jsonBytes, postActionHookStruct)
if err != nil {
fmt.Println("Unable to unmarshal json into struct")
continue
}
postActionHookStruct.Execute()
}
}
return pair, nil
}

func Test_SpyMode_WhenGivenAMatchingRequestItReturnsTheCorrectResponse(t *testing.T) {
RegisterTestingT(t)

Expand Down

0 comments on commit ce50a7d

Please sign in to comment.