pact-foundation / pact-jvm

JVM version of Pact. Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.
https://docs.pact.io
Apache License 2.0
1.08k stars 478 forks source link

Content-Encoding compression not supported by MockHttpServer.kt #556

Open joelgithub opened 6 years ago

joelgithub commented 6 years ago

When I upgraded to using PactProviderRuleMk2 and as a consequence the new Kotlin MockHttpServer all my consumer tests using POSTS started to fail due to a 500 error from the mock server.

After turning up the log level I found this error:

`2017-10-04 23:05:50,800 ERROR [Thread-2] consumer.BaseMockServer (MockHttpServer.kt:76) - Failed to generate response groovy.json.JsonException: Unable to determine the current character, it is not a string, number, array, or object

The current character read is '?' with an int value of 65533 Unable to determine the current character, it is not a string, number, array, or object line number 1 index number 1 M?1 .^ at groovy.json.internal.JsonParserCharArray.decodeValueInternal(JsonParserCharArray.java:206) at groovy.json.internal.JsonParserCharArray.decodeValue(JsonParserCharArray.java:157) at groovy.json.internal.JsonParserCharArray.decodeFromChars(JsonParserCharArray.java:46) at groovy.json.internal.JsonParserCharArray.parse(JsonParserCharArray.java:384) at groovy.json.internal.BaseJsonParser.parse(BaseJsonParser.java:107) at groovy.json.JsonSlurper.parseText(JsonSlurper.java:205) at au.com.dius.pact.matchers.util.JsonUtils$.parseJsonString(JsonUtils.scala:11) at au.com.dius.pact.matchers.JsonBodyMatcher.matchBody(JsonBodyMatcher.scala:19) at au.com.dius.pact.model.Matching$.matchBody(Matching.scala:159) at au.com.dius.pact.model.RequestMatching$.requestMismatches(RequestMatching.scala:55) at au.com.dius.pact.model.RequestMatching$.compareRequest(RequestMatching.scala:42) at au.com.dius.pact.model.RequestMatching.au$com$dius$pact$model$RequestMatching$$compareToActual$1(RequestMatching.scala:11) at au.com.dius.pact.model.RequestMatching$$anonfun$1.apply(RequestMatching.scala:12) at au.com.dius.pact.model.RequestMatching$$anonfun$1.apply(RequestMatching.scala:12) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234) at scala.collection.Iterator$class.foreach(Iterator.scala:893) at scala.collection.AbstractIterator.foreach(Iterator.scala:1336) at scala.collection.IterableLike$class.foreach(IterableLike.scala:72) at scala.collection.AbstractIterable.foreach(Iterable.scala:54) at scala.collection.TraversableLike$class.map(TraversableLike.scala:234) at scala.collection.AbstractTraversable.map(Traversable.scala:104) at au.com.dius.pact.model.RequestMatching.matchInteraction(RequestMatching.scala:12) at au.com.dius.pact.consumer.BaseMockServer.generatePactResponse(MockHttpServer.kt:96) at au.com.dius.pact.consumer.BaseMockServer.handle(MockHttpServer.kt:72) at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79) at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83) at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:82) at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:675) at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:79) at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647) at sun.net.httpserver.ServerImpl$DefaultExecutor.execute(ServerImpl.java:158) at sun.net.httpserver.ServerImpl$Dispatcher.handle(ServerImpl.java:431) at sun.net.httpserver.ServerImpl$Dispatcher.run(ServerImpl.java:396) at java.lang.Thread.run(Thread.java:745) 20`

The client code that I use to execute the request uses Content-Encoding: gzip to compress the body and it seems that the mock server cannot handle unzipping the body as it arrives. The error disappears when I set the Content-Encoding to "identity" (no compression). I saw in another issue in Pact-JS that this was once an issue for the scala server as well but that it was fixed back in 2014. I suspect it has been reintroduced with the new Kotlin server.

ryandens commented 4 years ago

Left a comment in the #pact-jvm-help slack channel but figured this would be a more appropriate place. I ran into this today and wanted to make sure this is something that we expect to work. I think a possible solution would be to include the Content-Encoding header in lookupBodyMatcher and to use the PlainTextBodyMatcher if it is gzip’d. is this a change you would be open to @uglyog? If so, I can make it. If not did you have different ideas on how you would like to tackle this?

uglyog commented 4 years ago

A gzipped content encoding should be invisible to the matching logic. I'll look at why KTor is not automatically uncompressing the body.