如何在 Azure API 管理策略中重用响应上下文变量?
How Can I Reuse the Response Context Variable in Azure API Management Policy?
我正在使用 Azure API 管理解决方案编写概念证明。
我正在尝试编写执行以下操作的 <inbound>
政策:
- 使用
<send-request>
向 API 的身份验证端点发出请求。
- 身份验证 API returns 两个密钥必须包含在 http headers 中才能向其他端点发出后续请求。
- 我正在使用
JObject
将身份验证 API 的响应解析为 json
- 然后我尝试从 json object 的两个属性中读取值(它们是字符串)
- 然后,我将向不同的 API 端点发出后续请求,并设置两个 http headers。 headers 的值必须是来自第一个(身份验证)响应的两个变量。
这是我目前的政策:
<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>
我遇到的问题是为第二个 header(令牌 B)设置值。看来我不能 re-use 上下文变量 (IResponse)context.Variables["auth"]
.
当我查看跟踪时,我看到第一个 <set-header>
策略的以下输出:
"message":"Expression was successfully evaluated.",
"value":"xxxxxxxxxxxxxxxxxxxxx"
但是对于第二个 <set-header>
政策,我得到:
"message":"Expression evaluation failed.",
"details":"Object reference not set to an instance of an object."
我可以看到,在第一个策略上调用方法后,我无法再在第二个 <set-header>
策略中以相同的方式重用上下文变量。
我试过:
- 使用
<set-variable>
设置令牌字符串。我相信 <set-variable>
可以 return 的类型数量有限,而我不能 return IResponse
或 JObject
。如果我尝试转换为 json 然后提取每个 属性 (TokenA 和 TokenB)的字符串,我会遇到与上述相同的问题。
有人可以帮我解决语法问题,让我可以复制 IResponse
object 或 JObject
以便我可以使用 .SelectToken()
阅读两次吗?我确定我误解了一个基本概念,但我远不是经验丰富的 C# 开发人员!
谢谢
您收到错误的原因是您阅读响应正文的方式。当您阅读正文时
JObject identity = ((IResponse)context.Variables["auth"]).Body.As<JObject>();
你基本上是从上下文变量中处理正文。因此,下次您读取变量主体时,它会抛出臭名昭著的 Object reference
错误。要在 Azure API 管理中读取主体,您需要在代码中使用 preservecontent
属性。所以你将阅读正文如下所示
JObject identity = ((IResponse)context.Variables["auth"]).Body.As<JObject>(preserveContent: true);
执行此操作时,将保留原始正文,并且在求值中仅注入正文的副本。
您可以在以下位置找到有关此内容的深入文档
"Set Body- APIM policy"
我正在使用 Azure API 管理解决方案编写概念证明。
我正在尝试编写执行以下操作的 <inbound>
政策:
- 使用
<send-request>
向 API 的身份验证端点发出请求。 - 身份验证 API returns 两个密钥必须包含在 http headers 中才能向其他端点发出后续请求。
- 我正在使用
JObject
将身份验证 API 的响应解析为 json
- 然后我尝试从 json object 的两个属性中读取值(它们是字符串)
- 然后,我将向不同的 API 端点发出后续请求,并设置两个 http headers。 headers 的值必须是来自第一个(身份验证)响应的两个变量。
这是我目前的政策:
<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>
我遇到的问题是为第二个 header(令牌 B)设置值。看来我不能 re-use 上下文变量 (IResponse)context.Variables["auth"]
.
当我查看跟踪时,我看到第一个 <set-header>
策略的以下输出:
"message":"Expression was successfully evaluated.", "value":"xxxxxxxxxxxxxxxxxxxxx"
但是对于第二个 <set-header>
政策,我得到:
"message":"Expression evaluation failed.", "details":"Object reference not set to an instance of an object."
我可以看到,在第一个策略上调用方法后,我无法再在第二个 <set-header>
策略中以相同的方式重用上下文变量。
我试过:
- 使用
<set-variable>
设置令牌字符串。我相信<set-variable>
可以 return 的类型数量有限,而我不能 returnIResponse
或JObject
。如果我尝试转换为 json 然后提取每个 属性 (TokenA 和 TokenB)的字符串,我会遇到与上述相同的问题。
有人可以帮我解决语法问题,让我可以复制 IResponse
object 或 JObject
以便我可以使用 .SelectToken()
阅读两次吗?我确定我误解了一个基本概念,但我远不是经验丰富的 C# 开发人员!
谢谢
您收到错误的原因是您阅读响应正文的方式。当您阅读正文时
JObject identity = ((IResponse)context.Variables["auth"]).Body.As<JObject>();
你基本上是从上下文变量中处理正文。因此,下次您读取变量主体时,它会抛出臭名昭著的 Object reference
错误。要在 Azure API 管理中读取主体,您需要在代码中使用 preservecontent
属性。所以你将阅读正文如下所示
JObject identity = ((IResponse)context.Variables["auth"]).Body.As<JObject>(preserveContent: true);
执行此操作时,将保留原始正文,并且在求值中仅注入正文的副本。 您可以在以下位置找到有关此内容的深入文档 "Set Body- APIM policy"