Hi Apigee Community,
I have an API with /foo/bar/ as basepath and 8 resource paths. Depending on the resource path, the API call will go to a different target server, example:
API call | Backend webservice call |
http://proxypath.com/foo/bar/a/b/test/something?key=apikey | targetservice11.com/target/test/something?key=apikey |
http://proxypath.com/foo/bar/c/d/id/something?key=apikey | targetservice22.com/target/id/something?key=apikey |
I have an API where I would like to use BasePath like /foo/bar/ . Let's assume that this API Proxy has 8 different paths (resources?) like: /foo/bar/a/b, /foo/bar/c/d, /foo/bar/e/f... and for each of them I would like to create a different Conditional Flow, because each resource path goes to a different target endpoint.
First flow/resource will have a condition like:
<Condition>(proxy.pathsuffix MatchesPath "/a/b/**") and (request.verb = "GET")</Condition>
with target endpoint url:
targetpath.com/target/
This means that when I make an API call to this resource:
GET http://proxypath.com/foo/bar/a/b/test/something?key=apikey
then this call will be send to Target endpoint with path like:
GET targetservice11.com/target/a/b/test/something?key=apikey
The main problem is that the real target webservice accepts a request like
targetservice11.com/target/test/something?key=apikey
without the /a/b resource path. I do not want to send url fragment used in flow condition (in example /a/b) to Target Endpoint, so I would like to send to Target Endpoint request:
targetservice11.com/target/test/something?key=apikey
(with /a/b path fragment removed), but by default in Apigee everything after basepath will be attached to Target endpoint url.
Since I need to remove part of path suffix (in example /a/b) in all resources (different part in each one), I considered using a few mechanisms:
<AssignMessage async="false" continueOnError="false" enabled="true" name="AssignMessage.AssignMessageSuffix"> <DisplayName>AssignMessage.AssignMessageSuffix</DisplayName> <AssignVariable> <Name>conditional.path.suffix</Name> <Value>/a/b</Value> <Ref/> </AssignVariable> <AssignVariable> <Name>target.copy.pathsuffix</Name> <Value>false</Value> </AssignVariable> <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables> <AssignTo createNew="false" transport="http" type="request"/> </AssignMessage>
var path_suffix = context.getVariable("proxy.pathsuffix"); var condition_suffix = context.getVariable("conditional.path.suffix"); path_suffix = path_suffix.replace(condition_suffix, ''); context.setVariable("newsuffix.to.attach", path_suffix);
var path_suffix = context.getVariable("proxy.pathsuffix"); if(pathsuffix=="/a/b**" && requestverb=="GET") { path_suffix = path_suffix.replace("/a/b", ''); context.setVariable("newsuffix.to.attach", path_suffix); } else if (pathsuffix=="/c/d**" && requestverb=="GET") { path_suffix = path_suffix.replace("/c/d", ''); context.setVariable("newsuffix.to.attach", path_suffix); } else if () { } ...
Which one of these solutions should I use in my proxies? Is there some easier or better way to deal with the problem? I have been also considering using different Proxy Endpoints, instead of resources. So, in our example, I would have 2 proxy endpoints. The first proxy would have basepath: /foo/bar/a/b/, while the second one would have the basepath: /foo/bar/c/d/. What do you think about this idea?
Adding Apigee people with whom we had previous discussions about configuring API proxies:
@mchalmers @Srinivas Sudhindra @Yuriy @NICOLA CARDACE
Adding TomTom watchers:
Here is a link to the Apigee documentation about resource paths: http://docs.apigee.com/api-services/content/uri-based-configurations
The video (minute 00:18) and the bellow documentation snippet:
<lines from Apigee documentation>
For example, if your service provides weather reports and weather forecasts, your backend service might define two API resources:
When you create an API proxy, at a minimum you're creating an alias base URL that maps to your backend service. For example:
Backend base URL | New/equivalant API proxy URL |
---|---|
http://mygreatweatherforecast.com | http://{your_org}-{environment}.apigee.net/mygreatweatherforecast |
<end of lines from Apigee documentation>
indicate that the resource is a characteristic of the backend service (and not of the API call request).
Therefore, the following API calls:
API call | Backend webservice call |
http://proxypath.com/foo/bar/a/b/test/something?key=apikey | targetservice11.com/target/test/something?key=apikey |
http://proxypath.com/foo/bar/c/d/id/something?key=apikey | targetservice22.com/target/id/something?key=apikey |
will be implemented in Apigee as:
basepath: /foo/bar/a/b/ ------ with target endpoint: (server: targetservice11.com, path: /target/test/)
basepath: /foo/bar/c/d/ ------ with target endpoint: (server: targetservice22.com, path: /target/test/)
Is my understanding correct?
You could set target.copy.pathsuffix to false using :
<AssignVariable>
<Name>target.copy.pathsuffix</Name>
<Value>false</Value>
</AssignVariable>
and then set the target.url variable to your target endpoint using either an AssignMessage or javascript.
Another option is to use an environment variable using the below in TargetEndpoint:
<HTTPTargetConnection>
<LoadBalancer>
<Server name="IP or server name"/>
</LoadBalancer>
<Path>/target/test/something?key={apikey}</Path>
</HTTPTargetConnection>
or even set the query parameter using an AssignMessage.
Hello @Jarosław Wojtalik.
If the proxy path always just contains two path variables depth, it would be possible to use a simple JavaScript to just remove the first two path variables.
var path_suffix = context.getVariable("proxy.pathsuffix"); // find index of third occurrence of '/' index0 = path_suffix.indexOf('/'); index1 = path_suffix.indexOf('/', index); index2 = path_suffix.indexOf('/', index1); // substring from index2 to end of path path_suffix = path_suffix.substring(index2); // save the substring path to new variable context.setVariable("newsuffix.to.attach", path_suffix); ...
Code can be optimized. Hope this helps.
Hello @kbouwmeester,
I was also thinking about using similar JS, but unfortunately depth is not always the same and it would be very easy to make a mistake.
I was also thinking about using flow name ("current.flow.name"), and in this flow name put fragments I would like to remove (e.g. flow with name "/c/d**"). In this case it would be easy to assign new version of path suffix to target url using JS, but I would have to make sure to always put there everything i want to remove.
(Taken from Apigee Community: https://community.apigee.com/questions/29451/how-can-i-read-condition-expression-using-js-or-po.html...
What to you think about this idea with flow naming?
User | Count |
---|---|
3 | |
2 | |
1 | |
1 | |
1 |