【问题标题】:How Can I Reuse the Response Context Variable in Azure API Management Policy?如何在 Azure API 管理策略中重用响应上下文变量?
【发布时间】:2020-05-14 16:13:29
【问题描述】:

我正在使用 Azure API 管理解决方案编写概念证明。

我正在尝试编写一个 <inbound> 策略,它执行以下操作:

  • 使用 <send-request> 向 API 的身份验证端点发出请求。
  • 身份验证 API 返回两个密钥,它们必须作为 http 标头包含在内,以便能够向其他端点发出后续请求。
  • 我正在使用 JObject 将来自身份验证 API 的响应解析为 json
  • 然后我尝试从 json 对象的两个属性中读取值(它们是字符串)
  • 然后,我将向不同的 API 端点发出后续请求,并设置两个 http 标头。标头的值必须是第一个(身份验证)响应中的两个变量。

这是我的政策目前的样子:

<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>

我遇到的问题是设置第二个标头(令牌 B)的值。看来我不能重用上下文变量(IResponse)context.Variables["auth"]。

当我查看跟踪时,我看到第一个 &lt;set-header&gt; 策略的以下输出:

"message":"表达式评估成功。", “价值”:“xxxxxxxxxxxxxxxxxxxxx”

但是对于第二个&lt;set-header&gt; 政策,我得到:

"message":"表达式评估失败。", "details":"对象引用未设置为对象的实例。"

我可以看到,在第一个策略上调用方法后,我不再能够在第二个&lt;set-header&gt; 策略中以相同的方式重用上下文变量。

我试过了:

  • 使用&lt;set-variable&gt; 设置令牌字符串。我相信&lt;set-variable&gt; 可以返回的类型数量有限,我无法返回IResponse 或JObject。如果我尝试转换为 json,然后提取每个属性(TokenA 和 TokenB)的字符串,我会遇到与上述相同的问题。

有人可以帮助我复制IResponse 对象或JObject 的语法,以便我可以使用.SelectToken() 读取它两次吗?我确定我误解了一个基本概念,但我远非一个经验丰富的 C# 开发人员!

谢谢

【问题讨论】:

    标签: c# azure-api-management api-management apim


    【解决方案1】:

    您收到错误的原因是您阅读响应正文的方式。当您将正文阅读为

    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"

    【讨论】:

    • 完美答案。谢谢曼达尔。不知道我是如何在文档中错过它的。
    • JObject 应该被支持作为变量的值。所以你应该能够做到 ()"/> 并稍后使用 tokens 变量.好处是您将解析一次 body。
    • 如果不是因为这个,我可能永远找不到答案
    猜你喜欢
    • 2023-01-28
    • 1970-01-01
    • 1970-01-01
    • 2020-06-11
    • 1970-01-01
    • 2018-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多