multiple accept values in request for wiremock - json

I'm attempting to write a mock for my api.
To test it correctly I need a request whick allows application/json and / to be accepted.
Which sould work in HTML like this
application/json, */*
When I use this in my wiremock mapping json file, i recieve errors, or with minor changes just "not matching" response.
My Json is build like this
"request": {
"urlPathPattern": "/publish",
"method": "POST",
"headers": {
"Accept": {
"contains": "application/json, */*"
}
},
"bodyPatterns": []
}
I couldn't find any solution, neither on the wiremock docs nor with the help of google, but maybe my description of the problem was just not showing the results I would have needed.
Can anyone enlighten me?
with best regards

As I understand your problem, you need to accept both application/json and */* as Accept header values. I'm assuming that the case where you'd receive something matching */* would interpret those * as wildcards, so some/type would match. In this case, you just want to make sure that the Accept header has some value.
If that is the case, I'd recommend you use matches to do regex matching on the header.
"request": {
"urlPathPattern": "/publish",
"method": "POST",
"headers": {
"Accept": {
"matches": ".*\/.*"
}
},
"bodyPatterns": []
}
If you instead need to match exactly on either application/json or */*, you'd need to do something like...
"request": {
"urlPathPattern": "/publish",
"method": "POST",
"headers": {
"Accept": {
"matches": "(application\/json|\*\/\*)"
}
},
"bodyPatterns": []
}

Related

Is there a way to have a wildcard in the bodyFileName for a wiremock stub mapping?

My issue is that I want to give my response file names a more meaningful name but to do this I need to be able to match on any text following the id. Here is my current mapping:
{
"priority": 10,
"request": {
"urlPattern": "/api/v1/customer\\?Id=(.*)&IdType=(.*)&AdditionalInformation=(.*)",
"method": "GET"
},
"response": {
"transformers": [
"dynamic-mapping-transformer"
],
"status": 200,
"headers": {
"Content-Type": "application/json",
"Correlation-ID": "{{request.headers.Correlation-ID}}"
},
"transformerParameters": {
"bodyFileName": "{{request.query.Id}}",
"fileDirectory": "getWorkplaceDetails",
"extension": "json",
"encodeName": false,
"caseInsensitive": true
}
}
}
And the naming convention for the response files should be something along the lines of "Id_foo_bar" but "foo" and "bar" are not available in the request so there is no way for me to know them before the response is posted. I would like to use a wild card in the bodyFileName value to match on anything after the Id and was wondering if anyone knew a way to do this?
EDIT 1
I forgot to mention that the mapping needs to accept multiple files with different names which is why I am looking to use a wild card instead of a static file name.

event.body in lambda function is not an object even though application/json header exists

I have an API Gateway / lambda function set up with a LAMBDA_PROXY integration.
I have a POST resource which is sending a JSON object in the body like the following:
{
"version": 123,
"attributes": [
{
"id": 1123,
"type": "integer",
"defaultValue": 88
}
]
}
The POST request is sent with a Content-Type: application/json header.
I expect the lambda function to receive event.body as an object so that I will be able to reference the object like this:
const version = event.body.version;
In fact, this does not work and I am forced to run a JSON.parse() on event.body.
At first I was thinking that the content-type header was not getting to the lambda but then I printed to the log event.headers and the header is in fact there:
{
"Accept": "*/*",
"content-type": "application/json",
"Host": "jfpvip409c.execute-api.eu-west-1.amazonaws.com",
"User-Agent": "curl/7.65.0",
"X-Amzn-Trace-Id": "Root=1-5fe9940a-3f3634ce4ccd26f5211c21d1",
"X-Forwarded-For": "192.118.35.111",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
}
Can somebody please help me understand why this is the case ?
Thanks in advance
nsteiner

How to encode special characters in Wiremock request body?

I'm using Wiremock server to mock responses and using JSON format to mock responses.
{
"request":
{
"url": "/token",
"method": "POST",
"bodyPatterns" : [{
"contains": "username=test_user#gmail.com&password=passwordtest_security_token"
}]
},
"response":
{
"status": 200,
"headers":
{
"Content-Type" : "application/json"
},
"jsonBody": {"message": "ok"}
}
This is not working as the '#' in the email is not encoded. I need to pass "test_user%40gmail" for the request to work.
Here the change is only at one place. But for other mocks, request bodies have many special characters**(#,%*\n\s)**. Is there any way to handle the encoding part in the Wiremock.
Also, is there way to encode the string in url?
In the above example there is an accolade missing which prevents is from loading in WireMock. The below example is complete:
{
"request": {
"url": "/token",
"method": "POST",
"bodyPatterns": [{
"contains": "username=test_user#gmail.com&password=passwordtest_security_token"
}
]
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"jsonBody": {
"message": "ok"
}
}
}
In your question you highlighted that you need to use %40 instead of #. I have been unable to replicate this scenario. As I'm unsure if you're posting through a form, or raw string.
In the case that you use a regular Form Data option this results in failure to match.
But sending it as a raw body the result is quite the opposite. The example behaves exactly as you would described it should. Below is a screenshot of my Postman result:

Describe http request/reply in json

I have a case where I have to serialize a N number of http requests, perform the requests in parallel, and describe the response in the same json. To do this in json is pretty easy obviously, I could do something like:
[
{
"request": {
"uri": "http://something",
"headers": [
{
"Content-Type": "application/json"
}
],
"body": ".. snip .. you get the idea",
"other-stuff": ""
},
"response": {
// something along the lines of the request structure to be filled in after the request completed
}
},
// second request/response here, and so on.
]
But while I could make this format up myself, I feel this problem is (very) likely solved before, and there should be some sort of json standard floating around that does this. Can't find it though. Have you encountered this somewhere?

Loopback: Send request with json data using REST connector

I would like to fetch data from 3rd party REST Service in my Loopback Application. In order to fetch data from Service I need to authenticate first with login and password. I can test service using curl:
curl -b cookies -c cookies -X POST -d '{"auth": {"username":"MyUser","password":"Secret"}}' 'http://api.awesome.service.com/'
That works great. Tcpdump shows request like that:
Host: http://api.awesome.service.com/
User-Agent: curl/7.47.0
Accept: */*
Cookie: HBFAPI_SESSID=hbapi%3A197887%3A58a3028d12c36%3Anym2
Content-Length: 58
Content-Type: application/x-www-form-urlencoded
{"auth":{"username":"MyUser","password":"Secret"}}
So, I've created datasource first:
{
"awesome_datasource": {
"name": "awesome_datasource",
"baseURL": "https://api.awesome.service.com/",
"crud": false,
"connector": "rest",
"operations": [{
"template": {
"method": "POST",
"url": "http://api.awesome.service.com/auth",
"form":{
"auth": {
"username": "{username:string}",
"password": "{password:string}"
}
},
"json": true
},
"functions":{
"login": ["username", "password"]
}
}]
}
}
I tested that using explorer. No matter what I do, I can't get data in request body formatted as json. With or without json option result is this same, which in tcpdump is:
host: api.awesome.service.com
content-type: application/x-www-form-urlencoded
accept: application/json
content-length: 66
Connection: close
auth%5Busername%5D=MyUser&auth%5Bpassword%5D=Secret
I've tried pass parameters as 'query', 'form' or 'data' option. Also checked various header content-type options, but no luck so far.
Model is simple without parameters. Base model is 'Model' (no User, because I want to keep it simple as possible)
I was able to find this thread, but it wasn't much help:
https://github.com/strongloop/loopback-connector-rest/pull/12
Any advice will be much appreciated.
Well all you have to do is to use json instead of form there:
{
"awesome_datasource": {
"name": "awesome_datasource",
"baseURL": "https://api.awesome.service.com/",
"crud": false,
"connector": "rest",
"operations": [{
"template": {
"method": "POST",
"url": "http://api.awesome.service.com/auth",
"json": {
"auth": {
"username": "{username:string}",
"password": "{password:string}"
}
}
},
"functions":{
"login": ["username", "password"]
}
}]
}
}
REST connector tries to mimic request module as much as possible. Basically body, json, form and query(qs in request) do the same thing as the request options but they also accept template strings. Here's the documentation from request with a little modification:
query(qs in request) - object containing querystring values to be appended to the uri
body - entity body for PATCH, POST and PUT requests. Must be a Buffer, String or ReadStream. If json is true, then body must be a JSON-serializable object.
form - when passed an object or a querystring, this sets body to a querystring representation of value, and adds Content-type: application/x-www-form-urlencoded header. When passed no options, a FormData instance is returned (and is piped to request). See "Forms" section above.
json - sets body to JSON representation of value and adds Content-type: application/json header. Additionally, parses the response body as JSON.