Closed kubejm closed 6 years ago
I met another or maybe same issue: generated wiremock config (or mappings) is "body" : "{\"name\":\"hi\\\\r\\\\nname\"}"
and return {"name":"hi\\r\\nname"}
in HTTP response, while I expected {"name":"hi\r\nname"}
(while should contains a newline)
What I have is a contract:
request:
method: GET
url: /my-url
response:
status: 200
bodyFromFile: hiname.json
headers:
Content-Type: application/json;charset=UTF-8
a hiname.json:
{
"name":"hi\r\nname"
}
and a generated mapping:
{
"id" : "c3cce57c-875d-4a45-85ce-ac094d07ec69",
"request" : {
"url" : "/my-url",
"method" : "GET"
},
"response" : {
"status" : 200,
"body" : "{\"name\":\"hi\\\\r\\\\nname\"}",
"headers" : {
"Content-Type" : "application/json;charset=UTF-8"
},
"transformers" : [ "response-template" ]
},
"uuid" : "c3cce57c-875d-4a45-85ce-ac094d07ec69"
}
Check if the workaround works for you
hi @marcingrzejszczak the workaround works for me, thank you~
add more info
I'm using spring-cloud-contract-gradle-plugin 2.0.0.RELEASE (which is latest for now)
I modified lines to make it work:
task fixSadContractIssue() {
dependsOn('generateClientStubs')
doLast {
File brokenMapping = new File(project.buildDir, '/stubs/META-INF/xxx/mappings/my-contract.json')
brokenMapping.text = brokenMapping.text.replace('\\\\', '\\')
}
}
verifierStubsJar.dependsOn(fixSadContractIssue)
I guess I need your help. I've migrated to ObjectMapper
to do the deserialization and I've written such a test but I'm not sure if the number of quotes is correct ;) (https://github.com/spring-cloud/spring-cloud-contract/commit/45ede5e1253001746af797cf09392cb406beecf6#diff-921272dc81327196df68e37608cdd717R2084)
@Issue('#667')
def "should not double escape backslashes"() {
given:
Contract groovyDsl = org.springframework.cloud.contract.spec.Contract.make {
priority 1
request {
method 'GET'
urlPath(value(consumer(regex(/\/data\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/)),
producer('/data/444d57b2-e309-4576-83cb-5530ee03106a')))
}
response {
status 200
headers {
header("Content-Type", "application/json;charset=UTF-8")
}
body([
jsonString: '{\\"attribute\\": \\"value\\"}'
])
}
}
when:
String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, groovyDsl), groovyDsl).toWireMockClientStub()
then:
AssertionUtil.assertThatJsonsAreEqual('''
{
"request" : {
"urlPathPattern" : "/data/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}",
"method" : "GET"
},
"response" : {
"status" : 200,
"body" : "{\\"jsonString\\":\\"{\\\\\\"attribute\\\\\\": \\\\\\"value\\\\\\"}\\"}",
"headers" : {
"Content-Type" : "application/json;charset=UTF-8"
},
"transformers" : [ "response-template", "foo-transformer" ]
},
"priority" : 1
}
''', wireMockStub)
and:
stubMappingIsValidWireMockStub(wireMockStub)
}
Can you paste exactly how the WireMock JSON mapping should look like?
This is how I would expect the WireMock JSON mapping to look like:
{
"uuid" : "32912777-64f2-4382-9b55-4dc013a1cb28",
"request" : {
"urlPathPattern" : "/data/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}",
"method" : "GET"
},
"response" : {
"status" : 200,
"body" : "{\"jsonString\":\"{\\\"attribute\\\": \\\"value\\\"}\"}",
"headers" : {
"Content-Type" : "application/json;charset=UTF-8"
}
},
"priority" : 1
}
The above mapping is what is being produced with the workaround we are currently utilizing in our project. Also, your assertion looks correct assuming that assertThatJsonsAreEqual
does not do anything funny with escaping those characters.
Thank you for continuing to look into this! Sorry for not getting back to you sooner.
I gave it another try but still no luck. The problem is that all frameworks seem to treat the text in the json in a bizarre way. If I make some progress I'll update the issue.
Since its an issue with the outputs of the Groovy Json Processing libraries, we can't really do a real fix, but I'm providing a workaround in this PR: https://github.com/spring-cloud/spring-cloud-contract/pull/750 .
We have a service that returns a response with structure similar to the following:
Example contract to support the response above:
The contract above does not produce the expected mapping. It produces the following, which introduces extra backslashes and when running stubrunner leads our clients to receiving improper responses.
It appears the issue is within this method: https://github.com/spring-cloud/spring-cloud-contract/blob/1.2.x/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/BaseWireMockStubStrategy.groovy#L162-L169
From debugging and attempting to change the implementation, it seems the Groovy packages to building json are responsible for introducing the backslashes. I tried using the JsonGenerator, found within Groovy 2.5, but also ran into the same issue. I attempted to use a custom converter without any luck. Another challenge I found when investigating this issue was around testing, because the test suite utilizes an AssertionUtils that also uses Groovy's json parsers/builders for evaluating the correctness of the maps and responses from wiremock.
It does not seem this issue is necessarily at the fault of Groovy, because it seems it is just trying to interpret the json it thinks it sees, even though I want it to be evaluated as and remain a string.
Versions tested in: 1.2.4.RELEASE, 1.2.0.RELEASE, and within the 1.2.x branch
As a temporary workaround, I introduced the following gradle task to manually update the problematic mapping file. This explicitly replaces the extraneous backslashes with the amount I would expect.
Also, thanks a lot to @marcingrzejszczak and his help with troubleshooting this problem with me!