Wiremock Standalone: dynamic response based on current day - wiremock

I would like to mock API that returns the state of third party service. And there are a lot of them.
So, to cover our logic related to those statuses, I would like my mock to return different statuses based on the day of the week when it is called.
It will allow to test all statuses within 1 week.
But it should be predefined as in tests I should know what status was returned to our back end to calculate expected results. So, bare. randomizer won't work.
The JSON example is the following
...
"state": {
"state_message": ,
"life_cycle_state": TERMINATED,
"result_state": "SUCCESS",
"user_cancelled_or_timedout": false
},
...
So, that life_cycle_state should be changing
I was trying with response-template and contains functions.
Like this:
"life_cycle_state": {{#contains "Sat Sun Mon" '{{now timezone="UTC" format="EEE"}}'}}"RUNNING"{{/contains}},
But it looks like wire mock does not understand that now is a function and treats it as string
How could I achieve expected behavior?

Related

REST: Is it considered restful if API sends back two type of response?

We have stock website and we help buyers connect with the sellers. We are creating API to let buyers push their contact details and get back the seller details. This is transaction and get logged in our database. We have created following API:
The request is POST, the URL looks like:
/api/leads
The request body looks like:
{
"buyermobile": "9999999999",
"stockid": "123"
}
The response looks like:
{
"sellermobile" : "8888888888",
"selleraddress": "123 avenue park"
}
We have a new requirement, i.e. we need to send back PDF URL (instead of "sellermobile" & "selleraddress"). This PDF URL would contain the seller details in case it comes from one of our client.
We have modified the same API, now the request body looks like:
{
"buyermobile": "9999999999",
"stockid": "123",
"ispdf": true
}
The response looks like:
{
"sellerdetailspdf" : "https://example.com/sellerdetails-1.pdf",
}
Is it RESTFUL to do this? OR we should create separate API for getting response as PDF?
I wouldn't approach it this way. What happens when you need to add XLS? Do you add "isxls" to the request too?
Things I'd consider:
Use a mime type for content negotiation. Post the same request, and specify in the Accept header what you expect back - JSON, PDF, etc. You're then actually getting the report instead of a link to the report, which may or may not be better.
- or -
Include a link in the typical lead response.
{
"sellermobile" : "8888888888",
"selleraddress": "123 avenue park",
"_links": {
"seller-details-pdf": "https://example.com/sellerdetails-1.pdf"
}
}
- or -
Support a query parameter that specifies the type in the response.
- or -
Have a single property that specifies the type in the response, rather than a boolean. Much cleaner to extend when you add new response types.
The first two options have the bonus that you don't require clients to handle multiple response types to a single request. That's not forbidden by any spec, but it's annoying for clients. Try not to annoy the people who you want to pay you. :)
Again the implementation looks good to me, however you could potentially look at breaking the return of the PDF URL to another endpoint maybe something like api/lead/pdf that way your request body is the same for api/lead and all subsequent endpoints under /lead. Allowing your routes and other code to handle small portioned tasks instead of having a route that handles multiple flags and multiple code routes.
That looks good to me - the same type of input should give the same type of response but in your case you have two different types of input - one with the "ispdf" flag and one without. So it's consistent to responds with two different types of response, one with the PDF link and one without.
That's still something you'll want to document but basically it's a correct implementation.

How to design calculation API in RESTFul way?

I'm trying to design an API to calculate a result based on inputs.
Real business:
The API compares two securities portfolios (source and target) and return the orders, the consumer gets the orders, so he/she can then places those orders to adjust portfolio from source to target.
If this is hard to be understood, then here's a similar scenario:
The API compare two text, then return the difference of the 2 texts.
It is a little bit different from the classic CRUD, because the inputs and output are different resources
My first thought is like this:
POST /api/difference
{
'source': { ... },
'target': { ... }
}
But, it will be conflict with the classic payload:
POST /api/difference
{
'lineNumber': ...,
'isAdded': ...
}
Questions:
Should I use a media-type to distinguish the the input payloads? What a 'resource' should be in this case?
What should the API look like if I also want to place the orders (or apply the text diff) in the same time when the API is called?
Iam not sure whether I understand your problem correctly, but in general it
depends on whether the resources are already persisted in the system. In case
both resources are already available in the system I would simply build an URI
like /portfolio/{source_id}/difference/{target_id} which returns the diff
result. If only the source exists I would probably use something like:
POST /portfolio/{source_id}/difference
{target}
If both resources are not available I would probably consider to first persist
such a resource and make then the comparison.
If I understood you correctly, there already exists the resource POST /api/difference and hence you are looking to change MIME type. Instead, why don't you go with the first approach and change the resource name? For example,
POST /api/compare
{
'source': { ... },
'target': { ... }
}

Getting active time from Google Fit Rest API

I am struggling with matching the "active time" returned by Fit REST API with reality.
As an example - on 12/14 I had two walks, about 45 minutes each. The api returns one of them as type 7 ("walking" - right!) and another one as type 0 (in vehicle - wrong!). However, Fit app shows both as "walking", so it apparently uses a different data source.
I checked some other days and on these days, the session with type 0 is indeed a valid "in vehicle" session.
I tried all aggregated data sources that return com.google.activity.segment. Most of them are empty, I've found data only in merge_activity_segments and platform_activity_segments (and they seem to be identical).
Google's docs have a caveat about delay in data sync, but they never specified how long this delay is. The data I am looking at is about 24 hours old - if their sync is that slow, then this API is more or less unusable.
I am using the following POST to https://www.googleapis.com/fitness/v1/users/me/dataset:aggregate
{
"aggregateBy": [
{
"dataSourceId": "derived:com.google.activity.segment:com.google.android.gms:merge_activity_segments"
}
],
"endTimeMillis": "1481788800000",
"startTimeMillis": "1481702400000",
"bucketByTime": {
"period": {
"timeZoneId": "America/Los_Angeles",
"type": "day",
"value": 1
}
}
}
For reference - activity types: https://developers.google.com/fit/rest/v1/reference/activity-types
Has anyone been able to retrieve activity time from Fit's REST API that is correct? Any suggestions?
By the way, steps and calories seem to work fine - just aggregate the following datasets:derived:com.google.calories.expended:com.google.android.gms:merge_calories_expended and derived:com.google.step_count.delta:com.google.android.gms:estimated_steps
A side note - it is probably the worst documented API from a major company I have seen.

Creating Group categories - D2L Valence

I am attempting to dynamically create a group category with in a course using the following service:
[/d2l/api/lp/(version)/(orgUnitId)/groupcategories/ \[POST\]][1]
The following is the GroupData (Group.GroupData in Create form) JSON block that I am sending to this service:
{
"Name": "New Group Category",
"Description": {
"Content": "",
"Type": "HTML"
},
"EnrollmentStyle": 0,
"EnrollmentQuantity": null,
"AutoEnroll": false,
"RandomizeEnrollments": false,
"NumberOfGroups": 5,
"MaxUsersPerGroup": null
}
I am making the call with the user context of a administrative "Utility" account. I have 2 test courses, both of which I have confirmed I am able create the category through the web interface using this utility account.
My problem is I am having mixed results depending on the course that I try to create the category in. In one course the course returns 200-OK, in the other it returns 403-Forbidden.
Here are the (simplified) requests :
Call 1
/d2l/api/lp/1.4/350110/groupcategories/
Result: 403-Forbidden
Call 2
/d2l/api/lp/1.4/19988/groupcategories/
Result: 200-OK
The only difference is the OrgUnitID. Version, JSON, and user context are all the same, yet I'm getting 2 different results. I have tried with several other courses and again, I have success in some but not all; always receiving a 403 as the error.
After some investigation, I believe I have found 2 distinct differences between courses that are successful and those that return 403.
Courses created just before April 2012 are successful, anything afterwards fail
Courses with a 5 digit Org Unit ID are successful, anything with 6 digits seems to fail.
So my thoughts are we either applied a patch late march / early April of 2012 which somehow changed how courses are flagged on creation, OR somehow only 5 digits (or less?) Org IDs are being accepted by the service.
I'm hoping someone could provide some insight or verify they have no issue with 6+ digit OUIDs and group category creation.
Further reviewing the documentation on API Responses - Disposition and error handling I realized that there are 3 possible cases for a 403 response:
Response body contains Timestamp out of range
Response body contains Invalid Token
application or calling user context does not have the permissions required for the attempted action
Given this, I took a closer look at the response header and realized the issue was actually #2 "Invalid Token", not #3 as I was assuming.
Investigating my code further it seems the user defined SHA256 function I was using was producing an incorrect HASH/Signature when the data being hashed was exactly 55 characters long (yes I realize how crazy this sounds). The temporary work around is to pad my OrgIDs with leading zeros, so my request would actually look something similar too:
/d2l/api/lp/1.4/00350110/groupcategories/
Thankfully, this seems to work, and is acceptable for the immediate future. Long term solution will be to replace my SHA256 function with something more reliable.
I am using Colfusion 7MX for my development, which does not have a native SHA256 Hash function, hence the use of the user defined function.

Elasticsearch query design via RESTful API

I'm trying to build a query that first lets me get a list of followers that are following a user, second it should take that list and then check to see if they are 'online'.
I have two 'indexes' or endpoints /channel and /following.
The channel endpoint JSON object looks like this (parts abbreviated)
{ channel: {"username":"username1", ... , "online":"true" } }
The following endpoint object looks a bit like this
{ following : {"username1":{"username2":"username2", "username3":"username3"} }
if I run a simple query /following/_search I get back hits like...
{
"_index": "following",
"_type": "following",
"_id": "_Liso_",
"_score": 1,
"_source": {
"Gabe": "Gabe",
"Gavin": "Gavin"
}
}
This result means that Gavin is following Gabe.
I believe the issue is how I'm storing the data.
In firebase my data looks like this
following
|---Gabe
|----Gavin:Gavin
so each child object of following object has key/value children of {username}:{username}
Now I can run queries that individually get the results I need. For example, if I ask ElasticSearch (ES) if channel "Gavin" is "online" I get back one result depending on if they are or are not online. And same with Following. However I can't seem to get the query to first see who is following Gavin and then see if they are online and return those users whom are online.
I've found a better solution (or maybe not). First you query the database for users whom are following a user.
From this list you send another query
{
"query":{
"filtered":{
"query":{
"match_all":{}
},
"filter":{
"bool":{
"must":{
"terms":{
"username":["username1"]
}
},
"must_not":{
"terms":{
"online":["true"]
}
}
}
}
}
}
}
This works however the username cannot be mixed with capitols. I don't know if this is an indexing issue on my part or terms have to be very specific. The solution I'm using on the client side is to lowercase the search terms before I submit them. It's crude and hacky but it works for now.
Issues that I may run into:
If a user has millions of followers pulling all that data from the
database will make the client sluggish.
a possible solution to this is to paginate the following results and run the query for every 20 returned results.
I'll continue to revise the answer as I develop / learn better query methods.