API Proxy with hierarchical URLs

Not applicable

Hello, and thanks in advance for any help you guys can give me...

I'm new to API Gee and I'm in the process of creating my API.

So far, I used Baas to create a collection and a few entities underneath.

I also created an API Proxy so I can expose that.

What I want to do now, is tell the API Proxy to "mask" some of my API calls. For example, I have a shops collection and a /shops method that lists all the shops. If I want to filter by shop ID, I can add ?ql=select * where _id=1. What I want to do, is set up my Proxy so I can mask that and simply call /shops/1

How can I do that?

Thanks in advance!

Solved Solved
0 4 345
1 ACCEPTED SOLUTION

Not applicable

This can be readily done with a combination of XML and JSC based policies. In the following snippet we extract one or more catalog IDs into a variable named catalog.id as indicated above:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<ExtractVariables async="false" continueOnError="true" enabled="true" name="extractCatalogVariables">
    <DisplayName>extractCatalogVariables</DisplayName>
    <URIPath>
    	<!-- work from most specific to least specific-->
        <Pattern>/{version}/profile/{profile.alias}/catalog/{catalog.type}/{catalog.id}/entitled</Pattern>
        <Pattern>/{version}/profile/{profile.alias}/catalog/{catalog.type}/{catalog.id}</Pattern>
    </URIPath>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</ExtractVariables>

Our convention is that multiple IDs may be concatenated with the | character. Within a Javascript callout we construct a soap snippet for selecting one or more resources as follows:

var catalog.id = context.getVariable("catalog.id");
if (!catalog.id) catalog.id = "";

var resIDs = "";
if (catalog.id !== "") {
    resIDs = "<ResourceIds>";
    var iDsArr = catalog.id.split("|");
    iDsArr.forEach(function(id) {
        resIDs += ("<ResourceId>" + id + "</ResourceId>");
    });
    resIDs += "</ResourceIds>";
}
context.setVariable("catalog.resourceQuery", resIDs);

In a subsequent AssignMessage Policy we then insert this snippet into the target request:

<AssignMessage name="buildCatalogRequestById">
    <DisplayName>buildCatalogRequestById</DisplayName>
    <AssignTo createNew="true" type="request">request</AssignTo>
    <Set>
        <Headers>
            <Header name="Authorization">{request.header.Authorization}</Header>
            <Header name="user-agent">{request.header.user-agent}</Header>
            <Header name="Cookie">{request.header.Cookie}</Header>
        </Headers>
        <Verb>POST</Verb>
        <Payload contentType="text/xml">
            <Request xmlns="urn:foo:bar">
                {catalog.identityQuery}
                <ResourcesQuery>
                    {catalog.resourceQuery}
[snip]

This can be adapted to create your back end query to BaaS as well. Generally this pattern holds anytime you want to:

  • create uniform or simplified proxy for a more complex or proprietary target system
  • transform from one API style to another (REST to SOAP)

View solution in original post

4 REPLIES 4

sarthak
Participant V

You can do this in two ways : Either via node.js or using policies. If you want to do it with policies you will first need to use an Extract Variable policy where you will extract the ID with a snippet like ::

<URIPath>
      <Pattern ignoreCase="true">/shops/{id}</Pattern>
   </URIPath>

You can learn more about Extract Variables here.

After that you will use an AssignMessage policy or a javascript policy to construct the ?ql=select * where _id=1 with the extracted ShopId . Typically javascript will be easier.

Thank you!!!!!

And all of that can be done in the API Proxy?

I mean, my idea so far was not to have to implemente node.js or CURL to proxy my BaaS API but make 100% APIGee... Does that make sense?

Yes , all the above configurations are for inside an Apigee proxy. You can write node.js code or the various policies inside a proxy.

Not applicable

This can be readily done with a combination of XML and JSC based policies. In the following snippet we extract one or more catalog IDs into a variable named catalog.id as indicated above:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<ExtractVariables async="false" continueOnError="true" enabled="true" name="extractCatalogVariables">
    <DisplayName>extractCatalogVariables</DisplayName>
    <URIPath>
    	<!-- work from most specific to least specific-->
        <Pattern>/{version}/profile/{profile.alias}/catalog/{catalog.type}/{catalog.id}/entitled</Pattern>
        <Pattern>/{version}/profile/{profile.alias}/catalog/{catalog.type}/{catalog.id}</Pattern>
    </URIPath>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</ExtractVariables>

Our convention is that multiple IDs may be concatenated with the | character. Within a Javascript callout we construct a soap snippet for selecting one or more resources as follows:

var catalog.id = context.getVariable("catalog.id");
if (!catalog.id) catalog.id = "";

var resIDs = "";
if (catalog.id !== "") {
    resIDs = "<ResourceIds>";
    var iDsArr = catalog.id.split("|");
    iDsArr.forEach(function(id) {
        resIDs += ("<ResourceId>" + id + "</ResourceId>");
    });
    resIDs += "</ResourceIds>";
}
context.setVariable("catalog.resourceQuery", resIDs);

In a subsequent AssignMessage Policy we then insert this snippet into the target request:

<AssignMessage name="buildCatalogRequestById">
    <DisplayName>buildCatalogRequestById</DisplayName>
    <AssignTo createNew="true" type="request">request</AssignTo>
    <Set>
        <Headers>
            <Header name="Authorization">{request.header.Authorization}</Header>
            <Header name="user-agent">{request.header.user-agent}</Header>
            <Header name="Cookie">{request.header.Cookie}</Header>
        </Headers>
        <Verb>POST</Verb>
        <Payload contentType="text/xml">
            <Request xmlns="urn:foo:bar">
                {catalog.identityQuery}
                <ResourcesQuery>
                    {catalog.resourceQuery}
[snip]

This can be adapted to create your back end query to BaaS as well. Generally this pattern holds anytime you want to:

  • create uniform or simplified proxy for a more complex or proprietary target system
  • transform from one API style to another (REST to SOAP)