Hello team! I'm trying to use templating inside th...
# wiremock-java
g
Hello team! I'm trying to use templating inside the response transformerParameters. I've read the code on how Webhook does this and tried to replicate it, but I was unable to achieve the expected outcome, it comes as null. My stub is as it follows:
Copy code
{
  "request": {
    "method": "GET",
    "urlPattern": "/api/v1/transactions/approval-delegate-rules/.*"
  },
  "response": {
    "transformers": [
      "response-transformer"
    ],
    "transformerParameters": {
      "url": "/ApprovalDelegateRule?id=eq.{{request.pathSegments.[4]}}"
    }
  }
}
Could anyone help me on this?
l
Could you maybe explain what it is you are trying to achieve? The reason I ask is because the response in your stub doesn’t have a status or a body or anything other than the transformer parameters so I am not sure what the purpose of them are.
g
I am using Wiremock as a "proxy" which takes the user calls and redirects them to PostgREST, a rest layer on top of Postgres
Another option for what I want to do would be using Webhooks, but I also faced a issue on this because I could not make Webhook work synchronously with my custom ResponseDefinitionTransformer
l
I might be missing something but the stub you posted above isn't a proxy stub. Are you running as a browser proxy?
g
yea sorry, I implemented my own code to act as the proxy
l
OK, so what role does wiremock play in this. Are you expecting a specific transformed response to a specific request ?
g
I start a Wiremock standalone server which will have many stubs similar to the one that I sent, and each of these stubs will be using my custom ResponseDefinitionTransformer extension (which acts as a proxy) to make a HTTP request to my DB REST application and return this DB response to the original call
What I want is to be able to use Wiremock's templating ability, so that I don't face solved problems when building my "proxied" requests. As far as could tell, I think I can solve it in two ways, either using Templating inside my transformerParameters, or, using a custom implementation of the Webhook extension to help me with this (the problem with the latter one is that I was not able to return the Webhook response to the original call)
l
Is it the whole
url
parameter that is null in the parameters when it reaches your transformer ?
g
no, it's only the thing inside the mustache
{{request.pathSegments.[4]}} -> null
I can share with you my Template snippet if u want
l
Have you tried without the
[]
? -
request.pathSegments.4
g
yes, same outcome
l
Have you successfully used handlebars in a transformer parameter in other stubs?
g
nope, no luck also, the only place I could make it work was inside the webhook serveEventListener in my stub, like so:
Copy code
"serveEventListeners": [
  {
    "name": "webhook",
    "parameters": {
      "method": "GET",
      "url": "/ApprovalDelegateRule?id=eq.{{request.pathSegments.[4]}}",
      "body": "{ \"result\": \"SUCCESS\" }"
    }
  },
]
l
I need to take a look at the code to check to see if templating is supported in the transformer parameters
It definitely is in the webhook listener
g
yea, I don't think it is supported
I took a look at the code very briefly
🙌 1
But I don't have the technical knowledge to really know this
l
I can't see anywhere in the code that applied templating to the parameters unfortunately. Could you do this by making multiple specific stubs so you don't need to extract the path segment? It would be a little more verbose but if there are not too many options then it might work?
g
aw 😞
that won't work for me, because the wildcard in the path is to match UUIDs and such, so that the calls are similar to a real environment
A friend and I are thinking about forking the wiremock project and working on top of the current Webhook code, so that we're able to make it not async and use it to attend our needs
but thanks a lot man, u're awesome!!
l
I am just wondering if this could be done with an extension ?
You are very welcome
g
yea, I also thought extensions were the way to go, I have implemented some of my own, but I was not able to make a serveEventListener extension return a specific response to the original call
l
Is the transformation code in your custom transformer pretty generic ?
g
yes
l
This is tricky anyway you look at it. Just thinking out loud but I wonder if you could use the template engine directly in your response transformer. Not sure if that is possible but if you could then you could perform the transformation of the parameter yourself inside the transformer
g
I tried to use the template engine directly, It didn't work sadly. I searched through Wiremock's code to find where it was implemented on webhooks and copied the code
but yea, it's a tricky problem
l
Was there something specific that didn't work with the template engine. I have never tried it so was curious
Because you are only using the request object in the template engine would this work:
Copy code
@Override
    public ResponseDefinition transform(ServeEvent serveEvent) {
      TemplateEngine engine = TemplateEngine.defaultTemplateEngine();
      final Map<String, Object> model =
              new HashMap<>(engine.buildModelForRequest(serveEvent));

      Parameters parameters = serveEvent.getTransformerParameters();
      String url = parameters.getString("url");
      String transformedUrl = engine.getUncachedTemplate(url).apply(model);
      
      return new ResponseDefinitionBuilder()
              .withStatus(200)
              .withBody(transformedUrl)
              .build();
    }
I have just written a test inside the wiremock codebase and it does seem to work OK. I passed in a
url
parameter of
<http://example.com/{{request.id}}>
and the response I got back from the transformer was
<http://example.com/a7b5f288-adf9-412f-8474-bb648d48317a>
Just update the test a little to make it more like your example - mocked this url
/api/v1/transactions/approval-delegate-rules/.*
, with this template parameter
<http://example.com/{{request.pathSegments.4}}>
and made a request to
/api/v1/transactions/approval-delegate-rules/12345
I got back
<http://example.com/12345>
g
ohhh
I was missing this line:
Copy code
final Map<String, Object> model =
              new HashMap<>(engine.buildModelForRequest(serveEvent));
I'll try it out and get back to ya
l
Awesome
g
IT WORKED, AWESOME DUDE, THANK YOU SO MUCH
!!!!!
l
Excellent. Glad it worked.
🙌 1