Skip to content

Commit 560f2e6

Browse files
committed
Avoid copying the journal data into context data for template rendering
1 parent b120b47 commit 560f2e6

5 files changed

Lines changed: 41 additions & 78 deletions

File tree

core/hoverfly.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,16 @@ func NewHoverfly() *Hoverfly {
5353

5454
authBackend := backends.NewCacheBasedAuthBackend(cache.NewInMemoryCache(), cache.NewInMemoryCache())
5555

56+
newJournal := journal.NewJournal()
5657
hoverfly := &Hoverfly{
5758
Simulation: models.NewSimulation(),
5859
Authentication: authBackend,
5960
Counter: metrics.NewModeCounter([]string{modes.Simulate, modes.Synthesize, modes.Modify, modes.Capture, modes.Spy, modes.Diff}),
6061
StoreLogsHook: NewStoreLogsHook(),
61-
Journal: journal.NewJournal(),
62+
Journal: newJournal,
6263
Cfg: InitSettings(),
6364
state: state.NewState(),
64-
templator: templating.NewTemplator(),
65+
templator: templating.NewTemplatorWithJournal(newJournal),
6566
responsesDiff: make(map[v2.SimpleRequestDefinitionView][]v2.DiffReport),
6667
PostServeActionDetails: action.NewPostServeActionDetails(),
6768
}

core/hoverfly_funcs.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ func (hf *Hoverfly) applyTransitionsStateTemplating(requestDetails *models.Reque
224224
state := make(map[string]string)
225225

226226
for k, v := range stateTemplates {
227-
state[k], err = hf.templator.RenderTemplate(v, requestDetails, response, hf.Simulation.Literals, hf.Simulation.Vars, hf.state.State, hf.Journal)
227+
state[k], err = hf.templator.RenderTemplate(v, requestDetails, response, hf.Simulation.Literals, hf.Simulation.Vars, hf.state.State)
228228
if err != nil {
229229
return nil, err
230230
}
@@ -245,7 +245,7 @@ func (hf *Hoverfly) applyBodyTemplating(requestDetails *models.RequestDetails, r
245245
}
246246
}
247247

248-
return hf.templator.RenderTemplate(template, requestDetails, response, hf.Simulation.Literals, hf.Simulation.Vars, hf.state.State, hf.Journal)
248+
return hf.templator.RenderTemplate(template, requestDetails, response, hf.Simulation.Literals, hf.Simulation.Vars, hf.state.State)
249249
}
250250

251251
func (hf *Hoverfly) applyHeadersTemplating(requestDetails *models.RequestDetails, response *models.ResponseDetails, cachedResponse *models.CachedResponse) (map[string][]string, error) {
@@ -280,7 +280,7 @@ func (hf *Hoverfly) applyHeadersTemplating(requestDetails *models.RequestDetails
280280
for k, v := range headersTemplates {
281281
header = make([]string, len(v))
282282
for i, h := range v {
283-
header[i], err = hf.templator.RenderTemplate(h, requestDetails, response, hf.Simulation.Literals, hf.Simulation.Vars, hf.state.State, hf.Journal)
283+
header[i], err = hf.templator.RenderTemplate(h, requestDetails, response, hf.Simulation.Literals, hf.Simulation.Vars, hf.state.State)
284284

285285
if err != nil {
286286
return nil, err

core/templating/template_helpers.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type templateHelpers struct {
2626
now func() time.Time
2727
fakerSource *gofakeit.Faker
2828
TemplateDataSource *TemplateDataSource
29+
Journal *journal.Journal
2930
}
3031

3132
func (t templateHelpers) nowHelper(offset string, format string) string {
@@ -466,8 +467,7 @@ func (t templateHelpers) csvSqlCommand(commandString string) []RowMap {
466467
}
467468

468469
func (t templateHelpers) parseJournalBasedOnIndex(indexName, keyValue, dataSource, queryType, lookupQuery string, options *raymond.Options) interface{} {
469-
journalDetails := options.Value("Journal").(Journal)
470-
if journalEntry, err := getIndexEntry(journalDetails, indexName, keyValue); err == nil {
470+
if journalEntry, err := getIndexEntry(t.Journal, indexName, keyValue); err == nil {
471471
if body := getBodyDataToParse(dataSource, journalEntry); body != "" {
472472
data := util.FetchFromRequestBody(queryType, lookupQuery, body)
473473
if _, ok := data.(error); ok {
@@ -481,9 +481,9 @@ func (t templateHelpers) parseJournalBasedOnIndex(indexName, keyValue, dataSourc
481481
return getEvaluationString("journal", options)
482482
}
483483

484-
func (t templateHelpers) hasJournalKey(indexName, keyValue string, options *raymond.Options) bool {
485-
journalDetails := options.Value("Journal").(Journal)
486-
journalEntry, _ := getIndexEntry(journalDetails, indexName, keyValue)
484+
func (t templateHelpers) hasJournalKey(indexName, keyValue string) bool {
485+
486+
journalEntry, _ := getIndexEntry(t.Journal, indexName, keyValue)
487487

488488
return journalEntry != nil
489489
}
@@ -615,25 +615,25 @@ func formatNumber(number float64, format string) string {
615615
return fmt.Sprintf("%."+strconv.Itoa(decimalPlaces)+"f", rounded)
616616
}
617617

618-
func getIndexEntry(journalIndexDetails Journal, indexName, indexValue string) (*JournalEntry, error) {
618+
func getIndexEntry(journalIndexDetails *journal.Journal, indexName, indexValue string) (*journal.JournalEntry, error) {
619619

620-
for _, index := range journalIndexDetails.indexes {
621-
if index.name == indexName {
622-
if journalEntry, exists := index.entries[indexValue]; exists {
623-
return &journalEntry, nil
620+
for _, index := range journalIndexDetails.Indexes {
621+
if index.Name == indexName {
622+
if journalEntry, exists := index.Entries[indexValue]; exists {
623+
return journalEntry, nil
624624
}
625625
}
626626
}
627627
return nil, fmt.Errorf("no entry found for index %s", indexName)
628628
}
629629

630-
func getBodyDataToParse(source string, journalEntry *JournalEntry) string {
630+
func getBodyDataToParse(source string, journalEntry *journal.JournalEntry) string {
631631

632632
if strings.EqualFold(source, "request") {
633-
return journalEntry.requestBody
633+
return journalEntry.Request.Body
634634
}
635635
if strings.EqualFold(source, "response") {
636-
return journalEntry.responseBody
636+
return journalEntry.Response.Body
637637
}
638638
return ""
639639
}

core/templating/templating.go

Lines changed: 8 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ type TemplatingData struct {
2525
CurrentDateTime func(string, string, string) string
2626
Literals map[string]interface{}
2727
Vars map[string]interface{}
28-
Journal Journal
2928
Kvs map[string]interface{}
3029
InternalVars map[string]interface{} // data store used internally by templating helpers
3130
}
@@ -42,19 +41,6 @@ type Request struct {
4241
Host string
4342
}
4443

45-
type JournalEntry struct {
46-
requestBody string
47-
responseBody string
48-
}
49-
50-
type Journal struct {
51-
indexes []JournalIndex
52-
}
53-
54-
type JournalIndex struct {
55-
name string
56-
entries map[string]JournalEntry
57-
}
5844

5945
type Templator struct {
6046
SupportedMethodMap map[string]interface{}
@@ -65,13 +51,18 @@ var helpersRegistered = false
6551
var helperMethodMap = make(map[string]interface{})
6652

6753
func NewTemplator() *Templator {
54+
return NewTemplatorWithJournal(journal.NewJournal())
55+
}
56+
57+
func NewTemplatorWithJournal(journal *journal.Journal) *Templator {
6858

6959
templateDataSource := NewTemplateDataSource()
7060

7161
t := templateHelpers{
7262
now: time.Now,
7363
fakerSource: gofakeit.New(0),
7464
TemplateDataSource: templateDataSource,
65+
Journal: journal,
7566
}
7667

7768
helperMethodMap["now"] = t.nowHelper
@@ -148,12 +139,12 @@ func (*Templator) ParseTemplate(responseBody string) (*raymond.Template, error)
148139
return raymond.Parse(responseBody)
149140
}
150141

151-
func (t *Templator) RenderTemplate(tpl *raymond.Template, requestDetails *models.RequestDetails, response *models.ResponseDetails, literals *models.Literals, vars *models.Variables, state map[string]string, journal *journal.Journal) (string, error) {
142+
func (t *Templator) RenderTemplate(tpl *raymond.Template, requestDetails *models.RequestDetails, response *models.ResponseDetails, literals *models.Literals, vars *models.Variables, state map[string]string) (string, error) {
152143
if tpl == nil {
153144
return "", fmt.Errorf("template cannot be nil")
154145
}
155146

156-
ctx := t.NewTemplatingData(requestDetails, response, literals, vars, state, journal)
147+
ctx := t.NewTemplatingData(requestDetails, literals, vars, state)
157148
result, err := tpl.Exec(ctx)
158149
if err == nil {
159150
statusCode, ok := ctx.InternalVars["statusCode"]
@@ -168,7 +159,7 @@ func (templator *Templator) GetSupportedMethodMap() map[string]interface{} {
168159
return templator.SupportedMethodMap
169160
}
170161

171-
func (t *Templator) NewTemplatingData(requestDetails *models.RequestDetails, response *models.ResponseDetails, literals *models.Literals, vars *models.Variables, state map[string]string, journal *journal.Journal) *TemplatingData {
162+
func (t *Templator) NewTemplatingData(requestDetails *models.RequestDetails, literals *models.Literals, vars *models.Variables, state map[string]string) *TemplatingData {
172163

173164
literalMap := make(map[string]interface{})
174165
if literals != nil {
@@ -178,40 +169,13 @@ func (t *Templator) NewTemplatingData(requestDetails *models.RequestDetails, res
178169
}
179170

180171
variableMap := t.getVariables(vars, requestDetails)
181-
templateJournal := Journal{}
182-
if journal != nil {
183-
184-
indexes := make([]JournalIndex, 0, len(journal.Indexes))
185-
for _, index := range journal.Indexes {
186-
187-
journalIndexEntries := make(map[string]JournalEntry)
188-
for indexKey, entry := range index.Entries {
189-
190-
journalEntry := JournalEntry{
191-
requestBody: entry.Request.Body,
192-
responseBody: entry.Response.Body,
193-
}
194-
journalIndexEntries[indexKey] = journalEntry
195-
}
196-
journalIndex := JournalIndex{
197-
name: index.Name,
198-
entries: journalIndexEntries,
199-
}
200-
indexes = append(indexes, journalIndex)
201-
}
202-
templateJournal = Journal{
203-
indexes: indexes,
204-
}
205-
206-
}
207172

208173
kvs := make(map[string]interface{})
209174
return &TemplatingData{
210175
Request: getRequest(requestDetails),
211176
Literals: literalMap,
212177
Vars: variableMap,
213178
State: state,
214-
Journal: templateJournal,
215179
CurrentDateTime: func(a1, a2, a3 string) string {
216180
return a1 + " " + a2 + " " + a3
217181
},

core/templating/templating_test.go

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package templating_test
33
import (
44
"testing"
55

6-
"github.com/SpectoLabs/hoverfly/core/journal"
7-
86
"github.com/SpectoLabs/hoverfly/core/models"
97
"github.com/SpectoLabs/hoverfly/core/templating"
108
. "github.com/onsi/gomega"
@@ -297,7 +295,7 @@ func Test_ShouldCreateTemplatingDataPathsFromRequest(t *testing.T) {
297295
Scheme: "http",
298296
Destination: "test.com",
299297
Path: "/foo/bar",
300-
}, nil, &models.Literals{}, &models.Variables{}, make(map[string]string), &journal.Journal{})
298+
}, &models.Literals{}, &models.Variables{}, make(map[string]string))
301299

302300
Expect(actual.Request.Path).To(ConsistOf("foo", "bar"))
303301
}
@@ -308,7 +306,7 @@ func Test_ShouldCreateTemplatingDataPathsFromRequestWithNoPaths(t *testing.T) {
308306
actual := templating.NewTemplator().NewTemplatingData(&models.RequestDetails{
309307
Scheme: "http",
310308
Destination: "test.com",
311-
}, nil, &models.Literals{}, &models.Variables{}, make(map[string]string), &journal.Journal{})
309+
}, &models.Literals{}, &models.Variables{}, make(map[string]string))
312310

313311
Expect(actual.Request.Path).To(BeEmpty())
314312
}
@@ -323,7 +321,7 @@ func Test_ShouldCreateTemplatingDataQueryParamsFromRequest(t *testing.T) {
323321
"cheese": {"1", "3"},
324322
"ham": {"2"},
325323
},
326-
}, nil, &models.Literals{}, &models.Variables{}, make(map[string]string), &journal.Journal{})
324+
}, &models.Literals{}, &models.Variables{}, make(map[string]string))
327325

328326
Expect(actual.Request.QueryParam).To(HaveKeyWithValue("cheese", []string{"1", "3"}))
329327
Expect(actual.Request.QueryParam).To(HaveKeyWithValue("ham", []string{"2"}))
@@ -336,7 +334,7 @@ func Test_ShouldCreateTemplatingDataQueryParamsFromRequestWithNoQueryParams(t *t
336334
actual := templating.NewTemplator().NewTemplatingData(&models.RequestDetails{
337335
Scheme: "http",
338336
Destination: "test.com",
339-
}, nil, &models.Literals{}, &models.Variables{}, make(map[string]string), &journal.Journal{})
337+
}, &models.Literals{}, &models.Variables{}, make(map[string]string))
340338

341339
Expect(actual.Request.QueryParam).To(BeEmpty())
342340
}
@@ -347,7 +345,7 @@ func Test_ShouldCreateTemplatingDataHttpScheme(t *testing.T) {
347345
actual := templating.NewTemplator().NewTemplatingData(&models.RequestDetails{
348346
Scheme: "http",
349347
Destination: "test.com",
350-
}, nil, &models.Literals{}, &models.Variables{}, make(map[string]string), &journal.Journal{})
348+
}, &models.Literals{}, &models.Variables{}, make(map[string]string))
351349

352350
Expect(actual.Request.Scheme).To(Equal("http"))
353351
}
@@ -362,7 +360,7 @@ func Test_ShouldCreateTemplatingDataHeaderFromRequest(t *testing.T) {
362360
"cheese": {"1", "3"},
363361
"ham": {"2"},
364362
},
365-
}, nil, &models.Literals{}, &models.Variables{}, make(map[string]string), &journal.Journal{})
363+
}, &models.Literals{}, &models.Variables{}, make(map[string]string))
366364

367365
Expect(actual.Request.Header).To(HaveKeyWithValue("cheese", []string{"1", "3"}))
368366
Expect(actual.Request.Header).To(HaveKeyWithValue("ham", []string{"2"}))
@@ -375,7 +373,7 @@ func Test_ShouldCreateTemplatingDataHeaderFromRequestWithNoHeader(t *testing.T)
375373
actual := templating.NewTemplator().NewTemplatingData(&models.RequestDetails{
376374
Scheme: "http",
377375
Destination: "test.com",
378-
}, nil, &models.Literals{}, &models.Variables{}, make(map[string]string), &journal.Journal{})
376+
}, &models.Literals{}, &models.Variables{}, make(map[string]string))
379377

380378
Expect(actual.Request.Header).To(BeEmpty())
381379
}
@@ -702,7 +700,7 @@ func Test_VarSetToNilInCaseOfInvalidArgsPassed(t *testing.T) {
702700
actual := templator.NewTemplatingData(&models.RequestDetails{
703701
Scheme: "http",
704702
Destination: "test.com",
705-
}, nil, &models.Literals{}, vars, make(map[string]string), &journal.Journal{})
703+
}, &models.Literals{}, vars, make(map[string]string))
706704

707705
Expect(actual.Vars["varOne"]).To(BeNil())
708706

@@ -722,7 +720,7 @@ func Test_VarSetToProperValueInCaseOfRequestDetailsPassedAsArgument(t *testing.T
722720

723721
actual := templator.NewTemplatingData(&models.RequestDetails{
724722
Path: "/part1/foo,bar",
725-
}, nil, &models.Literals{}, vars, make(map[string]string), &journal.Journal{})
723+
}, &models.Literals{}, vars, make(map[string]string))
726724

727725
Expect(actual.Vars["splitRequestPath"]).ToNot(BeNil())
728726
Expect(len(actual.Vars["splitRequestPath"].([]string))).To(Equal(2))
@@ -823,13 +821,13 @@ func Test_ApplyTemplate_Arithmetic_Ops_With_Each_Block(t *testing.T) {
823821

824822
template, _ := templator.ParseTemplate(responseBody)
825823
state := make(map[string]string)
826-
result, err := templator.RenderTemplate(template, requestDetails, nil, &models.Literals{}, &models.Variables{}, state, &journal.Journal{})
824+
result, err := templator.RenderTemplate(template, requestDetails, nil, &models.Literals{}, &models.Variables{}, state)
827825

828826
Expect(err).To(BeNil())
829827
Expect(result).To(Equal(` 3.5 9 total: 12.50`))
830828

831829
// Running the second time should produce the same result because each execution has its own context data.
832-
result, err = templator.RenderTemplate(template, requestDetails, nil, &models.Literals{}, &models.Variables{}, state, &journal.Journal{})
830+
result, err = templator.RenderTemplate(template, requestDetails, nil, &models.Literals{}, &models.Variables{}, state)
833831
Expect(err).To(BeNil())
834832
Expect(result).To(Equal(` 3.5 9 total: 12.50`))
835833
}
@@ -867,7 +865,7 @@ func Test_ApplyTemplate_setStatusCode(t *testing.T) {
867865
Expect(err).To(BeNil())
868866

869867
response := &models.ResponseDetails{}
870-
result, err := templator.RenderTemplate(template, &models.RequestDetails{}, response, &models.Literals{}, &models.Variables{}, make(map[string]string), &journal.Journal{})
868+
result, err := templator.RenderTemplate(template, &models.RequestDetails{}, response, &models.Literals{}, &models.Variables{}, make(map[string]string))
871869

872870
Expect(err).To(BeNil())
873871
Expect(result).To(Equal(""))
@@ -883,7 +881,7 @@ func Test_ApplyTemplate_setStatusCode_should_ignore_invalid_code(t *testing.T) {
883881
Expect(err).To(BeNil())
884882

885883
response := &models.ResponseDetails{}
886-
result, err := templator.RenderTemplate(template, &models.RequestDetails{}, response, &models.Literals{}, &models.Variables{}, make(map[string]string), &journal.Journal{})
884+
result, err := templator.RenderTemplate(template, &models.RequestDetails{}, response, &models.Literals{}, &models.Variables{}, make(map[string]string))
887885

888886
Expect(err).To(BeNil())
889887
Expect(result).To(Equal(""))
@@ -920,7 +918,7 @@ func ApplyTemplate(requestDetails *models.RequestDetails, state map[string]strin
920918
func renderTemplate(requestDetails *models.RequestDetails, state map[string]string, responseBody string, templator *templating.Templator) (string, error) {
921919
template, err := templator.ParseTemplate(responseBody)
922920
Expect(err).To(BeNil())
923-
return templator.RenderTemplate(template, requestDetails, nil, &models.Literals{}, &models.Variables{}, state, &journal.Journal{})
921+
return templator.RenderTemplate(template, requestDetails, nil, &models.Literals{}, &models.Variables{}, state)
924922
}
925923

926924
func initiateTemplator() *templating.Templator {

0 commit comments

Comments
 (0)