I would like to execute the flow based on a contains match
<Flow name="do_something_flow">
<Description/>
<Request>
<Step>
<FaultRules/>
<Name>do_something</Name>
</Step>
</Request>
<Response/>
<Condition>request.path MatchesPath "/**/india/blr/**"</Condition>
</Flow>
The flow should execute when ever the request path contains /india/blr for example
/v1/x1/india/blr/z1
/v1/x1/india/blr
/v1/india/blr
/india/blr
The above path expression does not work for the second and last path- where URL starts and ends with subpath.
What i really needs is
request.path contains "/india/blr"
Try changing your condition statement as
<Condition>request.path ~ "/india/blr/**"</Condition>
To catch all 4 cases, you could use this:
<Condition>request.path MatchesPath "**/india/blr**"</Condition>
However, this is a overly broad and will also match paths like this:
/india/blrx/asd
So, to be more precise, you probably want this:
<Condition>request.path MatchesPath "**/india/blr/**" or request.path MatchesPath "**/india/blr"</Condition>
In the pre-flow you can have a custom javacallout policy to match the path with contains condition.
Then populate a variable
Use that variable in the condition of your flow.
It is a round about way - but works in absence of a "contains" operator in apigee path conditions.
Alternately, you can try JavaRegex which is supported by apigee in conditions. http://apigee.com/docs/api-services/api/conditions-reference
~~ ( JavaRegex operator ) Matches a javax.util.regex compliant regular expression
Related
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.
I have several <intercept-url> in my spring-security XML. I just have this small doubt. Suppose I have something like :
<intercept-url pattern="/data/**" access="ROLE_ADMIN" />
<intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN" />
Since the below <intercept-url> has a pattern of /** I was wondering if the second URL over-rides the first one. E.g. I gt acess to /data/** even if I am a USER.
Quote from the reference documentation:
You can use multiple <intercept-url> elements to define different access requirements for different sets of URLs, but they will be evaluated in the order listed and the first match will be used. So you must put the most specific matches at the top.
As long as the rule for /** is listed later, it won't override the more specific rule for /data/**.
As jpprade suggested already, if you get access to /data/** as a plain user with the above rules, there must be some other problem with your configuration. In that case share your web.xml and the whole security config to troubleshoot that.
The second doesn't overides the first one, in theory it is the first matched rules which is applied.
if you can access /data/** as USER maybe it is because your miss something in the configuration, maybe the filter declaration ?
I have a webService that returns certain values. I know what those values will be. I want to pick them out of the XML and if those values are true I want the assertion to pass. Imagine that my test passes if I get this result... How can I assert that that is the case?
<BasicPersons>
<id>4</id>
<firstName>Patricia</firstName>
<middleName>A</middleName>
<lastName>Cluss</lastName>
</BasicPersons>
<BasicPersons>
<id>5</id>
<firstName>Benjamin</firstName>
<middleName>L</middleName>
<lastName>Handen</lastName>
</BasicPersons>
<BasicPersons>
<id>6</id>
<firstName>Ellen</firstName>
<lastName>Frank</lastName>
</BasicPersons>
<BasicPersons>
SoapUI provides XPath assertion for test steps that extracts XML element from the response and compare it with expected data.
Let's take you XML fragment as an example (I added root element to make it well-formed). First create in SoapUI new Test Request step and fill it with request XML. Let's then check whether response contains BasicPersons element with id=4 and all other specified fields. Add new assertion XPath Match from Property Content group. Then type in the expression for the check. Here is what I get:
boolean(/root/BasicPersons[id=4 and firstName="Patricia" and middleName="A" and lastName="Cluss"])
Expected Result shall be true if XPath matches XML response. The assertion fails otherwise.
You may create several assertion for testing several persons from your response.
A xpath expression like...
((//*:BasicPersons[1]/*:middleName)='A' and (//*:BasicPersons[1]/*:firstName)='Patricia') and so on for other fields)
This will return TRUE when all condition will match the response.
Using MarkLogic to pull in data from a web service with xdmp:http-get() or xdmp:http-post(), I'd like to be able to check the headers that come back before I attempt to process the data. In DQ I can do this:
let $result := xdmp:http-get($query,$options) (: $query and $options are fine, I promise. :)
return $result
And the result I get back looks like this:
<v:results v:warning="more than one node">
<response>
<code>200</code>
<message>OK</message>
<headers>
<server>(actual server data was here)</server>
<date>Thu, 07 Jun 2012 16:53:24 GMT</date>
<content-type>application/xml;charset=UTF-8</content-type>
<content-length>2296</content-length>
<connection>close</connection>
</headers>
</response>
followed by the actual response. the problem is that I can't seem to XPath into this response node. If I change my return statement to return $result/response/code I get the empty sequence. If I could check that code to make sure I got a 200 back before attempting to process the actual data that came back it would be much better than using try-catch blocks to see if the data exists and is sane.
So, if anyone knows how to access those response codes I would love to see your solution.
For the record, I have tried xdmp:get-response-code(), but it doesn't take any parameters, so I don't don't know what response code it's looking at.
You're getting burned by two gotchas at once:
awareness of namespaces
awareness of document nodes
First, the namespace. The XML output of the http-get function is in a namespace as seen by the top-level element:
<response xmlns="xdmp:http-get">
To successfully access elements in that namespace, you need to declare a prefix in your query bound to the correct namespace, and then use that prefix in your XPath expressions. For example:
declare namespace h="xdmp:http-get";
//h:code
Now lets talk about document nodes. :-)
You're trying to access $result as if it is a document node containing an element, but in actuality, it is a sequence of two root nodes (so they're not siblings either). The first one (the one you're interested in here) is a parentless <response> element—not a document containing a <response> element.
This is a common gotcha: knowing when a document node is present or not. Document nodes are always invisible when serialized (hence the gotcha), and they're always present on documents stored in the database. However, when you just use a bare element constructor in XQuery (as the http-get implementation does), you construct not a document node but an element node without a document node parent.
For example, the following query will return the empty sequence, because it's trying to get the <foo> child of <foo>:
declare variable $foo := <foo>bar</foo>;
$foo/foo
On the other hand, the following does return <foo>, because it's getting the <foo> child of the document node (which has to be explicitly constructed, in XQuery):
$declare variable $doc := document{ <foo>bar</foo> };
$doc/foo
So you have to know how a given function's API is designed (whether it returns a document containing an element or just an element).
To solve your problem, don't try to access $result/h:response/h:code (which is trying to get the <response> child of <response>). Instead, access $result/h:code (or more precisely $result[1]/h:code, since <response> is the first of a sequence of two nodes returned by the http-get function).
For more information on document nodes, check out this blog article series: http://community.marklogic.com/blog/document-formats-part1
Here is a sample to route message if USER_AUDIT Transaction with http request list:
http://www.blabla.com/dothis/USER_AUDIT?AA=aa&BB=bb
<when>
<simple>${in.header.CamelHttpPath} regex '(?i)/USER_AUDIT'</simple>
<bean ref="transactionList" method="get" />
<bean ref="transactionTransform" method="convert" />
</when>
Now I want to route other transactions see, CARD_VER to the same route.
Is there a syntax like:
<simple>${in.header.CamelHttpPath} regex '(?i)/USER_AUDIT' || '(?i)/CARD_VER'</simple> ?
In the regular expression you can add "or"s so you can match if either of the 2 is matching. But then you need to a bit a bit reg exp ninja to do that. That would be something alike
'(?i)/[USER_AUDIT|CARD_VER]'
But check the JavaDoc for regular expression: http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html. And Other docs for how to do regular expressions. Also there is plugins you can install in your Java editors where you can try out regular expressions on the fly, to figure out a pattern that works for you.
However in the Simple expression in Camel you can also use binary operators, and add a 2nd expression. So it would be something like:
<simple>${in.header.CamelHttpPath} regex '(?i)/USER_AUDIT' ||
${in.header.CamelHttpPath} regex '(?i)/CARD_VER'</simple>
In Camel 2.8.x or older, you could only have 1 binary operator, but from Camel 2.9 onwards you can have as many you want.
See details in the Camel documentation for the Simple expression. See the section about operators at: http://camel.apache.org/simple