Need to modify response using Azure APIM set-body policy - azure

I am relatively new to Azure APIM and I have this backend which I am able to invoke which returns the response in format
{
"data": {
"attributes": {
"municipalities": []
}
}
}
I want to modify the response so that the data is returned in the format
{
"data": {
"municipalities": []
}
}
I have tried using the set body liquid template
<outbound>
<set-body template="liquid">
{
"data": {
"municipalities": {{body.data.attributes.municipalities}}
}
}</set-body>
</outbound>
But the response I get is just
{
"data": {
"municipalities":
}
}
If someone can point out to me what I am doing wrong or if there is a better way to do this?
I also tried to use the below code just to check if I am able to retrieve the "data" attribute but I got the below error in the trace part of Azure APIM Test
<outbound>
<set-body>
#{
JObject inBody = context.Request.Body.As<JObject>();
return inBody["data"].ToString();
}
</set-body>
</outbound>
ERROR:
{
"messages": [
{
"message": "Expression evaluation failed.",
"expression": " \n JObject inBody = context.Request.Body.As<JObject>();\n return inBody[\"data\"].ToString(); \n",
"details": "Object reference not set to an instance of an object."
},
"Expression evaluation failed. Object reference not set to an instance of an object.",
"Object reference not set to an instance of an object."
]
}

As body.data.attributes.municipalities is a array, we can't put it "municipalities": directly. For your requirement of modify the format of the json data, we need to write every property of each array item. Below is my steps for your reference.
My json is:
{
"data": {
"attributes": {
"municipalities": [
{
"name": "hury",
"email": "hury#mail.com"
},
{
"name": "mike",
"email": "mike#email.com"
}
]
}
}
}
And my liquid template show as:
==============================Update============================
First the code JObject inBody = context.Request.Body.As<JObject>(); you shared can't get the response data. You should use JObject inBody = context.Response.Body.As<JObject>();.
Then for your question about "Is there an easier way to remove .attributes part, I provide a solution below for your reference.
Do not use liquid template, use Replace to replace "attributes": { with empty and use Substring to remove the last }.
<set-body>#{
JObject inBody = context.Response.Body.As<JObject>();
string str = inBody.ToString();
string str1 = str.Replace("\"attributes\": {", "");
string result = str1.Substring(0, str1.Length-1);
return result;
}</set-body>
Notice: This approach requires a high degree of specification for your response data format.

I also managed to get the desired output with the below code, so that the code is generic and doesnt need to do any string operations.
<set-body>#{
JToken inBody = context.Response.Body.As<JToken>()["data"]["attributes"];
JObject jsonObject = new JObject{
["data"] = inBody
};
return jsonObject.ToString();
}</set-body>

Related

manipulate response in apim outbound policies

I have SOAP service that I have converted to rest in apim and returns the response in json using the following outbound policy:
<outbound>
<base />
<xml-to-json kind="direct" apply="always" consider-accept-header="false" />
</outbound>
Response output is like below:
"response": {"currentABNRecord": {
"ABN":
{
"identifierValue": "xxxxx",
"identifierStatusCode": "ACT",
"issuingPartyCode": null,
"replacedIndicator": "N"
}
}
}
My requirement is to "manipulate" conditionally data by modifying "identifierStatusCode" and appending a new attribute "termsAnConditions" when "identifierStatusCode" is "ACT" and if it is DEL to "DELETED" to something else like below :
"response": {"currentABNRecord": {
"ABN":
{
"identifierValue": "xxxxx",
"identifierStatusCode": "ACT",
"issuingPartyCode": null,
"replacedIndicator": "N",
"termsAnConditions": "Some terms and conditions"
}
}
}
How can I call an azure function(perform all the conditional logic in it ) in the outbound policy and return the modified object. Is this the correct approach or can I do it policies.

How to retrieve Id from the response which suddenly fails

We are using MS Graph api to collect Ad user information. One of our method suddenly stop working when using our groovy script.
Actually when calling the Graph API url from POSTMAN directly for requesting user information we receive the following response
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users",
"value": [
{
"businessPhones": [],
"displayName": "Rhea Sam",
"givenName": null,
"jobTitle": null,
"mail": "user#mydoamin.com",
"mobilePhone": null,
"officeLocation": null,
"preferredLanguage": null,
"surname": null,
"userPrincipalName": "user#mydoamin.com#EXT##rlxcom.onmicrosoft.com",
"id": "05906321-ed38-4bfd-9c9e-02bfb7d32405"
}
]
}
Until now our groovy script call for that same API was working well but then suddenly stop working
Here is calling method code we are using
public String getGuestUserId(String AuthToken,String userEmail){
String _userId
def http = new HTTPBuilder("https://graph.microsoft.com/v1.0/users/?")
http.request(GET) {
requestContentType = ContentType.JSON
//uri.query = [ $filter:"mail eq '$userEmail'"].toString()
uri.query=[$filter:"mail eq '$userEmail'"]
headers.'Authorization' = "Bearer " + AuthToken
response.success = { resp, json ->
if (**json.value**){
_userId=**json.value**[0].id
}
else
_userId=-1 // user does not exist
}
// user ID not found : error 404
response.'404' = { resp ->
_userId = 'Not Found'
}
}
_userId
}
What is happening when executing this method now is that the json.value return an error saying :
"No such property: value for class: java.lang.Object"
Note that if we try to return just the json.toString() then it return only
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users",
"value": []
What is wrong and how to solve it as it is suppose to return same information as the POSTMAN response in which we are concerned only to retrive the Id of teh user from the response
Thanks for your help
regards

Groovy and Spring Cloud Contract - Variable in the bodyAsValue

I would like to know how am I supposed to create in Groovy the Json payload with a random value.
For example
Contract.make {
name"MyFirstContract"
description "A description"
request {
method "POST"
url "/api/team/createTeam"
headers {
contentType applicationJson()
accept applicationJson()
header"Authorization", execute('bearerOfAccessToken()')
}
body """ {
"authenticatedUserCode":"papas",
"input": {
"name":"${execute('generateTeamUniqueName()')}",
"teamDefinitionName": "JUNIT TEST NAME",
"context":"context AHO",
"description":"team Description",
"members":
[
{"role":"Junit Reviewer",
"memberType":"USER",
"reference":"papas"
},
{"role":"Junit Observer",
"memberType":"USER",
"reference":"papas"
},
{"role":"Junit Collaborator",
"memberType":"USER",
"reference":"papas"
},
{"role":"Junit Reviewer",
"memberType":"USER",
"reference":"papas"
}
]
} } """
}
The important part from the previous code is the following that fails during compilation.
"name":"${execute('generateTeamUniqueName()')}",
with the following error message:
Execution default-generateTests of goal org.springframework.cloud:spring-cloud-contract-maven-plugin:3.0.2:gener
ateTests failed: expecting '}' or ',' but got current char 'E' with an int value of 69
Is it possible to call a method inside the body or I have to return the ALL the contents of the body through the same method???
Thank you!
You have to call it for the whole body, it won't work for part of it

Copy a file, rename in case it exists using MS Graph for Onedrive/Sharepoint

I am copying a file from one drive to another. As part of the body request, I am also providing conflictBehavior as rename (tried with replace as well) but the copy is failing.
POST: https://graph.microsoft.com/beta/users/{user-id}/drive/items/{item-id}/copy
Body:
{
"parentReference": {"id": {folder-id-to-copy}, "driveId": {drive-id},
"#microsoft.graph.conflictBehavior": "rename"
}
After executing above command, as expected I get a 202 and in the header I look at Location. When querying the monitor URL, I see the below error:
{
"#odata.context": "https://{host-name}/_api/v2.1/$metadata#drives('default')/operations/$entity",
"id": "7a0decd4-df2f-4717-8eee-b7c2cd131009",
"createdDateTime": "0001-01-01T00:00:00Z",
"lastActionDateTime": "0001-01-01T00:00:00Z",
"status": "failed",
"error": {
"code": "nameAlreadyExists",
"message": "Name already exists"
}
}
What to pass in order to rename/replace existing file while copying
If you are trying to rename it with special name, then try this.
POST /users/{user-id}/drive/items/{item-id}/copy
Content-Type: application/json
{
"parentReference": {
"id": {folder-id-to-copy}, "driveId": {drive-id},
},
"name": "your_file_name (copy).txt"
}
Reference here: https://learn.microsoft.com/en-us/graph/api/driveitem-copy?...
And if you want to rename the file automatically, then try this using Instance Attributes.
POST /users/{user-id}/drive/items/{item-id}/copy?#microsoft.graph.conflictBehavior=rename
Content-Type: application/json
{
"name": "{filename}"
}
name should be provided.
if you are using GraphServiceClient, you can do the following:
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var parentReference = new ItemReference
{
DriveId = "6F7D00BF-FC4D-4E62-9769-6AEA81F3A21B",
Id = "DCD0D3AD-8989-4F23-A5A2-2C086050513F"
};
// To resolve the issue: Code: nameAlreadyExists Message: The specified item name already exists. Copy
List<QueryOption> options = new List<QueryOption>
{
new QueryOption("#microsoft.graph.conflictBehavior", "rename")
};
var name = "contoso plan (copy).txt";
await graphClient.Me.Drive.Items["{driveItem-id}"]
.Copy(name,parentReference)
.Request(options)
.PostAsync();
Ref https://learn.microsoft.com/en-us/graph/api/driveitem-copy?view=graph-rest-1.0&tabs=csharp

How to iterate through each property element in API response in Katalon studio?

I'm writing test script in katalon studio to verify response body of the API.My response body is of format:
{
"status": "Success",
"correlationCode": "1234-5678",
"type": {
"id": 51247,
"name": "Student",
},
"data": {
"name": "Sara Nieves",
"gender": "Female",
"dob": "1995-08-06",
"libraryCard": {
"id": "11178",
"type": "Seniors"
},
"qualifications": [
{
"id": "45650986546",
"name": "Graduate Certificate in Environmental Engineering Management"
}
]
}
}
I want to verify that none of the elements return 'null' value. Since, the elements returned for the API response are not static(meaning name, gender etc might not get returned every time) therefore, i can't use something like "data.name" to verify if it has null value. So, i want a generic way to loop through each and every attribute returned and check if its value is returned as null or not.
Any help will be much appreciated. Thanks!
You have the error message:
groovy.lang.MissingMethodException: No signature of method: WSVerification1569811424284$_run_closure1.doCall() is applicable for argument types: (com.kms.katalon.core.testobject.ResponseObject) values: [200 1 KB] 22572.groovy:21)
I assume your response object type: com.kms.katalon.core.testobject.ResponseObject
The code to parse response as json and validate it:
import groovy.json.JsonSlurper
/**
* the recursive method to validate that json object does not have null values
* #param obj - the parsed json object (sequence of maps and lists)
* #param path - a variable to know where the error occurred in json data.
*/
void assertNoNullValue(Object obj, String path='ROOT'){
//the main assertion
assert obj!=null : "value in json could not be null: $path"
if(obj instanceof Map){
//iterate each key-value in map and validate the value recursively
obj.each{k,v-> assertNoNullValue(v,path+".$k") }
} else if(obj instanceof List){
//iterate each value in list and validate the value recursively
obj.eachWithIndex{v,i-> assertNoNullValue(v,path+"[$i]") }
}
}
def response = ...
assert response.isJsonContentType()
def responseText = response.getResponseText()
//parse body
def data = new JsonSlurper().parseText(responseText)
assertNoNullValue(data)
This solution is not as precise as the one suggested by #dagget, but it is a quick check:
def response = '''
{
"status": "Success",
"correlationCode": "1234-5678",
"type": {
"id": 51247,
"name": "Student",
},
"data": {
"name": "Sara Nieves",
"gender": "femmina",
"dob": "1995-08-06",
"libraryCard": {
"id": "11178",
"type": "Seniors"
},
"qualifications": [
{
"id": "45650986546",
"name": "Graduate Certificate in Environmental Engineering Management"
}
]
}
}
'''
assert !response.contains("null")

Resources