mock-server / mockserver

MockServer enables easy mocking of any system you integrate with via HTTP or HTTPS with clients written in Java, JavaScript and Ruby. MockServer also includes a proxy that introspects all proxied traffic including encrypted SSL traffic and supports Port Forwarding, Web Proxying (i.e. HTTP proxy), HTTPS Tunneling Proxying (using HTTP CONNECT) and SOCKS Proxying (i.e. dynamic port forwarding).
http://mock-server.com
Apache License 2.0
4.61k stars 1.08k forks source link

Thread safety issue with Velocity templates using request scoped tools like $json #1773

Open dom54 opened 1 year ago

dom54 commented 1 year ago

Describe the issue

We are seeing issues with incorrect response being returned from mockserver

What you are trying to do

We have some velocity templates setup that we are passing in via JSON. We are seeing incorrect values from mockserver which are confirmed by the logs. As you can see this should be impossible based on the template logged.

2023-07-17 19:23:48 5.15.0 INFO 1080 generated output:

  {"statusCode":200,"headers":{"Content-Type":["application/json"]},"body":"{ \"accessUrl\": \"0b77c7cc-c99e-4dfd-99e3-8a7d4646e503\"}"}

 from template:

  {'statusCode': 200, 'headers': {'Content-Type': ["application/json"]}, 'body': '{ "accessUrl": "$json.parse($!request.body).externalReference"}'}

 for request:

  {
    "method" : "POST",
    "path" : "/v1/generate/url",
    "headers" : {
      "User-Agent" : [ "Java/1.8.0_265" ],
      "Pragma" : [ "no-cache" ],
      "Host" : [ "teamcity-agent-4-mockserver:1080" ],
      "Content-Type" : [ "application/json" ],
      "Content-Length" : [ "177" ],
      "Connection" : [ "keep-alive" ],
      "Cache-Control" : [ "no-cache" ],
      "Authorization" : [ "Bearer redacted" ],
      "Accept" : [ "application/xml, text/xml, application/json, application/*+xml, application/*+json" ]
    },
    "keepAlive" : true,
    "secure" : false,
    "protocol" : "HTTP_1_1",
    "localAddress" : "redacted:1080",
    "remoteAddress" : "redacted0:36074",
    "body" : {
      "externalReference" : "2ef7a3b3-bea7-4708-8306-fb4b25ffcfa9",
      "firstName" : "Checkmy",
      "lastName" : "Bank",
      "redirectUrl" : "http://teamcity-agent-4-fmo-as:8080/WebApp/direct/index.html"
    }
  }

MockServer version 5.15.0

To Reproduce Tricky... not sure yet.

  1. How you are running MockServer (i.e maven plugin, docker, etc) Docker

  2. Code you used to create expectations TBC

  3. What error you saw Impossible output given input, shown in logs

Expected behaviour Consistent output based on template

MockServer Log Log output, as INFO level (or lower) As above

dom54 commented 1 year ago

The accessUrl in the output shows the ID of another request in the same second (""{ \"accessUrl\": \"0b77c7cc-c99e-4dfd-99e3-8a7d4646e503\"}"}"

Having looked through the code, I just cant see how this could be happening right now

dom54 commented 1 year ago

The velocity code is not threadsafe (Mockserver is misusing it, or its a bug, not sure yet).

dom54 commented 1 year ago

Mockserver is not using Velocity in a threadsafe way, as ToolContext is not threadsafe when using request scoped tools.

https://github.com/mock-server/mockserver/pull/1774

juan-antonio-alba-db commented 1 year ago

Hello, I have being facing this error since 7 days ago, and I have just migrated to use JAVASCRIPT template which works properly.

I have been reproducing the issue by using locust against the mockserver With the following template [ { "httpRequest": { "method": "POST", "path": "/cars" }, "httpResponseTemplate": { "template": "#set($jsonBody = $json.parse($request.body))\n#if($jsonBody.json)\n #set($ids = $jsonBody.json.carIds)\n#else\n #set($ids = $jsonBody.carIds)\n#end\n{\n \"statusCode\": 200,\n \"body\": {\n \"cars\": [\n #foreach($id in $ids)\n {\"carId\": \"$id\",\n \"businessTransactionExecutable\": true\n } #if($foreach.hasNext),#end\n #end]}}", "templateType": "VELOCITY" } } ]

I hope it helps

Regards

dom54 commented 1 year ago

Funnily enough, I have migrated away from JAVASCRIPT before facing this issue, because it is no longer supported properly.

https://github.com/mock-server/mockserver/issues/1771

The Docker image uses JDK17 where Nashorn is not present (it is deprecated)