diff --git a/docs/src/main/asciidoc/migrations.adoc b/docs/src/main/asciidoc/migrations.adoc index f2bd566dc0..2bc45beaa6 100644 --- a/docs/src/main/asciidoc/migrations.adoc +++ b/docs/src/main/asciidoc/migrations.adoc @@ -132,3 +132,11 @@ The flow for setting the generated tests package name will look like this: Related to https://github.com/spring-cloud/spring-cloud-contract/issues/260[issue 260]. + +==== New methods in TemplateProcessor + +In order to add support for `fromRequest.path` some methods had to be added to the +`TemplateProcessor` interface. + +Related to +https://github.com/spring-cloud/spring-cloud-contract/issues/388[issue 388]. \ No newline at end of file diff --git a/pom.xml b/pom.xml index 6bafc04a89..9aadf5ba46 100644 --- a/pom.xml +++ b/pom.xml @@ -130,8 +130,8 @@ org.apache.commons - commons-lang3 - 3.6 + commons-text + 1.1 au.com.dius diff --git a/spring-cloud-contract-spec/pom.xml b/spring-cloud-contract-spec/pom.xml index cf6adf397c..d554eb0382 100644 --- a/spring-cloud-contract-spec/pom.xml +++ b/spring-cloud-contract-spec/pom.xml @@ -36,7 +36,7 @@ org.apache.commons - commons-lang3 + commons-text org.slf4j diff --git a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/ContractTemplate.groovy b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/ContractTemplate.groovy index 5d7cd1270c..86a6ab914b 100644 --- a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/ContractTemplate.groovy +++ b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/ContractTemplate.groovy @@ -23,7 +23,7 @@ interface ContractTemplate { String closingTemplate() /** - * Returns the template for retrieving a URL from request + * Returns the template for retrieving a URL path and query from request */ String url() @@ -40,6 +40,17 @@ interface ContractTemplate { */ String query(String key, int index) + /** + * Returns the template for retrieving a URL path + */ + String path() + + /** + * Returns the template for retrieving nth value of a URL path (zero indexed) e.g. {{{ request.path.[2] }}} + * @param index + */ + String path(int index) + /** * Returns the template for retrieving the first value of a request header e.g. {{{ request.headers.X-Request-Id }}} * @param key diff --git a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/FromRequest.groovy b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/FromRequest.groovy index 7c504f7388..27a37534f9 100644 --- a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/FromRequest.groovy +++ b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/FromRequest.groovy @@ -2,13 +2,13 @@ package org.springframework.cloud.contract.spec.internal import groovy.transform.CompileStatic import org.springframework.cloud.contract.spec.ContractTemplate + /** * Helper class to reference the request body parameters * * @author Marcin Grzejszczak * @since 1.1.0 */ - @CompileStatic class FromRequest { @@ -46,6 +46,21 @@ class FromRequest { return new DslProperty(template.query(key, index)) } + /** + * URL path + */ + DslProperty path() { + return new DslProperty(template.path()) + } + + /** + * nth value of a URL path (zero indexed) e.g. {{{ request.path.[2] }}} + * @param index + */ + DslProperty path(int index) { + return new DslProperty(template.path(index)) + } + /** * First value of a request header e.g. request.headers.X-Request-Id * @param key diff --git a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/HandlebarsContractTemplate.groovy b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/HandlebarsContractTemplate.groovy index 33d49aa348..5e223642bf 100644 --- a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/HandlebarsContractTemplate.groovy +++ b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/HandlebarsContractTemplate.groovy @@ -38,6 +38,16 @@ class HandlebarsContractTemplate implements ContractTemplate { return wrapped("request.query.${key}.[${index}]") } + @Override + String path() { + return wrapped("request.path") + } + + @Override + String path(int index) { + return wrapped("request.path.[${index}]") + } + @Override String header(String key) { return header(key, 0) diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/WireMockToDslConverter.groovy b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/WireMockToDslConverter.groovy index 7e8b93c372..736fec8587 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/WireMockToDslConverter.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/WireMockToDslConverter.groovy @@ -27,7 +27,7 @@ import repackaged.nl.flotsam.xeger.Xeger import java.nio.charset.StandardCharsets -import static org.apache.commons.lang3.StringEscapeUtils.escapeJava +import static org.apache.commons.text.StringEscapeUtils.escapeJava /** * Converts WireMock stubs into the DSL format diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/TestGenerator.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/TestGenerator.groovy index f53ecdbfd9..1ddc638d68 100755 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/TestGenerator.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/TestGenerator.groovy @@ -20,9 +20,8 @@ import java.nio.charset.StandardCharsets import java.nio.file.Path import java.util.concurrent.atomic.AtomicInteger -import wiremock.com.google.common.collect.ListMultimap import groovy.transform.PackageScope -import org.apache.commons.lang3.StringUtils +import wiremock.com.google.common.collect.ListMultimap import org.springframework.cloud.contract.spec.ContractVerifierException import org.springframework.cloud.contract.verifier.builder.JavaTestGenerator @@ -31,13 +30,13 @@ import org.springframework.cloud.contract.verifier.config.ContractVerifierConfig import org.springframework.cloud.contract.verifier.file.ContractFileScanner import org.springframework.cloud.contract.verifier.file.ContractMetadata import org.springframework.core.io.support.SpringFactoriesLoader +import org.springframework.util.StringUtils import static org.springframework.cloud.contract.verifier.util.NamesUtil.afterLast import static org.springframework.cloud.contract.verifier.util.NamesUtil.beforeLast import static org.springframework.cloud.contract.verifier.util.NamesUtil.convertIllegalPackageChars import static org.springframework.cloud.contract.verifier.util.NamesUtil.directoryToPackage import static org.springframework.cloud.contract.verifier.util.NamesUtil.toLastDot - /** * @author Jakub Kubrynski, codearte.io */ @@ -104,7 +103,7 @@ class TestGenerator { private String relativizeContractPath(Map.Entry> entry) { Path relativePath = configProperties.contractsDslDir.toPath().relativize(entry.getKey()) - if (StringUtils.isBlank(relativePath.toString())) { + if (StringUtils.isEmpty(relativePath.toString())) { return DEFAULT_CLASS_PREFIX } return relativePath.toString() diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilder.groovy index 22bf426855..667bb2b356 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilder.groovy @@ -22,7 +22,7 @@ import com.jayway.jsonpath.PathNotFoundException import groovy.json.JsonOutput import groovy.transform.PackageScope import groovy.transform.TypeChecked -import org.apache.commons.lang3.StringEscapeUtils +import org.apache.commons.text.StringEscapeUtils import org.apache.commons.logging.Log import org.apache.commons.logging.LogFactory import org.springframework.cloud.contract.spec.Contract diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodRequestProcessingBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodRequestProcessingBodyBuilder.groovy index 2ada092bf4..a8e26b52c4 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodRequestProcessingBodyBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodRequestProcessingBodyBuilder.groovy @@ -29,7 +29,7 @@ import org.springframework.cloud.contract.verifier.util.ContentUtils import java.util.regex.Pattern -import static org.apache.commons.lang3.StringEscapeUtils.escapeJava +import static org.apache.commons.text.StringEscapeUtils.escapeJava import static org.springframework.cloud.contract.verifier.util.ContentUtils.getGroovyMultipartFileParameterContent /** diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/TestSideRequestTemplateModel.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/TestSideRequestTemplateModel.groovy index b66e795591..e6d8140dbe 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/TestSideRequestTemplateModel.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/TestSideRequestTemplateModel.groovy @@ -3,7 +3,8 @@ package org.springframework.cloud.contract.verifier.builder import groovy.json.JsonOutput import groovy.transform.CompileStatic import groovy.transform.Immutable -import org.apache.commons.lang3.StringEscapeUtils +import org.apache.commons.text.StringEscapeUtils + import org.springframework.cloud.contract.spec.internal.DslProperty import org.springframework.cloud.contract.spec.internal.Request import org.springframework.cloud.contract.verifier.util.ContentUtils @@ -29,6 +30,11 @@ class TestSideRequestTemplateModel { */ final Map> query + /** + * List of path entries + */ + final Path path + /** * Map containing request headers */ @@ -46,10 +52,14 @@ class TestSideRequestTemplateModel { static TestSideRequestTemplateModel from(final Request request) { String url = MapConverter.getTestSideValues(request.url ?: request.urlPath) + Path paths = new Path(buildPathsFromUrl(url)) Map> query = (Map>) (request.url ?: request.urlPath) .queryParameters?.parameters?.groupBy { it.name }?.collectEntries { [(it.key): it.value.collect { MapConverter.getTestSideValues(it) }] } + String fullUrl = (query == null || query.isEmpty()) ? url : + url + "?" + query.collect { String name, List values -> + return values.collect { "${name}=${it}"}.join("&") }.join("&") Map> headers = (Map>) (request.headers?.entries?.groupBy { it.name }?.collectEntries { @@ -57,7 +67,14 @@ class TestSideRequestTemplateModel { }) String body = trimmedAndEscapedBody(request.body) String rawBody = getBodyAsRawJson(request.body) - return new TestSideRequestTemplateModel(url, query, headers, body, rawBody) + return new TestSideRequestTemplateModel(fullUrl, query, paths, headers, body, rawBody) + } + + private static List buildPathsFromUrl(String url) { + String fakeUrl = "http://foo.bar" + (url.startsWith("/") ? url : "/" + url) + List paths = new URL(fakeUrl).path.split("/") as List + paths.remove(0) + return paths } private static String trimmedAndEscapedBody(Object body) { @@ -81,3 +98,16 @@ class TestSideRequestTemplateModel { return bodyValue } } + +@CompileStatic +class Path extends ArrayList { + + Path(List list) { + this.addAll(list) + } + + @Override + String toString() { + return "/" + this.join("/") + } +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/handlebars/HandlebarsEscapeHelper.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/handlebars/HandlebarsEscapeHelper.groovy index 62af651436..72c6007c23 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/handlebars/HandlebarsEscapeHelper.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/handlebars/HandlebarsEscapeHelper.groovy @@ -4,7 +4,7 @@ import wiremock.com.github.jknack.handlebars.Helper import wiremock.com.github.jknack.handlebars.Options import com.github.tomakehurst.wiremock.extension.responsetemplating.RequestTemplateModel import groovy.transform.CompileStatic -import org.apache.commons.lang3.StringEscapeUtils +import org.apache.commons.text.StringEscapeUtils import org.springframework.cloud.contract.verifier.builder.TestSideRequestTemplateModel /** * A Handlebars helper for the {@code escapejsonbody} helper function. diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScanner.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScanner.groovy index 91b254248f..37da2a9593 100755 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScanner.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScanner.groovy @@ -20,7 +20,6 @@ import wiremock.com.google.common.collect.ArrayListMultimap import wiremock.com.google.common.collect.ListMultimap import groovy.transform.CompileStatic import groovy.util.logging.Slf4j -import org.apache.commons.lang3.SystemUtils import org.springframework.cloud.contract.spec.Contract import org.springframework.cloud.contract.spec.ContractConverter import org.springframework.cloud.contract.verifier.util.ContractVerifierDslConverter @@ -43,6 +42,10 @@ import java.util.regex.Pattern @Slf4j class ContractFileScanner { + private static final String OS_NAME = System.getProperty("os.name"); + private static final String OS_NAME_WINDOWS_PREFIX = "Windows"; + protected static final boolean IS_OS_WINDOWS = getOSMatchesName(OS_NAME_WINDOWS_PREFIX); + private static final String MATCH_PREFIX = "glob:" private static final Pattern SCENARIO_STEP_FILENAME_PATTERN = Pattern.compile("[0-9]+_.*") private final File baseDir @@ -62,7 +65,7 @@ class ContractFileScanner { return patterns.collect({ String syntaxAndPattern = MATCH_PREFIX + '**' + File.separator + it // FIXME: This looks strange, need to be checked on windows - if (SystemUtils.IS_OS_WINDOWS) { + if (IS_OS_WINDOWS) { syntaxAndPattern = syntaxAndPattern.replace("\\", "\\\\") } fileSystem.getPathMatcher(syntaxAndPattern) @@ -177,4 +180,31 @@ class ContractFileScanner { } return path.substring(extIndex + 1); } + + /** + * Decides if the operating system matches. + * + * @param osNamePrefix the prefix for the os name + * @return true if matches, or false if not or can't determine + */ + private static boolean getOSMatchesName(final String osNamePrefix) { + return isOSNameMatch(OS_NAME, osNamePrefix); + } + + /** + * Decides if the operating system matches. + *

+ * This method is package private instead of private to support unit test invocation. + *

+ * + * @param osName the actual OS name + * @param osNamePrefix the prefix for the expected OS name + * @return true if matches, or false if not or can't determine + */ + private static boolean isOSNameMatch(final String osName, final String osNamePrefix) { + if (osName == null) { + return false; + } + return osName.startsWith(osNamePrefix); + } } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/template/TemplateProcessor.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/template/TemplateProcessor.groovy index 6791fea2b6..0d768437fc 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/template/TemplateProcessor.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/template/TemplateProcessor.groovy @@ -1,6 +1,7 @@ package org.springframework.cloud.contract.verifier.template import org.springframework.cloud.contract.spec.internal.Request + /** * Contract for conversion of templated responses. * diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy index ea0aa40b39..98cfa5cc69 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy @@ -32,9 +32,9 @@ import org.springframework.cloud.contract.spec.internal.OptionalProperty import java.util.regex.Matcher import java.util.regex.Pattern -import static org.apache.commons.lang3.StringEscapeUtils.escapeJava -import static org.apache.commons.lang3.StringEscapeUtils.escapeJson -import static org.apache.commons.lang3.StringEscapeUtils.escapeXml11 +import static org.apache.commons.text.StringEscapeUtils.escapeJava +import static org.apache.commons.text.StringEscapeUtils.escapeJson +import static org.apache.commons.text.StringEscapeUtils.escapeXml11 /** * A utility class that can operate on a message body basing on the provided Content Type. diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java index 1975f04bef..58ef30623d 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DelegatingJsonVerifiable.java @@ -16,12 +16,12 @@ package org.springframework.cloud.contract.verifier.util; -import com.toomuchcoding.jsonassert.JsonVerifiable; - import java.util.LinkedList; import java.util.regex.Pattern; -import static org.apache.commons.lang3.StringEscapeUtils.escapeJava; +import com.toomuchcoding.jsonassert.JsonVerifiable; + +import static org.apache.commons.text.StringEscapeUtils.escapeJava; /** * Implementation of the {@link MethodBufferingJsonVerifiable} that contains a list diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/RegexpBuilders.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/RegexpBuilders.groovy index 0d9c1184ba..f1593eb2f4 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/RegexpBuilders.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/RegexpBuilders.groovy @@ -23,7 +23,7 @@ import org.springframework.cloud.contract.spec.util.RegexpUtils import java.util.regex.Pattern -import static org.apache.commons.lang3.StringEscapeUtils.escapeJson +import static org.apache.commons.text.StringEscapeUtils.escapeJson import static ContentType.* import static ContentUtils.extractValue diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy index df5930b7ca..aebd757d63 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy @@ -2291,6 +2291,8 @@ DocumentContext parsedJson = JsonPath.parse(json); } body( url: fromRequest().url(), + path: fromRequest().path(), + pathIndex: fromRequest().path(1), param: fromRequest().query("foo"), paramIndex: fromRequest().query("foo", 1), authorization: fromRequest().header("Authorization"), @@ -2312,7 +2314,9 @@ DocumentContext parsedJson = JsonPath.parse(json); SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) then: !test.contains('''DslProperty''') - test.contains('''assertThatJson(parsedJson).field("['url']").isEqualTo("/api/v1/xxxx")''') + test.contains('''assertThatJson(parsedJson).field("['url']").isEqualTo("/api/v1/xxxx?foo=bar&foo=bar2")''') + test.contains('''assertThatJson(parsedJson).field("['path']").isEqualTo("/api/v1/xxxx")''') + test.contains('''assertThatJson(parsedJson).field("['pathIndex']").isEqualTo("v1")''') test.contains('''assertThatJson(parsedJson).field("['fullBody']").isEqualTo("{\\"foo\\":\\"bar\\",\\"baz\\":5}")''') test.contains('''assertThatJson(parsedJson).field("['paramIndex']").isEqualTo("bar2")''') test.contains('''assertThatJson(parsedJson).field("['responseFoo']").isEqualTo("bar")''') diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy index f4df63cb15..de924d9c5b 100755 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy @@ -1759,6 +1759,8 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } body( url: fromRequest().url(), + path: fromRequest().path(), + pathIndex: fromRequest().path(1), param: fromRequest().query("foo"), paramIndex: fromRequest().query("foo", 1), authorization: fromRequest().header("Authorization"), @@ -1796,7 +1798,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie }, "response" : { "status" : 200, - "body" : "{\\"url\\":\\"{{{request.url}}}\\",\\"param\\":\\"{{{request.query.foo.[0]}}}\\",\\"paramIndex\\":\\"{{{request.query.foo.[1]}}}\\",\\"authorization\\":\\"{{{request.headers.Authorization.[0]}}}\\",\\"authorization2\\":\\"{{{request.headers.Authorization.[1]}}}\\",\\"fullBody\\":\\"{{{escapejsonbody}}}\\",\\"responseFoo\\":\\"{{{jsonpath this '$.foo'}}}\\",\\"responseBaz\\":{{{jsonpath this '$.baz'}}} ,\\"responseBaz2\\":\\"Bla bla {{{jsonpath this '$.foo'}}} bla bla\\"}", + "body" : "{\\"url\\":\\"{{{request.url}}}\\",\\"path\\":\\"{{{request.path}}}\\",\\"pathIndex\\":\\"{{{request.path.[1]}}}\\",\\"param\\":\\"{{{request.query.foo.[0]}}}\\",\\"paramIndex\\":\\"{{{request.query.foo.[1]}}}\\",\\"authorization\\":\\"{{{request.headers.Authorization.[0]}}}\\",\\"authorization2\\":\\"{{{request.headers.Authorization.[1]}}}\\",\\"fullBody\\":\\"{{{escapejsonbody}}}\\",\\"responseFoo\\":\\"{{{jsonpath this '$.foo'}}}\\",\\"responseBaz\\":{{{jsonpath this '$.baz'}}} ,\\"responseBaz2\\":\\"Bla bla {{{jsonpath this '$.foo'}}} bla bla\\"}", "headers" : { "Authorization" : "{{{request.headers.Authorization.[0]}}};foo" },