Wiremock randomValues return as string and not number - wiremock

I'm using the randomValues to return random numbers in my route response.
When I just return it, the value is returned as number. But if I send as a property in the response body, the value is returned as string. Can I return this as a numeric value?
My docker:
version: '3.8'
services:
wiremock:
image: wiremock/wiremock
container_name: wiremock_server
volumes:
- ./wiremock:/home/wiremock
ports:
- 8888:8080
command:
- -verbose
- -global-response-templating
networks:
default:
ipam:
config:
- subnet: 172.30.0.0/16
My Wiremock mapping:
{
"request": {
"urlPattern": "/account/([0-9]*)/balance",
"method": "GET"
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": "{ \"balance\": \"{{randomValue length=9 type='NUMERIC'}}\" }"
}
}
Response received:
{
"balance": "499336545"
}
Response expectec:
{
"balance": 499336545
}
I tried return only the randomValue and works, but I need this inside a body property.

You're quoting the value in your response definition. Just use this:
{
"request": {
"urlPattern": "/account/([0-9]*)/balance",
"method": "GET"
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": "{ \"balance\": {{randomValue length=9 type='NUMERIC'}} }"
}
}

Related

Implement different response with WireMock when no request(s) match

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

WireMock set optional Parameters possibly?

i am very new here. I look up to setup die optional parameters in my Pattern. I have already read the documentary WireMock, but I have not found anything suitable.
My question is, can I query the parameters in any order =?
The next one would is ,y caseInsensitive doesn't work. I dont know why.
{
"priority": 1,
"request": {
"method": "GET",
"headers": {
"Content-Type": {
"equalTo": "application/json",
"caseInsensitive": true
}
},
"urlPattern": "/example\\?name=([a-zA-Z0-9]*)&id=([a-zA-Z0-9]*)"
},
"response": {
"status": 200,
"bodyFileName": "example/test.json"
}
}
As you've written your urlPattern, the query parameter matching is not order indifferent. If you want the query parameters to indifferent, you'd need to do something like...
{
"priority": 1,
"request": {
"method": "GET",
"headers": {
"Content-Type": {
"equalTo": "application/json"
}
},
"urlPath": "/example",
"queryParameters": {
"name": {
"matches": "([a-zA-Z0-9]*)"
},
"id": {
"matches": "([a-zA-Z0-9]*)"
}
}
},
"response": {
"status": 200,
"bodyFileName": "example/test.json"
}
}
The result of the query comes back the same answer.
i want, if i call my request, that the order of Parameters doesn't matter.
example Request: /example?name=max&id=01
example2 Request: /example?id=01&name=max
it should be get same Response.
And it should be case-insensitive.

Envoy External Authorization with OPA - evaluate fail with large JSON body

I have k8s pod running 3 containers: my app, opa, envoy
All my setup follow this guide: https://www.openpolicyagent.org/docs/latest/envoy-authorization/
Everything went well until I have 15kb JSON body.
Checking the OPA container log I see in request.http.body - only about half of JSON there.
{
"decision_id": "",
"error": {},
"input": {
"attributes": {
"destination": {
"address": {
"Address": {
"SocketAddress": {
"PortSpecifier": {
"PortValue": 8000
},
"address": "10.244.8.102"
}
}
}
},
"request": {
"http": {
"body": "only half of JSON body come here",
"headers": {
":authority": "api-service.com",
":method": "PUT",
":path": "/api",
"accept": "application/json",
"content-length": "14822",
"content-type": "application/json",
"x-envoy-decorator-operation": "....",
"x-envoy-internal": "true",
"x-forwarded-for": "10.244.6.0",
"x-forwarded-proto": "https",
"x-istio-attributes": "..."
},
"host": "....com",
"id": "12114967460600931537",
"method": "PUT",
"path": "/api",
"size": 14822
}
},
"source": {
"address": {
"Address": {
"SocketAddress": {
"PortSpecifier": {
"PortValue": 34670
},
"address": "10.244.3.164"
}
}
}
}
},
"parsed_path": [
"api"
],
"parsed_query": {}
},
"level": "info",
"msg": "Decision Log",
"query": "data.app.allow",
"type": "openpolicyagent.org/decision_logs"
}
I tried increase with_request_body.
http_filters:
- name: envoy.ext_authz
config:
with_request_body:
max_request_bytes: 819200
allow_partial_message: true
failure_mode_allow: false
Is there any other thing I missed?
Thanks a lot for your help
Are there any errors in the Envoy logs ?
What is the data that you are trying to send ? Does it need to be part of OPA's input document or can you leverage OPA's bundle feature.
I finally make it works by increasing max_request_bytes.
name: envoy.ext_authz
config:
with_request_body:
max_request_bytes: 819200
I configured this before in configmap but forgot to restart the pod. Just redeploy everything with new max_request_bytes - it's ok now
Reference: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/buffer/v3/buffer.proto.html?highlight=max_request_bytes
Thank you all

Wiremock standalone dynamic response array of objects is not working with bodyPatterns and matchesJsonPath

I am using wiremock to stubbing the requests. I have created a json file to get a response:
{
"request": {
"method": "POST",
"urlPath": "/nested/transform",
"bodyPatterns": [
{
"matchesJsonPath": "$.name.[0].first"
},
{
"matchesJsonPath": "$.name.[1].first"
}
]
},
"response": {
"status": 200,
"body": "{\"firstName\": \"$(name.[0].first)\", \"lastName\": \"$(name.[1].first)\"}",
"headers": {
"Content-Type": "application/json"
},
"transformers": ["body-transformer"]
}
}
My request and response are as below:
Request
{
"name": [
{
"first": "Vijay"
},
{
"first": "Sagar"
}
]
}
Here I receive very beard response and it is not parsed as I want.
Response which is not my expected result:
{
"firstName": "[{first=Vijay}, {first=Sagar}]",
"lastName": "[{first=Vijay}, {first=Sagar}]"
}
Expected result is: I'm willing to receive the following response based on above request and stubbed json:
{"firstName": "Vijay","lastName": "Sagar"}
How can I get the expected result as I tried a lot but was unable to match response parameters?
When working with a JSON response, I prefer to use the bodyFileName as this that escaping isn't necessary.
__files/nested_json_template.json
{
"firstName": "{{jsonPath request.body '$.name.[0].first'}}",
"lastName": "{{jsonPath request.body '$.name.[1].first'}}"
}
mappings/nested_json_mapping.json
{
"request": {
"method": "POST",
"urlPath": "/nested/transform",
"bodyPatterns": [
{
"matchesJsonPath": "$.name.[0].first"
},
{
"matchesJsonPath": "$.name.[1].first"
}
]
},
"response": {
"status": 200,
"bodyFileName": "nested_json.json",
"headers": {
"Content-Type": "application/json"
},
"transformers": ["response-template"]
}
}

WireMock not mapping request by body contains

My http request send to this: https://myhost.com/ap
My http request with body :
{
"Body": {
"CommandName": "GetApplicationProfile"
},
"Header": {
"Command": "GetApplicationProfile",
}
}
I want to mapping this request by WireMock.
Here WireMock's mapping file.
{
"request": {
"url": "/my_host/ap",
"bodyPatterns": [
{
"contains": "GetApplicationProfile"
}
]
},
"response": {
"headers": {
"Content-Type": "application/json"
},
"status": 200,
"bodyFileName": "get_profile.json"
}
}
I start wireMock like this:
java -jar wiremock-standalone-2.18.0.jar --port 8080 --enable-browser-proxying -verbose
But when request was started the WireMock not map this request. Nothing happened.
why?
The problem you're having is that you shouldn't have the hostname in the url part. This is not needed. Your example message can be sent and will be matched using the following rule.
{
"request": {
"url": "/app",
"bodyPatterns": [
{
"contains": "GetApplicationProfile"
}
]
},
"response": {
"headers": {
"Content-Type": "application/json"
},
"status": 200,
"body": "ddd"
}
}
The URL should not contain the host name. It should only contain the resource path.
The url format should start with "/" e.g. /https://myhost.com/ap.
Now if u r trying this on localhost then the URL should be localhost:<port>/https://myhost.com/ap.
The file should be present at src/test/resources/__files
If not it will give error file not present.
I see 2 issues here:
1. you need to remove the host name from the url in the mapping file.
2. your request is HTTPS which means you need to start your wiremock port with https: --https-port 8080 or you change your request to HTTP