UDG Reusing and parsing response field

Related to this documentation Concepts - Reusing response fields
where we can reuse the response by object.field to hit another API. If the field is array, can we iterate/parse the response like in Request Body to insert it to the body to hit the other API.

For example:
API A return
{ item_data : [ {id:1,variant:a}, {id:2,variant:c} ] }

and then we want to hit API B from the A result
request body :

{
   ids : [1,2]
}

Hey @midnight ,

in order to answer you I had to make a couple of assumptions, so if I misunderstood something, just let me know.

First you need to “translate” the JSON response from API A, to GQL schema. Your response is:

{
    "item_data": [
        {
            "id": 1,
            "variant": "a"
        },
        {
            "id": 2,
            "variant": "c"
        }
    ]
}

So GQL schema would probably be something like:

type ItemData {
  id: Int
  variant: String
}

type Query {
  item_data: [ItemData]
}

That’s API A taken care of. You the attach the datasource to item_data: [ItemData] field.
I assume now you want to get more information about each item from API B, right? SO your GQL schema needs to grow like this:

type ItemData {
  id: Int
  variant: String
  additionalInfoFromAPIB: Additional
}

type Additional {
  field1: String
  field2: Int
  fieldN:...
}

type Query {
  item_data: [ItemData]
}

Now you can attach your API B to additionalInfoFromAPIB: Additional field and use a URL like this:

http://apib.com/items?id={{.object.id}}

That’s how you would extend the information from API A with data from API B that’s correctly connected with the item id.

hi @agata-wit , thanks for the fast response :slight_smile: Yes I want to achieve something like that ; but what if the API B receives the ids in bulk. The solution provided forces us to get the item one by one.

So what if I want the GQL Schema to be like this

type ItemData {
  id: Int
  variant: String
}

type Additional {
  field1: String
  field2: Int
  fieldN:...
}

type Query {
  item_data: [ItemData]
  additionalInfoFromAPIB: [Additional]
}

So API B receives request as:

{
   ids : [1,2]
}

where the ids comes from the itemdata array.

Well i don’t know if it is a good practice , but what i’m curious about is :
can we do iteration and conditional by reusing UDG’s response fields? like in body transform

   {{range $index, $element := .value_list}}
        {{if $index}}
        , "{{$element}}"
        {{else}}
          "{{$element}}"
        {{end}}
    {{end}}

Yeah, you’re spot on - my way will mean fetching data one-by-one for each id.

But then what you typed out in that schema wouldn’t work either. Now additionalInfoFromAPIB is a query that returns an array of type Additional (I’m captain obvious here, sorry for that!).
You definitely need a query variable here, right? The ids? Like:

type Query {
  item_data: [ItemData]
  additionalInfoFromAPIB(ids:[Int]): [Additional]
}

So you will get ids by executing query item_data and then you want to take that array of ids and feed it as a parameter to the next query additionalInfoFromAPIB(ids:[Int]). Then data source for this query would be: http://apib.com/items?id={{.argument.ids}}

The first problem I see is that item_data' and 'additionalInfoFromAPIB are two separate queries, they are not aware of each other, so UDG (or GQL itself really) will not be able to get a response from query1, transform it (like body transform) and use it in query2.
You could probably write a script it outside of Tyk with steps like:

  1. Execute query1 on URL:
  2. Take query1 response and extract array of ids
  3. Execute query2 on URL:
    Unfortunately step 2 is currently not possible in Tyk.

I think what could be a solution here, is something we have on our roadmap which goes under the working title of: Batching requests in UDG. In simple terms it means we want UDG to be intelligent enough to know that it’ll have to do multiple requests to the same endpoint with different parameters each time (in your case, different ids to API B) and when this kind of case is detected in the query planner, UDG will “wait” for all ids and then send one API B request like this:

http://apib.com/items?id=id1,id2,id3,id4,...

instead of multiple like this:

http://apib.com/items?id=id1
http://apib.com/items?id=id2
...

Granted that REST API B supports an array of Int or String or whatever as path/query parameter.

I see… thanks for your response… do you have an estimation about when will the Batching requests in UDG rollsout :smiley: ?

What about iteration and conditional on UDG’s response field? is that possible?
I mean , with the schema you gave , we can use {{.object.id}} in POST body instead of in the parameter right? Can we do some logic there?