I have created a new API /v1/StatusCache to point to my end point /v1/Status. My goal is to be able to cache the data :
based on the uri
for a particular header
So if user 1 sends request to /v1/StatusCache/1234 and the same user sends request to /v1/StatusCache/5678, I should hit my server instead of getting previously cached result from the first request.
Also we user header (Authorization: Bearer ) in the request so my second goal is that if user 1 with header Authorization: Bearer token1 sends a request to /v1/StatusCache/1234 vs a user 2 with header Authorization: Bearer token2 sends a request to /v1/StatusCache/1234, I should get different results (non cached results)
I have this code for proxypath but it just caches every request for 10 seconds. What am I missing
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ResponseCache async="false" continueOnError="false" enabled="true" name="responsecache-1">
<DisplayName>ResponseCache-1</DisplayName>
<FaultRules/>
<Properties/>
<CacheKey>
<Prefix/>
<KeyFragment ref="proxy.pathsuffix" type="string">proxy.pathsuffix</KeyFragment>
</CacheKey>
<Scope>Exclusive</Scope>
<ExpirySettings>
<ExpiryDate/>
<TimeOfDay/>
<TimeoutInSec ref="">10</TimeoutInSec>
</ExpirySettings>
<SkipCacheLookup/>
<SkipCachePopulation/>
</ResponseCache>
My suggestion would be create a variable value combining the header and pathsuffix value (header+pathsuffix) - use this as the key for the response cache.
Try the following:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ResponseCache async="false" continueOnError="false" enabled="true" name="responsecache-1">
<DisplayName>ResponseCache-1</DisplayName>
<FaultRules/>
<Properties/>
<CacheKey>
<Prefix/>
<KeyFragment ref="proxy.pathsuffix" type="string"/>
<KeyFragment ref="request.header.Authorization" type="string"/>
</CacheKey>
<ExpirySettings>
<ExpiryDate/>
<TimeOfDay/>
<TimeoutInSec ref="">60</TimeoutInSec>
</ExpirySettings>
<SkipCacheLookup/>
<SkipCachePopulation/>
</ResponseCache>
I used 60 sec timeout for ease of testing.
This shows an example of proxy.pathsuffix + request.header.Authorization values being a unique cache key. Think of the key now looking like /1234__Bearer token1. The same path suffix and Authorization header value combined are needed to return an entry from cache.
Also, when trying to cache the URI, you may want to try the variable request.uri which includes the querystring-- this can sometimes dictate what the response looks like. If using this, be sure that the querystring does not include unique values like a current timestamp (or at least strip that parameter before using it as a cache key fragment).
Related
I am using serviceCalloutPolicy to get response from some "xyz" api. The response returned by "xyz" api is text data like "abnfhjdkdhrju784hhkfjhbbhg21g3u2u9fdjkfnfddsnrijirry3784yewrgshbsdjbcjsvnvksdnv" which is neither json nor xml . so how can extract this data into variable. I want to use this data as header in another api call.
You can get the response value by using Extract Variable Policy.
Place it after your Service Callout Policy.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ExtractVariables async="false" continueOnError="false" enabled="true" name="EVTIB-ExtractValueFromJC">
<DisplayName>EVTIB-ExtractValueFromJC"</DisplayName>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<Source clearPayload="false">yourJavaCalloutReponseName</Source>
<VariablePrefix>resp.data</VariablePrefix>
<JSONPayload>
<!--- Extract value from Json or XML , for example Json-->
<Variable name="apiRespData">
<JSONPath>$.data</JSONPath>
</Variable>
</JSONPayload>
</ExtractVariables>
And then use variable name to reference the value.
I'm developing aplication which sends thousands of http post requests. I want to record all responses and use them as stubs with help of Fiddler`.
For example (lets assume product price = productid for simplicity):
send request, body<productId>1</productId>
get real response, body <productprice>1</productprice>
save response (headers+body) form previous step in local storage,for
example in some dictionary [1,"HTTP/1.1 200 OK
<productprice>1</productprice>"]. (Since we stored this response,
next requests matching pattern body contains
<productId>1</productId>should be responded from our local storage
)
send request, body <productId>1</productId>
load response from local storage and return HTTP/1.1 200 OK
<productprice>1</productprice>
send request, body <productId>2</productId>
get real response, body <productprice>5</productprice>
save response (headers+body) form previous step in local storage,for
example in some dictionary [1,"HTTP/1.1 200 OK
<productprice>1</productprice>"],[2,"HTTP/1.1 200 OK
<productprice>2</productprice>"]
...
How to configure Fiddler for it?
Details:
I have already captured 1000 real POST requests and i want to debug my application with help of them.
Each request / response is unique and in general looks like:
request
POST https://myurl HTTP/1.1
Authorization: Bearer xxx
Content-Type: application/soap+xml; charset=utf-8; action="GetList"
Host: myurl.net
Content-Length: 358
Expect: 100-continue
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Body>
<catalogRequest xmlns="https://myurl">
<id xmlns="">1</id>
</catalogRequest>
</s:Body>
</s:Envelope>
response
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="https://myurl">
<env:Body>
<ns1:catalogResponse>
<result>
<id>1</id>
<name>some text</name>
<price>109.99</price>
... big xml ...
<status>1</status>
</result>
</ns1:catalogResponse>
</env:Body>
</env:Envelope>
I tried Autoresponder, but when i dragged captured sessions to the Autoresponder they were converted to rules like: METHOD:POST EXACT: - this rule doesn't use POST body. I can't manually change 1000 rules to use URLWithBody rule
I think it is possible to create Fiddler script, but i don't know how to store captured requests/responses for this script to use them as mapping.
After small research i found a way to record responses and use them as stubs in future. To acheive that i suggest to use fiddler scripts. Here example of scripts in pseudocode
For BeforeRequest:
var body = session.requestBodyBytes;
var id = GetIdFromBody(body);// code for getting id from request body
session.Reply = id;
For AfterResponse:
var body = session.GetRequestBodyAsString();
var id = GetIdFromRespBody(body);// code for getting id from response body
session.SaveResponse(id);
I need to save the value of the system variable "system.timestamp" into a flow variable.
(The idea is to obtain the duration of some callout policies in between)
However, I can't read it because the AssignMessage policy raises the fault:
{
"fault": {
"faultstring": "java.lang.Integer cannot be cast to java.lang.String",
"detail": {
"errorcode": "Internal Server Error"
}
}
}
Neither Long nor Integer values can be read, only strings, which is kind of strange because what would be the case of exposing variables one cannot read?
I am trying to avoid the "non elegant" Javascript policy, if that is possible at all, so here's the [very basic] AssignMessage policy I'm using to read the value:
<AssignMessage async="false" continueOnError="false" enabled="true" name="time-test">
<DisplayName>TimeTest</DisplayName>
<AssignVariable>
<Name>myvar</Name>
<Ref>system.timestamp</Ref>
</AssignVariable>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>
system.timestamp variable is documented here:
http://apigee.com/docs/api-services/reference/variables-reference#-a-class-jumplink-name-system-a-system-variables
If the AssignMessage policy doesn't work, you should be able to accomplish this using a JavaScript policy. That would allow you to convert the timestamp to whatever form it needs to be. Similarly, a JavaScript policy could be used to do any timing calculations or manipulations later on in the proxy.
Migs, this is a current limitation of the product. I also use system.timestamp in my code, and I solve this problem with a 1 or 2 line JavaScript policy that creates a new string variable named systemTimestamp. I don't know of a better solution currently.
I am trying to achieve the functionality where i have to call two different backends / target endpoints that have completely different interface in a sequence. Output of one call becomes input to the second one upon an error condition from the first call.
I would like to know how to implement this. I am new to Apigee so details will help me.
It sounds like you need to do a ServiceCallout in the request flow.
Set up your Target as whatever the second server is that you need to talk to in the normal flow. Then create a policy to callout to your first target:
<ServiceCallout name="myPolicy">
<Request clearPayload="false" variable="myRequest"/>
<Response>myResponse</Response>
<HTTPTargetConnection>
<Properties/>
<URL>http://example.com</URL>
</HTTPTargetConnection>
</ServiceCallout>
Note the Response block puts the headers and payload from the response into an object that you can then extract variables from using "myResponse" as the <Source> in the ExtractVariables policy.
Then you can build a new request for your target with the variables you set in the ExtractVariables by using an AssignMessage policy
Service Callout
http://apigee.com/docs/api-services/content/call-services-or-apis-using-servicecallout
ExtractVariables
http://apigee.com/docs/api-services/content/extract-message-content-using-extractvariables
AssignMessage
http://apigee.com/docs/api-services/content/generate-or-modify-messages-using-assignmessage
Suppose I want to create the following APIs:
/movies/{movieId}/cast
/movies/{movieId}/crew
/movies/{movieId}/awards
On the recent versions of Apigee, wildcards are no longer allowed in the base URL. To achieve the ones above, we first created an API proxy /movies. We then defined three separate resources under it, each starting with a wildcard:
/*/cast
/*/crew
/*/awards
Here's a couple of questions:
Is this the only way to define wildcards in a hierarchical API structure?
Is there a way to define these into 3 separate API proxies?
Say you created an API with the basepath /movies and then consume /movies/jaws/cast. You can then crate a PreFlow policy to extract the path variable like this:
<ExtractVariables async="false" continueOnError="false" enabled="true" name="Extract-URI">
<DisplayName>Extract URI</DisplayName>
<FaultRules/>
<Properties/>
<URIPath>
<Pattern>/{movieid}/{function}</Pattern>
</URIPath>
</ExtractVariables>
You now have two variables, one for the variable and one for the actual service. Now you can create a Conditional Flow for each function (cast, crew, awards...) on the variable function rather than matching the path:
<Flow name="Cast">
<Description/>
<Request/>
<Response>
<Step>
<FaultRules/>
<Name>Assign-cast</Name>
</Step>
</Response>
<Condition>(function = "cast") and (request.verb = "GET")</Condition>
</Flow>
You may still need to do some magic to rewrite your target path, but your request proxy path will still be /jaws/cast but now you can run specific policies against a request for the cast of Jaws.
See http://apigee.com/docs/api-services/api/conditions-reference and http://apigee.com/docs/gateway-services/content/flow-variables-and-conditions for more info on Conditional Flow configuration.