Skip to content

Commit afe807b

Browse files
author
Ronald Holshausen
committedMar 8, 2020
chore: disable escaping of HTML and XML embedded in JSON #1031
1 parent 0fefe31 commit afe807b

File tree

7 files changed

+148
-17
lines changed

7 files changed

+148
-17
lines changed
 

‎core/model/src/main/kotlin/au/com/dius/pact/core/model/generators/Generators.kt

+8-8
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ enum class Category {
2121
}
2222

2323
interface ContentTypeHandler {
24-
fun processBody(value: String, fn: (QueryResult) -> Unit): OptionalBody
24+
fun processBody(value: OptionalBody, fn: (QueryResult) -> Unit): OptionalBody
2525
fun applyKey(body: QueryResult, key: String, generator: Generator, context: Map<String, Any?>)
2626
}
2727

@@ -37,10 +37,10 @@ fun setupDefaultContentTypeHandlers() {
3737
data class QueryResult(var value: JsonElement?, val key: Any? = null, val parent: JsonElement? = null)
3838

3939
object JsonContentTypeHandler : ContentTypeHandler {
40-
override fun processBody(value: String, fn: (QueryResult) -> Unit): OptionalBody {
41-
val bodyJson = QueryResult(JsonParser().parse(value))
40+
override fun processBody(value: OptionalBody, fn: (QueryResult) -> Unit): OptionalBody {
41+
val bodyJson = QueryResult(JsonParser.parseString(value.valueAsString()))
4242
fn.invoke(bodyJson)
43-
return OptionalBody.body(Json.gson.toJson(bodyJson.value).toByteArray(), ContentType.JSON)
43+
return OptionalBody.body(Json.gson.toJson(bodyJson.value).toByteArray(value.contentType.asCharset()), ContentType.JSON)
4444
}
4545

4646
override fun applyKey(body: QueryResult, key: String, generator: Generator, context: Map<String, Any?>) {
@@ -195,14 +195,14 @@ data class Generators(val categories: MutableMap<Category, MutableMap<String, Ge
195195
return when (body.state) {
196196
OptionalBody.State.EMPTY, OptionalBody.State.MISSING, OptionalBody.State.NULL -> body
197197
OptionalBody.State.PRESENT -> when {
198-
contentType.isJson() -> processBody(body.valueAsString(), "application/json", context, mode)
199-
contentType.isXml() -> processBody(body.valueAsString(), "application/xml", context, mode)
198+
contentType.isJson() -> processBody(body, "application/json", context, mode)
199+
contentType.isXml() -> processBody(body, "application/xml", context, mode)
200200
else -> body
201201
}
202202
}
203203
}
204204

205-
private fun processBody(value: String, contentType: String, context: Map<String, Any?>, mode: GeneratorTestMode):
205+
private fun processBody(value: OptionalBody, contentType: String, context: Map<String, Any?>, mode: GeneratorTestMode):
206206
OptionalBody {
207207
val handler = contentTypeHandlers[contentType]
208208
return handler?.processBody(value) { body: QueryResult ->
@@ -211,7 +211,7 @@ data class Generators(val categories: MutableMap<Category, MutableMap<String, Ge
211211
handler.applyKey(body, key, generator, context)
212212
}
213213
}
214-
} ?: OptionalBody.body(value.toByteArray(ContentType(contentType).asCharset()), ContentType(contentType))
214+
} ?: value
215215
}
216216

217217
/**

‎core/model/src/test/groovy/au/com/dius/pact/core/model/PactReaderTransformSpec.groovy

+6-6
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class PactReaderTransformSpec extends Specification {
3636
]
3737

3838
jsonMap = this.class.getResourceAsStream('/pact.json').withReader {
39-
new JsonParser().parse(it).asJsonObject
39+
JsonParser.parseReader(it).asJsonObject
4040
}
4141
}
4242

@@ -58,7 +58,7 @@ class PactReaderTransformSpec extends Specification {
5858
| "request": {
5959
| "method": "GET",
6060
| "path": "/mallory",
61-
| "query": "name\\u003dron\\u0026status\\u003dgood",
61+
| "query": "name=ron&status=good",
6262
| "body": {
6363
| "id": "123",
6464
| "method": "create"
@@ -97,7 +97,7 @@ class PactReaderTransformSpec extends Specification {
9797
| "request": {
9898
| "method": "GET",
9999
| "path": "/mallory",
100-
| "query": "name\\u003dron\\u0026status\\u003dgood",
100+
| "query": "name=ron&status=good",
101101
| "body": {
102102
| "id": "123",
103103
| "method": "create"
@@ -138,7 +138,7 @@ class PactReaderTransformSpec extends Specification {
138138
| "request": {
139139
| "method": "GET",
140140
| "path": "/mallory",
141-
| "query": "name\\u003dron\\u0026status\\u003dgood",
141+
| "query": "name=ron&status=good",
142142
| "body": {
143143
| "id": "123",
144144
| "method": "create"
@@ -181,7 +181,7 @@ class PactReaderTransformSpec extends Specification {
181181
| "request": {
182182
| "method": "GET",
183183
| "path": "/mallory",
184-
| "query": "name\\u003dron\\u0026status\\u003dgood",
184+
| "query": "name=ron&status=good",
185185
| "body": {
186186
| "id": "123",
187187
| "method": "create"
@@ -239,7 +239,7 @@ class PactReaderTransformSpec extends Specification {
239239
| "request": {
240240
| "method": "POST",
241241
| "path": "/mallory",
242-
| "query": "name\\u003dron\\u0026status\\u003dgood",
242+
| "query": "name=ron&status=good",
243243
| "body": {
244244
| "id": "123",
245245
| "method": "create"

‎core/support/src/main/kotlin/au/com/dius/pact/core/support/Json.kt

+6-2
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@ open class NumberSerializer : JsonSerializer<Number> {
2727
object Json {
2828

2929
val numberAdapter = NumberSerializer()
30-
val gsonPretty: Gson = GsonBuilder().setPrettyPrinting().serializeNulls().registerTypeHierarchyAdapter(Number::class.java, numberAdapter).create()
31-
val gson: Gson = GsonBuilder().serializeNulls().registerTypeHierarchyAdapter(Number::class.java, numberAdapter).create()
30+
val gsonPretty: Gson = GsonBuilder().setPrettyPrinting()
31+
.serializeNulls()
32+
.disableHtmlEscaping()
33+
.registerTypeHierarchyAdapter(Number::class.java, numberAdapter).create()
34+
val gson: Gson = GsonBuilder().serializeNulls().disableHtmlEscaping()
35+
.registerTypeHierarchyAdapter(Number::class.java, numberAdapter).create()
3236

3337
/**
3438
* Converts an Object graph to a JSON Object

‎provider/pact-jvm-provider-junit5/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ dependencies {
77
testRuntime "ch.qos.logback:logback-classic:${project.logbackVersion}"
88
testCompile 'ru.lanwen.wiremock:wiremock-junit5:1.1.1'
99
testCompile 'com.github.tomakehurst:wiremock:2.19.0'
10+
testRuntime "org.junit.jupiter:junit-jupiter-engine:${project.junit5Version}"
1011
testRuntime "org.junit.vintage:junit-vintage-engine:${project.junit5Version}"
1112
testCompile "org.codehaus.groovy:groovy:${project.groovyVersion}"
1213
testCompile('org.spockframework:spock-core:2.0-M2-groovy-3.0') {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package au.com.dius.pact.provider.junit5
2+
3+
import au.com.dius.pact.core.model.Interaction
4+
import au.com.dius.pact.core.model.Pact
5+
import au.com.dius.pact.provider.junit.Provider
6+
import au.com.dius.pact.provider.junit.State
7+
import au.com.dius.pact.provider.junit.loader.PactFolder
8+
import com.github.tomakehurst.wiremock.WireMockServer
9+
import groovy.util.logging.Slf4j
10+
import org.apache.commons.lang3.RandomStringUtils
11+
import org.apache.http.HttpRequest
12+
import org.junit.jupiter.api.BeforeAll
13+
import org.junit.jupiter.api.BeforeEach
14+
import org.junit.jupiter.api.TestTemplate
15+
import org.junit.jupiter.api.extension.ExtendWith
16+
import ru.lanwen.wiremock.ext.WiremockResolver
17+
import ru.lanwen.wiremock.ext.WiremockUriResolver
18+
19+
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse
20+
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo
21+
import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath
22+
import static com.github.tomakehurst.wiremock.client.WireMock.post
23+
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo
24+
25+
@Provider('XmlInJsonService')
26+
@PactFolder('pacts')
27+
@ExtendWith([
28+
WiremockResolver,
29+
WiremockUriResolver
30+
])
31+
@Slf4j
32+
class StateInjectedProviderTest {
33+
34+
@TestTemplate
35+
@ExtendWith(PactVerificationInvocationContextProvider)
36+
void testTemplate(Pact pact, Interaction interaction, HttpRequest request, PactVerificationContext context) {
37+
log.info("testTemplate called: ${pact.provider.name}, ${interaction.description}")
38+
request.addHeader('X-ContractTest', 'true')
39+
40+
context.verifyInteraction()
41+
}
42+
43+
@BeforeAll
44+
static void setUpService() {
45+
//Run DB, create schema
46+
//Run service
47+
//...
48+
log.info('BeforeAll - setUpService ')
49+
}
50+
51+
@BeforeEach
52+
void before(PactVerificationContext context, @WiremockResolver.Wiremock WireMockServer server,
53+
@WiremockUriResolver.WiremockUri String uri) throws MalformedURLException {
54+
// Rest data
55+
// Mock dependent service responses
56+
// ...
57+
log.info("BeforeEach - $uri")
58+
59+
context.setTarget(HttpTestTarget.fromUrl(new URL(uri)))
60+
61+
server.stubFor(
62+
post(urlPathEqualTo('/data'))
63+
.withHeader('X-ContractTest', equalTo('true'))
64+
.withRequestBody(matchingJsonPath('$.[?(@.entityName =~ /\\w+/)]'))
65+
.willReturn(aResponse()
66+
.withStatus(201)
67+
.withHeader('Location', "http://localhost:${server.port()}/entity/1234"))
68+
)
69+
}
70+
71+
@State('create XML entity')
72+
Map<String, Object> createXmlEntityState() {
73+
log.info('create XML entity state')
74+
[eName: RandomStringUtils.randomAlphanumeric(20)]
75+
}
76+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{
2+
"provider": {
3+
"name": "XmlInJsonService"
4+
},
5+
"consumer": {
6+
"name": "XmlInJsonConsumer"
7+
},
8+
"interactions": [
9+
{
10+
"providerStates": [
11+
{
12+
"name": "create XML entity",
13+
"params": {
14+
"name": "mock-name"
15+
}
16+
}
17+
],
18+
"description": "Create new entity",
19+
"request": {
20+
"method": "POST",
21+
"path": "/data",
22+
"headers": {
23+
"Content-Type": ["application/json"]
24+
},
25+
"body": {
26+
"entityName": "mock-name",
27+
"xml": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<entity name=\"mock-name\"/>"
28+
},
29+
"generators": {
30+
"body": {
31+
"$.entityName": {
32+
"expression": "${eName}",
33+
"type": "ProviderState"
Has a conversation. Original line has a conversation.
34+
}
35+
}
36+
}
37+
},
38+
"response": {
39+
"status": 201
40+
}
41+
}
42+
],
43+
"metadata": {
44+
"pact-specification": {
45+
"version": "3.0.0"
46+
},
47+
"pact-jvm": {
48+
"version": "4.0.7"
49+
}
50+
}
51+
}

‎provider/pact-jvm-provider-maven/src/test/groovy/au/com/dius/pact/provider/maven/PactPublishMojoSpec.groovy

-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,6 @@ class PactPublishMojoSpec extends Specification {
171171
System.setProperty('pact.consumer.tags', '1,2,3')
172172
mojo.tags = ['one', 'two', 'three']
173173

174-
175174
when:
176175
mojo.execute()
177176

0 commit comments

Comments
 (0)
Please sign in to comment.