Hello,
I have to protect with Apigee an application with thousands of resource path, all with the same flow.
Should I have in the XML proxy a <Condition> tag with thousands of "or" clause?
For example:
<Condition>(proxy.pathsuffix MatchesPath "/products") or (proxy.pathsuffix MatchesPath “/contracts”) or (proxy.pathsuffix MatchesPath “/documents”) etc....</Condition>
I'm afraid it's neither easy to maintain nor fast to execute. Are there best practice?
I cannot use wildcards! 🙂
Thanks in advance for the help
Solved! Go to Solution.
I'm afraid it's neither easy to maintain nor fast to execute.
I agree with you, it does not seem that it would be "easy" to maintain. Lots of copy-pasta in your proxy endpoint. I don't think I would want to maintain that. I am unsure how fast it would be.
Are there best practice?
Hmmm. It's a bit unusual. Are the LEFT MOST path segments all common? or? Are you saying that /products and /contracts etc are examples of the left-most segments in the path?
I mean does it look like this?
https://endpoint/v1/products
https://endpoint/v1/contracts
https://endpoint/v1/documents
or does it look like this
https://endpoint/contracts
https://endpoint/products
https://endpoint/documents
Something you might try: In the proxyendpoint itself, don't use a conditional flow. Or use Conditional flows to EXCLUDE verbs you know you don't want to allow (PUT or PATCH for example, possibly). Then, in the Request PostFlow, attach a JavaScript step that checks the 1000 or more paths in a loop.
var validResourcePaths = /* something here */
var pathsuffix = context.getVariable('proxy.pathsuffix');
function pathMatcher(path) {
return path.startsWith(pathsuffix);
}
if (!validResourcePaths.find(pathMatcher)) {
// The find method invokes the pathMatcher function once for each item
// in the list until a match is found.
// If control reaches here, the provided path is not in the list.
throw new Error('unknown request');
// This will throw a Fault and result in an error sent back to the client.
// Use FaultRules in the ProxyEndpoint to "handle" the fault and
// send a curated error message.
}
// If control reaches here, the pathsuffix is valid. Do nothing further.
Some notes
I have no idea how fast this would be. Probably it would be slower than using a single, very very long Condition statement. But, there is a limit to the length of the condition statement, and the I guess the limit probably would not allow for 1000 or more tests. Even if it did, the better maintainability of a JS step would probably be preferable. My personal preference is to favor maintainability over absolute performance.
This JS approach still leaves open the question of .. where do you store the list of valid paths? In Apigee X and hybrid there is a nifty feature called "propertysets" that might allow it, except I think there is a line limit in the propertyset file too. (Try it and see). If you are not using Apigee X or hybrid, then you need something else. I could suggest a separate JS file which stores the data as a JS array. Something like this:
var list = [
'/products', '/contracts', '/documents', ...
];
And then in the JS step you would have to use the IncludeURL element, like this:
<Javascript name='JS-CheckPath' >
<IncludeURL>jsc://list-of-valid-paths.js</IncludeURL>
<ResourceURL>jsc://checker-script.js</ResourceURL>
</Javascript>
Another option: you could store the set of valid paths externally, and use a ServiceCallout to retrieve them, and then cache that data, and retrieve it from cache using LookupCache. In that case the top of your checker-script.js would do something like:
var list = JSON.parse(context.getVariable('serviceCallloutResponse.content'));