Virtual service: reading the request headers in code injected into a response
Hi, SmartBear Customer Care sent me here when they couldn't find an answer for me.
We have set up a virtual service with ReadyAPI that's working well when we run it locally, and it's also working when we run it in a virtserver and have only one user accessing it. The service is keeping a small amount of state to simulate changes to a database. We used a simple load test to show that our service has a race condition that can cause it to return the wrong data up to 10% of the time, so we can't recommend rolling out the service to our broader organization yet.
We're trying to support the stateful service for multiple users by reading a "clientId" header in the request and dynamically generating the name of a property in order to look up its current value that can be unique for each client (the value is set in a different request). What's working for a single user now is that we have script code that sets the property, and then we inject this code into the response to return the per-client property value:
mode="${#MockService#${#MockService#clientId}-mode}"
This fails our load test probably because the time between running the script code to set the (global) property and running the code in the response gives an opportunity for another request to overwrite the property value.
To be clear: we have script code for this response (not shown here) that sets the property, and to inject a value into the response, we also have the code above directly in the response that reads both the clientId and the unique property value for the client. The scripting environment and the syntax for code in the response is somewhat different than in the script, and we have found very little documentation on what we can do with this code in the response.
One fix we tried didn't work, where we tried to access objects that are available in script code:
mode="${=def clientId = mockRequest.getRequestHeaders().get("myClientId").get(0); context.expand("#MockService#" + clientId + "-mode")}'"
Turns out we can't access mockRequest in the response:
mode="No such property: mockRequest for class: Script36'"
I know we can store these per-client properties in headers instead of properties, but for that to work, we still have to figure out how to read the request headers in the response code. Anyone have ideas for a solution?