In Apigee
given a variable in javascript policy, example: var value = 123;
how to get this variable in the assign message policy?
by using {a} in the payload message is not reachable
For the variable to be available for use in any Apigee policy, you first have to make it a flow variable. You can use Apigee's JavaScript Object Model method called context to to this (see ref here). In your JS policy, you have var {some-value} = 123;. To make this available as a flow variable,introduce this line in your JS policy after the variable assignment: context.setVariable("preferred-variable-name", some-value);
You can now access this preferred-variable-name in your AM policy as show below:
<AssignVariable>
<Name>preferred-variable-name</Name>
<Ref>preferred-variable-name</Ref>
</AssignVariable>
Just to mention it is possible to pass the value directly in the policy as well as shown below
<AssignVariable>
<Name>variable_name</Name>
<Value>123</Value>
</AssignVariable>
Read more here.
The <Name> tag can be set to any name.
You have to set the variable in the context object using context.setVariable("variable-name", value);
Refer to this variable in the assign_message policy using {variable-name}.
You can just set the context variable in jsPolicy like this:
context.setVariable("a","123");
You can use it after in any of the policies.
Ex :-
<QueryParams>
<QueryParam name="a">{a}</QueryParam>
</QueryParams>
Related
I am working in Jmeter.
I need to sent the value for the variable name 'Reference' in the response of the particular request.
I am able to get the response using Bean shell Post processor using the string "vars.put("response", new String(data));"
I need the get the variable 'Reference' which is referred by id as id="reference"
I need to pass value to the variable 'Reference'.
Can anyone help?
Since JMeter 3.1 it's recommended to use JSR223 Test Elements and Groovy language for any form of scripting so if you want to store the response into the Reference JMeter Variable you can do it as follows:
Add JSR223 PostProcessor as a child of the request which response you want to store
Put the following code into "Script" area:
vars.put("Reference", prev.getResponseDataAsString());
where:
vars is a shorthand for JMeterVariables class instance
prev stands for the parent SampleResult
see JavaDoc for the above shorthands for all available functions/properties description and Top 8 JMeter Java Classes You Should Be Using with Groovy for comprehensive explanation with examples for the above and other JMeter API shortcuts available for Groovy scripts
I want to transform a URL before it is redirected to the target, removing a string. I have the following flow in Apigee:
USER -> APIGEE -> APPLICATION -> APIGEE -> USER
The user requests and then its URL should be rewritten removing bar from the URL.
BEFORE apigee.url.com/foo/bar/pBxATaojIn8tk5dvQdNJ
AFTER target.url.com/foo/pBxATaojIn8tk5dvQdNJ
I use Proxy Endpoints and Target Endpoints and try to rewrite using a PreFlow hook with Javascript in the Target Endpoint, without success rewriting the proxy.pathsuffix. How can I solve this?
I now use the following solution:
// Disable copy path
context.setVariable("target.copy.pathsuffix", false);
// Replace string in incoming proxy URL path
var proxyPathSuffix = context.getVariable("proxy.pathsuffix");
var fooBarAfter = proxyPathSuffix.replace('/fooToReplace', '');
// Fetch target outgoing url path
var targetBasePath = context.getVariable("target.basepath");
var urlPath = targetBasePath.concat(fooBarAfter);
// Replace outgoing url
var targetUrl = context.getVariable("target.url");
targetUrl = targetUrl.replace(targetBasePath, urlPath);
context.setVariable("target.url", targetUrl);
I came up with it looking at the available variables here. As this is JS, if someone comes up with a better solution I would be happy!
From my understanding proxy.pathsuffix is a read only variable so you can't override it.
Assign your target endpoint to target.url instead. (I usually use in Assign Message Policy of the request)
Example:
<AssignVariable>
<Name>target.url</Name>
<Ref>yourTargetUrlValue</Ref>
</AssignVariable>
In my Assign Message Policy of the request, I have added the block of code above for defined my target url.
You can assign directly like <Ref>http://test.com</Ref> or assign via variable like <Ref>{targetUrlVal}</Ref>
If you got the url from somewhere, don't forget to assign value to your variable before use it by using context.setVariable("targetUrlVal", "http://test-01.com");
Hopefully my answer will help you.
I solved this similar to how you did it. See my answer on another SO question that answers this.
Hi I want to add a query parameter Age = 23
I tried adding
message.inboundProperties.'http.query.params'.Age = '23'
In a expression
<expression-component doc:name="Expression"><![CDATA[message.inboundProperties.'http.query.params'.Age= '23';]]></expression-component>
It won't work.
Inbound properties are Immutable hence you must add it in outbound property to add a query param in your outbound http connector you can use the below
<http:request config-ref="HTTP_Request_Configuration" path="outway" method="POST" doc:name="HTTP">
<http:request-builder>
<http:query-param paramName="Age" value="23"/>
</http:request-builder>
</http:request>
To add properties to an outgoing message they need to be in the outbound scope:
message.outboundProperties.'http.query.params'.Age= '23'
You are trying to modify inbound properties but you can´t, they are inmutable
Properties have two main scopes: inbound and outbound.
Inbound properties are immutable, are automatically generated by the message source and cannot be set or manipulated by the user. They contain metadata specific to the message source that prevents scrambling of data formats or other processing mishaps later in the message’s lifecycle. A message retains its inbound properties only for the duration of the flow; when a message passes out of a flow, its inbound properties do not follow it (see image below).
https://docs.mulesoft.com/mule-fundamentals/v/3.7/mule-message-structure
You must add it to outbound as Ryan said.
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
We wanted to be able to ignore case in our http parameter name for apikey--i.e., we want to accept ApiKey, APIKEY, and Apikey (and all other permutations) to be accepted...but it seems that request.queryparam.apikey will only accept "apikey" as HTTP parameter.
We thought of using ExtractVariable policy with ignoreCase attribute (then assign it to another variable qp.api_key) but it doesn't seem to work (or we don't fully understand what #ignoreCase does)..i.e., qp.api_key is only assigned if we pass apikey param (and not ApiKey, apiKey, etc).
<QueryParam name="apikey">
<Pattern ignoreCase="true">{api_key}</Pattern>
<VariablePrefix>qp</VariablePrefix>
</QueryParam>
how do we achieve case-insensitivity for the apikey HTTP get param?
The ignoreCase attribute applies to the Pattern - not the name.
Your pattern does not include anything other than the variable you are receiving, so in your case it does nothing.
But, a pattern can contain surrounding characters that comprise a pattern that you expect, as in:
<QueryParam name="apikey">
<Pattern ignoreCase="true">abc{api_key}</Pattern>
<VariablePrefix>qp</VariablePrefix>
</QueryParam>
In this case, when your API proxy is invoked with ?apikey=abc123 or ?apikey=aBc123, apikey will be set to 123.
If API Key is the only parameter in the querystring - following would work
<ExtractVariables async="false" continueOnError="false" enabled="true" name="extractapikey">
<DisplayName>ExtractApiKey</DisplayName>
<Variable name="request.querystring">
<Pattern ignoreCase="true">apikey={api_key}</Pattern>
</Variable>
</ExtractVariables>
+1 for Randy's suggestion to choose the reasonable spellings of apikey and putting all of those in a single ExtractVariables policy:
apikey
APIkey
apiKey
ApiKey
APIKey
APIKEY
If you really wanted to handle all possible spellings, another solution would be to use a JavaScript callout. You can access the variable message.queryparam.names, which is a collection of all query parameter names, or message.querystring, which is the query string itself. Loop through the names or parse the query string and once you find a parameter name that is a case-insensitive match, grab the corresponding message.queryparam.{queryparam_name} variable. See the Apigee docs for the possible variables you can access.
I created a Python Script Policy:
import re
qs = flow.getVariable('request.querystring')
p = re.compile(r".*apikey=(\w+).*", re.IGNORECASE)
m = p.match(qs)
if m is not None:
flow.setVariable('qp.api_key', m.group(1))
in this case, it gets assigned to qp.api_key and use that ref for the VerifyApiKey policy.
i think this should be a standard option to extract flow variables (i.e., case-insensitive param names) instead of going through extra policies to do the same relatively basic thing.
thanks for the quick response and ideas, guys.
I'd suggest lowercasing all parameters, so code can use a single standard naming convention. Code below can be executed within JavaScript policy to set variables that can be used later on in any subsequent policies. These variables will then become the variables to be referenced from any other places.
function setLowerCaseQueryParams(){
var qpnames = request.queryParams;
for(var key in qpnames){
context.setVariable("queryparams." + key.toLowerCase(), request.queryParams[key]);
}
}
setLowerCaseQueryParams();
With this function you can always send any combination of characters. e.g AbCdEFGHijKl=value, abcdEfghijkl=value or ABCDEFGHIJKL=value and it will always be accessed as:
var queryparamval = context.getVariable('queryparams.abcdefghijkl')