I am creating a JavaScript policy for an API and I am attempting to iterate the query parameter names to see which ones have been sent.
I used the context variable "request.queryparams.names" which I saw in the documentation as returning a variable of type "Collection"
var queryParamNames = context.getVariable("request.queryparams.names");
I could not iterate this variable in a loop nor could I invoke a "hasOwnProperty()" method on it. It kind of does not make sense to me as a Collection in JavaScript either is an array or a structured object and this seems to be neither.
When I trace my api request and see the variable in listed it shows up like [value1, value2] which looks like an array, but if I invoke
Object.prototype.toString.call(queryParamNames)
The type comes out to the JavaObject.
So firstly, why is that ?
Secondly, is this what is meant by a Collection because the docs don't say you get back a JavaObject ?
Thirdly, how do I iterate the query parameter names of this JavaObject ?
Thanks.
Dear @Georges Haddad , Welcome to Apigee Community. We see the same results. Let us look into it.
@krupa , Any idea what is the root cause ?
I'm assuming that apigee has some Java layer underneath it and that's probably the reason why this function would return a JavaObject in javascript. It's still accessible in JS but not as a standard JS collection. I assume we would have to know what the methods are of the netscape (I believe?) wrapper on Java objects. @Dino so far has the best solution, but it still does not answer my 3 questions listed above.
Yes, that is correct. The Javascript you write runs within Rhino, which is hosted in a Java VM. The thing you are getting is a Java object, an instance of java.util.Set.
> it it still does not answer my 3 questions listed above.
True enough! I'll address your questions but can't promise you satisfaction.
> why is that?
I can't answer that, I don't know. It just is. It was designed this way.
> is this what is meant by a Collection
I suppose so.
> how do I iterate the query params?
try this:
var queryParamNames = context.getVariable("request.queryparams.names"); var a = queryParamNames.toArray(); var length = a.length; context.setVariable('test_qparam_names_length', length); var i = 0; a.forEach(function(item) { context.setVariable('test_qparam_name_found' + i++, true); context.setVariable('test_qparam_name_' + i++, item.toString()); });
For my own purposes, it is easier to use the string manipulation approach, or to use the URI.js library. YMMV.
Thanks @Dino for the answers, they are to my satisfaction. So basically if the JavaObject returned is a JS wrapper of the Java Collection interface then there is a way we could leverage this. As you posted in your example of using .toArray(); which is a Java method in the Colleciton interface, we might as well can use .contains(); to check if a parameter is found inside it. This what I needed to do anyways.
So actually if you check out http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html and use those exposed methods, you can use the Set more efficiently. This should be reflected in the documentation too.
Answer by Dino
·
Nov 10, 2015 at 08:12 PM
Sorry you're having trouble using the request.queryparams.names context variable from within JS.
I cannot solve that immediate problem for you, but I can suggest something that might be useful as a workaround. I use URI.js often within my JS for parsing query params and so on.
To use it, you'd need to include the source of URI.js into your resources/jsc directory, and you'd need to specify it like this in the JS callout policy configuration:
<Javascript name='Javascript-ParseQparams' timeLimit='200' > <IncludeURL>jsc://URI.js</IncludeURL> <ResourceURL>jsc://parseQparams.js</ResourceURL> </Javascript>
And then your JS code would look something like this:
var uri = URI(context.getVariable('request.uri')); // get data map: var search = uri.search(true); // suppose the inbound API request looks like: // http://host/basepath/suffix?param1=value1a¶m1=value1b¶m2=value2 // // then, the search object would look like this: // { // "param1": [ // "value1a", // "value1b" // ], // "param2": "value2" // }
Thanks @Dino, that's a good way to go around the issue. I actually did the same workaround but manually parsing the querystring. This URI.js package looks like it can do the job better.
Answer by nagesh · Nov 12, 2015 at 05:08 AM
Hope this help!
//Convert Collection to string
var queryFieldsCollection = context.getVariable('request.queryparams.names') + '';
//Remove square brackets
queryFieldsCollection = queryFieldsCollection.substr(1, queryFieldsCollection.length - 2);
//Split string into an array
var queryFieldsArray = queryFieldsCollection.split(", ");
Once you have array, you iterate and get the array elements
--Regards,
Nagesh
Hi @nagesh thanks for that answer, though it is the same kind of workaround as getting the query fields form context.getVariable("request.querystring"); Either way still have to parse the feilds, at least with @Dino's answer you'd write less code and handle the parsing of the query params to the URL.js library.
Answer by fredericvanderelst · Sep 04, 2017 at 11:28 PM
Hi,
I've found that the 'array' given by
var tmp = context.getVariable("request.queryparams.names"); var qp = qparams.toArray();
is indeed an iterable array; so doing
// this *does* print the first element print("qp[0]: " + qp[0]); // but.. print("type of param: " + typeof(q2[0]); // prints 'object', not 'string' print("type of param: " + typeof(q2[0].toString()); // also. if ( q2[0] == 'xx' ) {..} // Always fails (actually I'm using Sets to do compulsory/optional param validation but this holds) *However*... if you do if (q2[0] + "" == 'xx') then you win. I'm happy and disturbed...
Answer by Kipruto Bett · Apr 26, 2018 at 02:36 PM
The URI.js library has a function, hasQuery(queryparamname) function that returns true if the queryparamname exists in the URI query string.
Not able to get body content in javascript policy 1 Answer
Access Javascript variable in Service Callout ploicy 1 Answer
How to call two services using httpclient? 1 Answer
Asynchronous HTTP Requests in an API proxy to another API proxy 2 Answers
How to access httpClient response headers in javascript? 2 Answers