What is the best way to remove path fragments from resource paths?

Not applicable

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:

  • using AssignMessage policy for each resource, where I assign path suffix part to remove to variable:
    • <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>
      		
    • later I use JS to create Target path suffix
    •  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);
      		
    • in this case I have to create AssignMessage policy for each resource, where I define fragment which I would like to not send to backend. So for each target endpoint I need to create such an AssignMessage.
  • using single JS with condition for each resource (example might not work fine, but it captures the idea):
    • 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 () {
      }
      ...
      		
    • this requires creating complex JS file, where most likely more than one condition will be checked (bad from performance reasons)

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?

3 5 5,256
5 REPLIES 5

Not applicable

Adding Apigee people with whom we had previous discussions about configuring API proxies:

@mchalmers @Srinivas Sudhindra @Yuriy @NICOLA CARDACE

Adding TomTom watchers:

@Emilia Ipate

Not applicable

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 URLNew/equivalant API proxy URL
http://mygreatweatherforecast.comhttp://{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 callBackend webservice call
http://proxypath.com/foo/bar/a/b/test/something?key=apikeytargetservice11.com/target/test/something?key=apikey
http://proxypath.com/foo/bar/c/d/id/something?key=apikeytargetservice22.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?

Not applicable

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?