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

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:

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](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 Likes

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

@mchalmers @Srinivas Sudhindra @Yuriy @NICOLA CARDACE

Adding TomTom watchers:

@Emilia Ipate

1 Like

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:

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:

indicate that the resource is a characteristic of the backend service (and not of the API call request).

Therefore, the following API calls:

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?

1 Like

You could set target.copy.pathsuffix to false using :

target.copy.pathsuffix false

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:

/target/test/something?key={apikey}

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.

2 Likes

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?