I'm trying to use Wiremock Request Templating to generate a response from my request body.
I am unable to replace the newlines that are generated from the jsonPath helper, due to an open issue with Handlebars.java, I have had to resort to a strange hack to remove newlines. This works as expected, but when Wiremock attempts to deal with my request I get an error:
"Unexpected character ('f' (code 102)): was expecting comma to separate Object entries\\n at [Source: (String)\\"{\\"id\\":\\"05325128-01d8-406d-8067-4e8b587a8983\\",\\"person\\":{\\"crn\\":\\"C461082\\",\\"name\\":\\"Sherri Durgan IV\\",\\"dateOfBirth\\":\\"2022-08-31\\",\\"sex\\":\\"Female\\",\\"status\\":\\"InCustody\\",\\"nomsNumber\\":\\"NOMS662\\",\\"nationality\\":\\"Honduras\\",\\"religionOrBelief\\":\\"Buddhist\\",\\"prisonName\\":\\"HMP Emmerich Camp\\"},\\"data\\":\\"{ \\"foo\\" : \\"4%:S2lL$3G\\", \\"bar\\" : \\"+O}btr`,yM\\", \\"bike\\" : \\"'dn+#T;7[s\\", \\"a\\" : 65468, \\"b\\" : \\"mpVql:uMx.\\", \\"name\\" : \\"C'i,+5o{8Y\\", \\"prop\\" : \\"%tEqU;an:]\\", \\"basic-information\\" : { \\"sentence-type\\" : { \\"sentenceTyp\\"[truncated 31 chars]; line: 1, column: 286]"
Here's my request:
{
"request": {
"method": "PUT",
"url": "/applications/some-uuid",
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json;charset=UTF-8"
},
"jsonBody": {
"data": "{{{urlEncode (replace(urlEncode (jsonPath request.body '$.data')) '%0A' '') decode=true}}}",
},
"transformers": ["response-template"]
}
}
Any pointers gratefully received!
Related
I tried to POST an array of objects and, as expected, it isn't that easy. In my case I want to insert multiple Transfer Order Lines in the same request.
// Request Body
[
{
"documentNo": "1002",
"itemNo": "1968-S",
"quantity": 3
},
{
"documentNo": "1002",
"itemNo": "1968-S",
"quantity": 113
}
]
// Response
{
"error": {
"code": "BadRequest",
"message": "Invalid Request Body CorrelationId: a2606676-3f8f-4753-aaee-be91a621f070."
}
}
Is it possible to do what I want without sending a request for every Line entity I want to add?
You need to create a structure like this:
url: api/2.0/$batch
Body:
```lang-json
{
"requests":
[
{
"method": "POST",
"id":"R1",
"url": "companies(id)/APIEntitySetName",
"headers":
{
"content-Type": "application/json"
},
"body":
{}
},
{
another line
}
]
}
```
I'm trying to stub a RESTful API. One of the resources return the details when the resource is (indeed) found, or an HTTP 404 (Not Found) when, eventually, there is no resource for the given URL.
This is my simplified stub/mapping:
{
"mappings": [
{
"name": "Retrieve Items",
"request": {
"headers": {
"accept": {
"caseInsensitive": true,
"equalTo": "application/json"
}
},
"method": "GET",
"urlPathPattern": "/api/items/[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}"
},
"response": {
"bodyFileName": "items-api/responses/retrieve/{{ request.pathSegments.[2] }}.json",
"headers": {
"content-type": "application/json"
},
"status": 200
}
}
]
}
Then I have several JSON files (in /home/wiremock/__files/items-api/responses/retrieve/ to match the requests against — but I can't find a way to implement the HTTP 404 (Not Found) scenario:
{
"timestamp": {{ now }},
"status": 404,
"error": "Not Found",
"message": null,
"path": "{{ request.path }}"
}
With this config I get back (the expected, but not useful for my use case) response from WireMock that the file name uuid-sent-in-request.json is not found.
Is there a way to implement this behavior currently?
Tom's answer will work as well. I think the benefits to his solution are that they aren't tied to specific request URLs, but my suggestion is to have a specific mapping for the files that will match with their specific JSON files, and a catch-all mapping for un-matched files. By assigning the requests with JSON responses a higher priority, WireMock will check those first, and if the request does not match any of the values specified in that mapping, will then go on to check if the second mapping matches, and return a 404.
{
"mappings": [
{
"name": "Retrieve Items - Success",
"priority": 1, // arbitrary number lower than the second priority
"request": {
"headers": {
"accept": {
"caseInsensitive": true,
"equalTo": "application/json"
}
},
"method": "GET",
"urlPathPattern": "/api/items/(UUID1|UUID2|UUID3|UUID4)"
},
"response": {
"bodyFileName": "items-api/responses/retrieve/{{ request.pathSegments.[2] }}.json",
"headers": {
"content-type": "application/json"
},
"status": 200
}
},
{
"name": "Retrieve Items - 404 Not Found",
"priority": 5, // arbitrary number that is higher than 1
"request": {
"headers": {
"accept": {
"caseInsensitive": true,
"equalTo": "application/json"
}
},
"method": "GET",
"urlPathPattern": "/api/items/[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}"
},
"response": {
"status": 404
}
}
]
}
Currently you would need to write a ResponseDefinitionTransformer to get the behaviour you're looking for.
It would need to check whether the ResponseDefinition passed in the parameter required a file, then if so check whether the file exists by doing something like:
try {
fileSource.getBinaryFileNamed(bodyFileName).readContents();
} catch (FileNotFoundException e) {
return WireMock.notFound().withBody("custom body");
}
// Otherwise return the unmodified response definition
I have a JSON request as below:
{
"fieldOne": 12345,
"fieldTwo": 1234,
"fieldThree": "2019-12-05T12:32:42.323905",
"fieldFour": "string",
"fieldFive": 5432,
"fieldSix": "string",
"fieldSeven": "string",
"fieldEight": "string"
}
I need to send the complete request JSON object inside a field in response. My Wiremock stub JSON is,
{
"request": {
"method": "POST",
"urlPath": "/endpoint"
},
"response": {
"status": 200,
"jsonBody": {
"request": "{{{request.body}}}", //If I remove quotes here then I get error so I added the quotes
"anotherField": "string"
},
"headers": {
"Content-Type": "application/json;charset=UTF-8"
},
"transformers": ["response-template"]
}
}
How can I send request body in a field in response?.
I now get error:
Illegal unquoted character ((CTRL-CHAR, code 10)):
has to be escaped using backslash to be included in string value\n at [Source: (
Edit:-
I was using wiremock 2.19.0 version which is causing this issue. I upgraded the version to 2.21.0 and now the issue is resolved
But in the response I still have the below problem where the request body is within double quotes which is an invalid JSON. Response:-
{
"request": "{ //Here the double quotes should not be present before curly brace
"fieldOne": 12345,
"fieldTwo": 1234,
"fieldThree": "2019-12-05T12:32:42.323905",
"fieldFour": "string",
"fieldFive": 5432,
"fieldSix": "string",
"fieldSeven": "string",
"fieldEight": "string"
}",
"anotherField": "string"
}
Use body instead of jsonBody. Then the response message(the content present within double quotes in body) can be formatted in whatever way required.
This will work with wiremock 2.19.0 version as well
{
"request": {
"method": "POST",
"urlPath": "/endpoint"
},
"response": {
"status": 200,
"body": "{\"request\": {{{request.body}}}, \"anotherField\": \"string\" }",
"headers": {
"Content-Type": "application/json;charset=UTF-8"
},
"transformers": ["response-template"]
}
}
I am trying to create dynamic mocks using WireMock. I have a situation where if I specify URL like :
http://localhost:8089/api/account/abc#abc.com
then I should receive response like:
{
"account" : "abc#abc.com"
}
In brief, the path param is returned in the response body. I am able to make the request URL generic by using urlPathPattern set to /api/account/([a-z]*) however, I am not sure how should I capture abc#abc.com and return this in the response using regular expressions.
In WireMock the regular expressions can be used to recognize the email format in the Request Matching. For the purpose of this example I used a very crude example. Your production implementation may require a more robust approach.
This request:
http://localhost:8181/api/account/someone#somewhere.net
Is matched by this rule:
{
"request": {
"method": "GET",
"urlPathPattern": "/api/account/([a-z]*#[a-z]*.[a-z]*)"
},
"response": {
"status": 200,
"jsonBody": {
"account": "{{request.path.[2]}}"
},
"transformers": ["response-template"],
"headers": {
"Content-Type": "application/json"
}
}
}
And returns this response:
{
"account": "someone#somewhere.net"
}
It makes use of a Response Template processing functionality in WireMock. The Request Model variables [{{request.path.[2]}}] can be used to obtain sections from the request.
The same can be done using WireMock.Net - Response-Templating
The rule looks like:
{
"Request": {
"Path": {
"Matchers": [
{
"Name": "RegexMatcher",
"Pattern": "^/api/account/([a-z]*#[a-z]*.[a-z]*)$"
}
]
},
"Methods": [
"get"
]
},
"Response": {
"StatusCode": 200,
"BodyAsJson": {
"account": "{{request.PathSegments.[2]}}"
},
"UseTransformer": true,
"Headers": {
"Content-Type": "application/json"
}
}
}
I am trying to provide a MOCK service that takes a headerName and value from the query and returns it as a (dynamic) header with the response. I am using the following response definition:
"response" : {
"status" : 200,
"statusMessage": "OK",
"headers" : {
"Content-Type" : "application/json",
"{{request.query.debugHeader}}" : "{{request.query.debugHeaderValue}}"
},
"jsonBody" : {
"headerSent": "{{request.query.debugHeader}} {{request.query.debugHeaderValue}}"
},
"transformers": ["response-template"],
"base64Body" : ""
}
The header value is correctly evaluated and put into the response template, however I can't get the header name to be taken from the request.
When sending a request:
http://localhost:8090/example?debugHeader=name&debugHeaderValue=value
The result headers I get back are:
HTTP/1.1 200 OK
Content-Type: application/json
{{request.query.debugHeader}}: value
However I want {{request.query.debugHeader}} to be replaced with the actual request parameter value ("name" in the example above).
Any ideas?
Thanks in advance
Alex
This is supported in WireMock.Net.
The request which you need to specify looks like this:
{
"Guid": "90356dba-b36c-469a-a17e-669cd84f1f05",
"Priority": 0,
"Request": {
"Path": {
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "/trans",
"IgnoreCase": false
}
]
},
"Methods": [
"get"
]
},
"Response": {
"StatusCode": 200,
"BodyDestination": "SameAsSource",
"Body": "{\"msg\": \"Hello world : {{request.path}}\" }",
"UseTransformer": true,
"Headers": {
"Content-Type": "application/json",
"Transformed-Postman-Token_{{request.path}}": "token is {{request.headers.Postman-Token}}"
}
}
}
This will add the transformed header Transformed-Postman-Token_{{request.path}} in the response.
Presently this type of variability is not part of the out-of-the-box WireMock application and would have to be custom added. In the WireMock documentation the section Extending WireMock and in particular the part on Transforming Responses.