Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

Apigee proxy to get the client Id's of all the apps a product is part of.

Hello All,

I have a requirement that with a call to an apigee end point with a different proxy name sent in header, the result should be the list of client id's of all the apps where the products that proxyname sent in the header are part of.

So let say I have proxy 1 and proxy2. Proxy 1 is part of Product1 and Product1 is part of App1 and App2. Now when I call Proxy2 using postman with Proxy1 name sent in header, the output should be some thing like below

{
"app": [

{

"appId": "****",

"attributes": [
{
"name": "DisplayName",
"value": "App1"
},

"credentials": [
{
"apiProducts": [
{
"apiproduct": "Product1",
"status": "approved"
}
],
"attributes": [],
"consumerKey": "****",
"consumerSecret": "****",

}

{

"appId": "****",

"attributes": [
{
"name": "DisplayName",
"value": "App2"
},

"credentials": [
{
"apiProducts": [
{
"apiproduct": "Product1",
"status": "approved"
}
],
"attributes": [],
"consumerKey": "****",
"consumerSecret": "****",

}

I tried developing the process where I get the list of all apps using the management api call trough a javascript. But I am not able to filter the all apps json response I get from the management api call to get the desired result I mentioned above.

Lets say I store the all apps response in the variable FinalList. I try to get the desired output using the below message template but it just shows [] and nothing else. 

<AssignVariable>
<Name>extracted-text</Name>
<Value>BADDBEEF</Value>
<Template>{jsonPath($.app[*].credentials[?@.apiProducts[?@.apiproduct == 'Product1']],FinalList,'true')}</Template>
</AssignVariable>

Any suggestion or help is highly appreciated.

 

Thanks

Solved Solved
0 5 234
1 ACCEPTED SOLUTION

Hi @KalyanLearner 

As you can see from your example response from the GET /apps Apigee API call, it includes credentials for the API Product, not the API proxies that are in the API Product.

But I think you meant to say, when you call proxy2 with a header including the name of the API Product (e.g. x-apiproduct:Product1), then you could get the clientIds using that API Product.

I tried using Assign Message and Extract Variable policy with jsonPath, but was unable to get the predicate part to work, even using https://jsonpath.com.

This works using apiProducts[0], but only for the first occurance - $.app[*].credentials[?(@.apiProducts[0].apiproduct=='quota-operations-by-counter-1')].consumerKey

But this doesn't using apiProducts[*] -  $.app[*].credentials[?(@.apiProducts[*].apiproduct=='quota-operations-by-counter-1')].consumerKey

I resorted to using JavaScript and that worked.

 

 

function findConsumerKeys(data, targetProduct) {
  const consumerKeys = [];

  if (data && data.app && Array.isArray(data.app)) {
    data.app.forEach(app => {
      if (app.credentials && Array.isArray(app.credentials)) {
        app.credentials.forEach(credential => {
          if (credential.apiProducts && Array.isArray(credential.apiProducts)) {
            credential.apiProducts.forEach(product => {
              if (product.apiproduct === targetProduct) {
                consumerKeys.push(credential.consumerKey);
              }
            });
          }
        });
      }
    });
  }
  return consumerKeys;
}

const targetProduct = context.getVariable("request.header.x-apiproduct");
const jsonData = JSON.parse( context.getVariable('message.content') );
const client_ids = findConsumerKeys(jsonData, targetProduct);
context.setVariable("client_ids",JSON.stringify(client_ids));

 

 

Then my curl request using the result of GET /apps as the input

 

 

curl -X POST https://$HOST/community-json-path/javascript \
>     -H content-type:application/json \
>     -H x-apiproduct:quota-operations-by-counter-1 \
>     --data-binary @apps.json

{
    "api_product":"quota-operations-by-counter-1",
    "client_ids":"["P8xgIzmVOrBVN98zbWLjUOKqX7aVBiVGBifE3BZOBsXXXXXX","5AXyS2KsdDY3y4ePBBf1KCCbhZiGAvO6GZdavMCJwXXXXXX"]"
}

 

That was a fun experiment, but I'm struggling with the use case for doing this in an API Proxy, why not just use jq on the result from GET /apps?expand=true > apps.json

jq '.app[] | .credentials[] | select(.apiProducts[]?.apiproduct == "quota-operations-by-counter-1") | .consumerKey' apps.json
"P8xgIzmVOrBVN98zbWLjUOKqX7aVBiVGBifE3BZOBsXXXXXX"
"5AXyS2KsdDY3y4ePBBf1KCCbhZiGAvO6GZdavMCJwCXXXXXX"

 

View solution in original post

5 REPLIES 5

Hi @KalyanLearner,

Just wanted to acknowledge your question—still no responses yet, but we’ll make sure it gets noticed and invite others to help out.

Thanks for the update @AlexET 

Hi @KalyanLearner 

As you can see from your example response from the GET /apps Apigee API call, it includes credentials for the API Product, not the API proxies that are in the API Product.

But I think you meant to say, when you call proxy2 with a header including the name of the API Product (e.g. x-apiproduct:Product1), then you could get the clientIds using that API Product.

I tried using Assign Message and Extract Variable policy with jsonPath, but was unable to get the predicate part to work, even using https://jsonpath.com.

This works using apiProducts[0], but only for the first occurance - $.app[*].credentials[?(@.apiProducts[0].apiproduct=='quota-operations-by-counter-1')].consumerKey

But this doesn't using apiProducts[*] -  $.app[*].credentials[?(@.apiProducts[*].apiproduct=='quota-operations-by-counter-1')].consumerKey

I resorted to using JavaScript and that worked.

 

 

function findConsumerKeys(data, targetProduct) {
  const consumerKeys = [];

  if (data && data.app && Array.isArray(data.app)) {
    data.app.forEach(app => {
      if (app.credentials && Array.isArray(app.credentials)) {
        app.credentials.forEach(credential => {
          if (credential.apiProducts && Array.isArray(credential.apiProducts)) {
            credential.apiProducts.forEach(product => {
              if (product.apiproduct === targetProduct) {
                consumerKeys.push(credential.consumerKey);
              }
            });
          }
        });
      }
    });
  }
  return consumerKeys;
}

const targetProduct = context.getVariable("request.header.x-apiproduct");
const jsonData = JSON.parse( context.getVariable('message.content') );
const client_ids = findConsumerKeys(jsonData, targetProduct);
context.setVariable("client_ids",JSON.stringify(client_ids));

 

 

Then my curl request using the result of GET /apps as the input

 

 

curl -X POST https://$HOST/community-json-path/javascript \
>     -H content-type:application/json \
>     -H x-apiproduct:quota-operations-by-counter-1 \
>     --data-binary @apps.json

{
    "api_product":"quota-operations-by-counter-1",
    "client_ids":"["P8xgIzmVOrBVN98zbWLjUOKqX7aVBiVGBifE3BZOBsXXXXXX","5AXyS2KsdDY3y4ePBBf1KCCbhZiGAvO6GZdavMCJwXXXXXX"]"
}

 

That was a fun experiment, but I'm struggling with the use case for doing this in an API Proxy, why not just use jq on the result from GET /apps?expand=true > apps.json

jq '.app[] | .credentials[] | select(.apiProducts[]?.apiproduct == "quota-operations-by-counter-1") | .consumerKey' apps.json
"P8xgIzmVOrBVN98zbWLjUOKqX7aVBiVGBifE3BZOBsXXXXXX"
"5AXyS2KsdDY3y4ePBBf1KCCbhZiGAvO6GZdavMCJwCXXXXXX"

 

Hi @kurtkanaskie 

Thanks for your reply. I will implement it and get back to you.

 

Thanks

 

Thanks a lot @kurtkanaskie .