URL Path Pattern Matching in WireMocks (pattern matching) - java

I am using wiremock for REST API testing and I am facing the below problem.
I have the following 2 json requests created.
REQUEST 1:
{
"request": {
"method": "GET",
"urlPattern": "/api/v1/user/2158634832/ishop.*",
"headers": {
"Accept": {
"contains": "application/json"
},
"X-RequestId": {
"matches": ".*"
},
"X-SecurityToken": {
"matches": "valid_secure_token"
}
}
},
"response": {
"status": 200,
"jsonBody": {
"user": {
"ID": "5cc1b131-8858-4870-a7ce-fd37aa805ebf",
"info": [
{
"kid": "2f0ad36a-9f23-427c-9a15-16d240385b87",
"cid": 10962435,
"pid": "V",
"contactid": 11812026,
"created": "2017-04-26T00:08:25.926",
"lastModified": "2017-04-27T00:01:45.047",
}
]
}
},
"headers": {
"Content-Type": "application/json"
}
}
}
My Get Request for the above wiremock looks something like this
**/api/v1/user/2158634832/ishop?ID=9879cfde-e353-4722-a91e-f22d29d8195c**
Request 2 :
{
"request": {
"method": "GET",
"urlPattern": "/api/v1/user/2158634832/ishop/status.*",
"headers": {
"Accept": {
"contains": "application/json"
},
"X-RequestId": {
"matches": ".*"
},
"X-SecurityToken": {
"matches": "valid_secure_token"
}
}
},
"response": {
"status": 200,
"jsonBody": {
"userstatus": {
"id": "5cc1b131-8858-4870-a7ce-fd37aa805ebf",
"type": "ishop",
"status" : "active",
"lastModifiedTime": "2017-04-27T00:01:45.047",
"allowedChange": "true"
}
},
"headers": {
"Content-Type": "application/json"
}
}
}
my Get request for the above looks something like this
/api/v1/user/2158634832/ishop/status?ID=9879cfde-e353-4722-a91e-f22d29d8195c
the problem here is that at times due to the similar URL Pattern for Request 1 and Request 2 what is happening is at times
When I submit a request for Request 1, I am getting the response which is of Request 2.
Can anyone suggest me a workaround how can i fix this ? I am hoping something to do with matches and urlPattern and somehow i can eleminate the status call in the first request i can do it, but not sure how.
any suggestions ?

Since one of your request URLs contains the other, a regex matching the shorter one will also match the longer one. I suspect this is why the shorter one is being matched when you'd prefer the longer one.
I suggest being more specific with your URL matches e.g.
"urlPath": "/api/v1/user/2158634832/ishop" in the first stub and
"urlPath": "/api/v1/user/2158634832/ishop/status" in the second
These will still match despite you not specifying the ID query param. WireMock treats extra headers or query parameters without match parameters as "don't care, match anyway".

Well i fixed it in the following way
Request 1 changed from
"urlPattern": "/api/v1/user/2158634832/ishop.*",
to
"urlPath": "/api/v1/user/2158634832/ishop",
Request 2 changed from
"urlPattern": "/api/v1/user/2158634832/ishop/status.*",
to
"urlPath": "/api/v1/user/2158634832/ishop/status",

A better solution is to use stub priority:
http://wiremock.org/docs/stubbing/#stub-priority
This way you can still use urlPatten
{
"priority" : 2,
"request": {
"method": "GET",
"urlPattern": "/api/v1/user/2158634832/ishop.*",
"headers": {
...
and:
{
"priority" : 1,
"request": {
"method": "GET",
"urlPattern": "/api/v1/user/2158634832/ishop/status.*",
"headers": {
...

Related

wiremock stub with query params not working

I am trying to match this url path -
/abc-service/abc?param1=value1&param2=VALUE_2
This gets matched with a json file as below
{
"request": {
"method": "GET",
"urlPathPattern": "/abc-service/abc(.*)"
},
"response": {
"headers": {
"Content-Type": "application/json"
},
"jsonBody": [],
"status": 200
}
}
But if I remove this and use stubFor() as below, it doesn't work.
WireMock.stubFor(
WireMock.get(WireMock.urlPathMatching("/abc-service/abc(.*)"))
.willReturn(okJson("[]")));
I even tried adding query params as below, that doesn't work either.
final Map<String, StringValuePattern> stringStringValuePatternMap = new HashMap<>();
stringStringValuePatternMap.put("param1", matching("value1"));
stringStringValuePatternMap.put("param2", matching("VALUE2"));
WireMock.stubFor(
WireMock.get(WireMock.urlPathEqualTo("/abc-service/abc"))
.withQueryParams(stringStringValuePatternMap)
.willReturn(
aResponse()
.withStatus(HttpStatus.OK.value())
.withHeader(
HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_JSON_VALUE)));
What am I doing wrong?

AWS Stepfunctions workflow using fargate as worker- how do I get to send the ouput to the next step?

I need to make an api for stepfunctions but the problem is, how do I get the output of the first as input for the next?
Here is what I have so far:
{
"Comment": "Match",
"StartAt": "Search",
"States": {
"Search": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"Cluster": "Search-cluster",
"TaskDefinition": "Search-task",
"Overrides": {
"ContainerOverrides": [
{
"Name": "search",
"Command.$": "$.commands"
}
]
}
},
"Next": "Save"
},
"Save": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"Cluster": "save-cluster",
"TaskDefinition": "save-task",
"Overrides": {
"ContainerOverrides": [
{
"Name": "save",
"Command.$": "$.commands"
}
]
}
},
"Next": "Send"
},
"Send": {
"Type": "Task",
"Resource": "arn:aws:states:::ecs:runTask.sync",
"Parameters": {
"Cluster": "send-cluster",
"TaskDefinition": "send-task",
"Overrides": {
"ContainerOverrides": [
{
"Name": "send",
"Command.$": "$.commands"
}
]
}
},
"End": true
}
}
}
I was facing the same issue and contacted AWS Support. Was told that it is not possible to directly return the result of a Fargate Task like you can do with Lambdas. One of the options is to store the result of your task in a separate DB like DynamoDB and write a Lambda to retrieve the value and update your input JSON with the output from the previous task.
Sidenote: In your ASL, you should look at using ResultPath. The default behaviour is to replace the input node with the output (result). Meaning, if in your input JSON you have values that you would like to use in subsequent states and if you don't specify ResultPath, they'd be lost after the first state. Ref: https://docs.aws.amazon.com/step-functions/latest/dg/input-output-resultpath.html#input-output-resultpath-amend
You don't have to manually mange this. Lambda function's event parameter contains the previous function(s) return output(s).

Dynamic response of Retrofit

My answer Json depends on whether it succeeds or not.
Unsuccessful example:
{
"success": false,
"errors": {
"email": "Could not find email address"
}
}
Successful example:
{
"success": true,
"user": {
"id": 6,
"fname": "XXXXXX",
"lname": "XXXXXX",
"email": "Username#mail.ca",
"roles": [
"Player"
"Coach"
"manager",
"Admin"
]
"date_registered": "2018-03-16T17: 49: 05.000Z"
}
"Token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzaWQiOiJiNjU1MDVkOGJiYzZhMTg1Y2E5MjU5NDlmNTU0OTc0MTgzM2Y2N2NiNjFjYThkMzNkMTUxY2U2MDhjMTBmNTllIiwiaWF0IjoxNTI3MjY3MzEwLCJleHAiOjE1Mjc4NzIxMTB9.p5pTlNjTsr-8N_8B3M5fW3T6PTTrcFo8D77N0WWgA3c"
}
Now, I want to have a POJO for both at the same time with retrofit.
Thank you
Edit : I just solved the problem by changing the form of JSON to :
{
"success": true,
"data": {
"user": {
"id": 6,
"fname": "XXXXXXX",
"lname": "XXXXXXXX",
"email": "Username#mail.ca",
"roles": [
"player",
"coach",
"manager",
"admin"
],
"activation_state": 0,
"date_registered": "2018-03-16T17:49:05.000Z"
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzaWQiOiI0MTFlZmI5Y2ExYzY1ZWFlYzQ4Yzg1ZjJkYTQwOThmODBjOTk1NWNjNjcyOTNlODI5NmI4N2RjZWY5OTMzYzljIiwiaWF0IjoxNTI4NDI0MDA1LCJleHAiOjE1Mjg0MjQ2MDl9.lTsQ867Lk78RV2ruaQFyxUNfm58bHpfzEsZnvKJQMXQ"
},
"errors": {}
}
Thank you for help
You could simply return a String Retrofit, and then parse it manually.
If not, then you have to create a POJO object that contains all variables from both objects.
And then at runtime you check if "success" is true/false, and then try to access the underlying varaibles.
Copy your json response and past http://pojo.sodhanalibrary.com/
Then submit
You will get multiple pojo class with respect to your response ,

swagger io consume json on post

Using swagger editor I created a post call to consume a json object that I want to simply load into a db but when I run the call I get an empty json object.
This is the parameters portion of my json swagger for the post
"parameters": [
{
"in": "body",
"name": "body",
"description": "Add question to collection",
"required": true,
"schema": { "type" : "object", "additionalProperties" : {}
}
}
],
It then creates a "Body" model, but I am not able to see the json that was part of the post:
#javax.annotation.Generated(value = "class io.swagger.codegen.languages.JaxRSServerCodegen", date = "2016-01-22T20:49:03.229Z")
public class Body {
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Body body = (Body) o;
return true;
}
#Override
public int hashCode() {
return Objects.hash();
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class Body {\n");
sb.append("}");
return sb.toString();
}
/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
}
If I remove the text/json from consume and generated my code again and I still see an issue with the body model and being able to pull in json.
If you look at the toString method it shows hard coded values, so I dont see how I can pull the json from the post with the post method only taking in the Body and securitycontext.
I am a little confused about the http accept, when using this swagger snippet:
"post": {
"tags": [
"AskGrey"
],
"summary": "Create new askgrey.com question",
"operationId": "postAskGrey",
"consumes": [
"application/json",
"text/json"
],
"produces": [
"application/json"
],
"parameters": [
{
"in": "body",
"name": "body",
"description": "Add question to collection",
"required": true,
"schema": { "type" : "object", "additionalProperties" : {}
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "object"
}
}
},
"deprecated": false
}
The method generated is the following:
#Override
#POST
#Consumes("application/json")
public Response postAskGrey(Body body,SecurityContext securityContext)
throws NotFoundException {
So based on all this I am not sure how to pull in the post body info, normally I would grab what I need from the http request but with swagger I cant seem to figure out how that gets used.
Before you send your data you should check HTTP ACCEPT method which you set in swagger when you send your data.
There should be Several Accept method which their behaviour distinct from each other when sending data to server.
Thus for application/JSON : Data are part of body.
form-data and x-www-form-urlencoded : Data are part of header.
I haven't adaquate Java experience to give correct code to obtain json into related jSON Object but How to convert HTTP Request Body into JSON Object in Java this answer could help.
Please Check following RFCs for further information
form-data related RFC https://www.rfc-editor.org/rfc/rfc7578
x-www-form-urlencoded related RFC https://datatracker.ietf.org/doc/html/draft-hoehrmann-urlencoded-01
application/JSON related rfc https://www.ietf.org/rfc/rfc4627.txt
UPDATED
Related curl command : I get the command from swagger live demo http://petstore.swagger.io/#/pet paste your json to it and change url, secret key give it a try!
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{
"id": 0,
"category": {
"id": 0,
"name": "string"
},
"name": "doggie",
"photoUrls": [
"string"
],
"tags": [
{
"id": 0,
"name": "string"
}
],
"status": "available"
}' 'http://petstore.swagger.io/v2/pet?api_key=special-key'

Creating JSON RPC requests in Java with parameters which have parameters

The title is a bit messy, but what I'm trying to do is create a JSON RPC request which looks like this:
{
"method":"site/method",
"id":1,
"filter":{
"name":"person"
}
}
I'm having trouble finding a way to do that. I'm using the JSONRPCBase library right now but I'm not sure it's compatible with that. Anybody have any suggestions?
Your request structure is not JSON-RPC compliant.
For JSON-RPC 2.0, try:
{
"jsonrpc":"2.0"
"method": "site/method",
"id": 1,
"params": {
"filter": {
"name": "person"
}
}
}
For JSON-RPC 1.0, the parameters must to be an array, depending on your method arguments, so it can vary depending on your implementation. For example:
{
"method": "site/method",
"id": 1,
"params": [{
"filter": {
"name": "person"
}}]
}
}
or
{
"method": "site/method",
"id": 1,
"params": [{
"name": "person"
}]
}
}

Categories