Reputation: 653
I'm writing a proof of concept utilising the Azure API Management solution.
I am trying to write an <inbound>
policy which does the following:
<send-request>
to make a request to an authentication endpoint of an API.JObject
This is what my policy looks like currently:
<inbound>
<base />
<!-- Authenticate with the API and get authentication tokens for subsequent calls -->
<send-request mode="new" response-variable-name="auth" timeout="20" ignore-error="true">
<set-url>https://www.service.com/api/authenticate</set-url>
<set-method>POST</set-method>
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>
@{
var credentials = new JObject();
credentials.Add(new JProperty("logonId", "{{API_LOGON_USERNAME}}"));
credentials.Add(new JProperty("logonPassword", "{{API_LOGON_PASSWORD}}"));
return credentials.ToString();
}
</set-body>
</send-request>
<!-- Make second query to a different endpoint, using the authentication tokens as http headers -->
<send-request mode="new" response-variable-name="data" timeout="20" ignore-error="true">
<set-url>https://www.service.com/api/data</set-url>
<set-method>GET</set-method>
<set-header name="TokenA" exists-action="override">
<value>
@{
JObject identity = ((IResponse)context.Variables["auth"]).Body.As<JObject>();
return identity.SelectToken("TokenA").ToString();
}
</value>
</set-header>
<set-header name="TokenB" exists-action="override">
<value>
@{
JObject identity = ((IResponse)context.Variables["auth"]).Body.As<JObject>();
return identity.SelectToken("TokenB").ToString();
}
</value>
</set-header>
</send-request>
<!-- Return response from the second API -->
<return-response response-variable-name="responseData">
<set-status code="200" reason="OK" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>
@{
JObject api_response = ((IResponse)context.Variables["data"]).Body.As<JObject>();
return api_response.ToString();
}
</set-body>
</return-response>
</inbound>
The issue I am having is around setting the value for the second header (Token B). It appears that I cannot re-use the context variable (IResponse)context.Variables["auth"]
.
When I review the trace, I see the following output for the first <set-header>
policy:
"message":"Expression was successfully evaluated.", "value":"xxxxxxxxxxxxxxxxxxxxx"
But for the second <set-header>
policy I get:
"message":"Expression evaluation failed.", "details":"Object reference not set to an instance of an object."
I can see that, after calling the method on the first policy, I am no longer able to reuse the context variable in the same way in the second <set-header>
policy.
I have tried:
<set-variable>
. I believe there are a limited number of types that <set-variable>
can return, and I cannot return the IResponse
or the JObject
. If I attempt to convert to json then extract the string of each property (TokenA and TokenB) I get the same issue as above.Could someone please help me with the syntax to allow me to copy the IResponse
object or the JObject
so that I can read it twice using .SelectToken()
? I'm sure I'm misunderstanding a fundamental concept, but I am far from a seasoned C# developer!
Thanks
Upvotes: 4
Views: 9248
Reputation: 1119
The reason you are getting the error is because of the way you are reading the response body. when you read the body as
JObject identity = ((IResponse)context.Variables["auth"]).Body.As<JObject>();
you are basically disposing of the body from the context variable. Hence the next time you read the variable body, it throws the infamous Object reference
error. To work with reading the bodies in Azure API management, you need to use the preservecontent
property in your code. SO you will read the body as shown below
JObject identity = ((IResponse)context.Variables["auth"]).Body.As<JObject>(preserveContent: true);
When you do this, the original body is preserved and only a copy of the body is injected in the evaluation. You can find in depth documentation about this at "Set Body- APIM policy"
Upvotes: 10