APIM策略将转换和传入GET请求转换为我的后端服务的POST请求

时间:2016-09-15 04:50:45

标签: azure-api-management policies

注意:请看下面我自己的答案

我一直在查看超薄文档几个小时。我需要的是:

我有来自只能发送GET请求的系统的传入GET请求。我的后端服务需要POST请求。

对于我应该使用的APIM政策或政策组合,有人能指出我正确的方向。

我正在使用政策参考,但仍无法提出合适的解决方案: https://msdn.microsoft.com/en-us/library/azure/dn894081.aspx

3 个答案:

答案 0 :(得分:1)

我找到了解决方法。

以下是该方案: 我要求客户端调用APIM端点,只返回简单的响应。即....认证=真/假。

我有一个来自系统的传入GET请求,该系统只能发送GET请求。我的后端服务需要POST请求。

以下是来自客户端的GET调用,该调用只能发送GET请求: HTTPS:/// API / V1 // 10010810销= 1212&安培;属性=悉尼&安培;订阅密钥= XXXXXXXXXXXXXX&安培;调试= 1

这是我的政策:

<policies>
<inbound>
    <set-header name="Content-Type" exists-action="override">
        <value>application/json</value>
    </set-header>
    <trace source="defaultTrace">
        @{
            return System.String.Format("The passed in querystring paramters were | pin: {0} | debugging: {1} | property: {2} | subscription-key: {3}", 
                context.Request.Url.Query.GetValueOrDefault("pin"), 
                context.Request.Url.Query.GetValueOrDefault("debugging"),
                context.Request.Url.Query.GetValueOrDefault("property"),
                context.Request.Url.Query.GetValueOrDefault("subscription-key")
                );
        }
    </trace>
    <set-variable name="requestPin" value="@(context.Request.Url.Query.GetValueOrDefault("pin"))" />
    <set-variable name="debugging" value="@(context.Request.Url.Query.GetValueOrDefault("debugging"))" />
    <trace source="defaultTrace">
        @{
            return System.String.Format(
            "Removing the following querystring parameters from url as we don't want to pass these ones to the backend service debugging: {0} | subscription-key: {1} | pin: {2}", 
                context.Request.Url.Query.GetValueOrDefault("debugging"),
                context.Request.Url.Query.GetValueOrDefault("subscription-key"),
                context.Request.Url.Query.GetValueOrDefault("pin")
                );
        }
    </trace>
    <set-query-parameter name="subscription-key" exists-action="delete" />
    <set-query-parameter name="debugging" exists-action="delete" />
    <set-query-parameter name="pin" exists-action="delete" />
    <base />
</inbound>
<backend>
    <!-- Setup a response-variable-name to hold the response from the backend service-->
    <send-request mode="copy" response-variable-name="microservice-response" timeout="20" ignore-error="false">
        <!-- Set the method to POST as the backend service MUST receive a POST call-->
        <set-method>POST</set-method>
        <set-body>
            @{
                // Get the pin from the url as we need it to construct the POST body
                var requestPin = context.Variables.GetValueOrDefault<string>("requestPin");

                var postBody = new JObject(
                    new JProperty("Type", "Pin"),
                    new JProperty("Value", requestPin)
                ).ToString();
                return postBody;
            }
        </set-body>
    </send-request>
</backend>
<outbound>
    <choose>
        <when condition="@(((IResponse)context.Variables["microservice-response"]).StatusCode == 200)">
            <!-- When the micro-service returned a valid response we put the response into the previously created variable called  microservice-response -->
            <return-response>
                <set-status code="200" reason="Ok" />
                <set-body>
                    @{
                        var debuggingVariable = context.Variables.GetValueOrDefault<string>("debugging");
                        var microserviceResponse = ((IResponse)context.Variables["microservice-response"]).Body.As<JObject>();

                        if(debuggingVariable == "1")
                        {
                            var returnResponse = new JObject(
                                new JProperty("Authenticated", true),
                                new JProperty("MicroserviceResponse", microserviceResponse),
                                new JProperty("StatusCode", ((IResponse)context.Variables["microservice-response"]).StatusCode)
                            ).ToString();
                            return returnResponse.ToString();
                        }
                        else
                        {
                            var returnResponse = new JObject(new JProperty("Authenticated", true)).ToString();
                            return returnResponse.ToString();
                        }
                    }
                </set-body>
            </return-response>
        </when>
        <when condition="@(((IResponse)context.Variables["microservice-response"]).StatusCode == 401)">
            <!-- When the micro-service returned a valid response we put the response into the previously created variable called  microservice-response -->
            <return-response>
                <set-status code="401" reason="Error" />
                <set-body>
                    @{
                        var debuggingVariable = context.Variables.GetValueOrDefault<string>("debugging");
                        var microserviceResponse = ((IResponse)context.Variables["microservice-response"]);

                        if(debuggingVariable == "1")
                        {
                            var returnResponse = new JObject(
                                new JProperty("Authenticated", false),
                                new JProperty("MicroserviceResponse", microserviceResponse.Body.As<JObject>().ToString()),
                                new JProperty("StatusCode", ((IResponse)context.Variables["microservice-response"]).StatusCode)
                            ).ToString();
                            return returnResponse.ToString();
                        }
                        else
                        {
                            var returnResponse = new JObject(new JProperty("Authenticated", false)).ToString();
                            return returnResponse.ToString();
                        }
                    }
                </set-body>
            </return-response>
        </when>
        <when condition="@(((IResponse)context.Variables["microservice-response"]).StatusCode == 400)">
            <!-- When the micro-service returned a valid response we put the response into the previously created variable called  microservice-response -->
            <return-response>
                <set-status code="200" reason="Ok" />
                <set-body>
                    @{
                        var debuggingVariable = context.Variables.GetValueOrDefault<string>("debugging");
                        var microserviceResponse = ((IResponse)context.Variables["microservice-response"]);

                        if(debuggingVariable == "1")
                        {
                            var returnResponse = new JObject(
                                new JProperty("Authenticated", false),
                                new JProperty("MicroserviceResponse", microserviceResponse.Body.As<JObject>().ToString()),
                                new JProperty("StatusCode", ((IResponse)context.Variables["microservice-response"]).StatusCode)
                            ).ToString();
                            return returnResponse.ToString();
                        }
                        else
                        {
                            var returnResponse = new JObject(new JProperty("Authenticated", false)).ToString();
                            return returnResponse.ToString();
                        }
                    }
                </set-body>
            </return-response>
        </when>
        <otherwise>
            <return-response>
                <!-- When the micro-service threw an exception we just want to show the caller Authenticated = false -->
                <!--<set-status code="500" reason="Error" />-->
                <set-body>
                        @{
                            var debuggingVariable = context.Variables.GetValueOrDefault<string>("debugging");
                            var microserviceResponse = ((IResponse)context.Variables["microservice-response"]);

                            if(debuggingVariable == "1")
                            {
                                var returnResponse = new JObject(
                                    new JProperty("Authenticated", false),
                                    new JProperty("MicroserviceResponse", microserviceResponse.Body.As<JObject>().ToString()),
                                    new JProperty("StatusCode", ((IResponse)context.Variables["microservice-response"]).StatusCode)
                                ).ToString();
                                return returnResponse.ToString();
                            }
                            else
                            {
                                var returnResponse = new JObject(new JProperty("Authenticated", false)).ToString();
                                return returnResponse.ToString();
                            }
                        }
                </set-body>
            </return-response>
        </otherwise>
    </choose>
    <base />
</outbound>
<on-error>
    <!-- When APIM threw an exception -->
    <trace source="defaultTrace">
        @{
            var returnResponse = new JObject
                (
                    new JProperty("Authenticated", false),
                    new JProperty("Source", context.LastError.Source),
                    new JProperty("Reason", context.LastError.Reason),
                    new JProperty("Message", context.LastError.Message),
                    new JProperty("Scope", context.LastError.Scope),
                    new JProperty("Section", context.LastError.Section),
                    new JProperty("Path", context.LastError.Path),
                    new JProperty("PolicyId", context.LastError.PolicyId)
                ).ToString();
            return returnResponse.ToString();
        } 
    </trace>
    <return-response>
        <set-status code="500" reason="Error" />
        <set-body>
            @{
                var debuggingVariable = context.Variables.GetValueOrDefault<string>("debugging");
                if(debuggingVariable == "1")
                {
                    var returnResponse = new JObject
                        (
                            new JProperty("Authenticated", false),
                            new JProperty("Source", context.LastError.Source),
                            new JProperty("Reason", context.LastError.Reason),
                            new JProperty("Message", context.LastError.Message),
                            new JProperty("Scope", context.LastError.Scope),
                            new JProperty("Section", context.LastError.Section),
                            new JProperty("Path", context.LastError.Path),
                            new JProperty("PolicyId", context.LastError.PolicyId)
                        ).ToString();
                    return returnResponse.ToString();
                }
                else
                {
                    var returnResponse = new JObject(new JProperty("Authenticated", false)).ToString();
                    return returnResponse.ToString();
                }
            }
        </set-body>
    </return-response>
</on-error>

该政策执行以下操作:

<强>入境

  • 在整个
  • 中编写一些跟踪语句
  • 从查询字符串中获取一些参数,以便在策略中使用
  • 删除一些参数,因为我们无法将这些参数传递给后端服务,因为调用与方法签名不匹配

后端 - 发送请求

  • 使用已通过的现有网址向后端服务发送请求,但显然没有我们删除的参数
  • 将方法设置为POST
  • 使用其他参数
  • 设置邮件正文

<强>出境

  • 如果我们得到200响应,那么我们知道后端服务正常运行
  • 设置一个名为 microservice-response 的变量来存储来自后端服务的响应
  • 设置一个将在生产中删除的调试变量。这样测试人员可以获得更详细的信息。我们将向他们显示微服务响应的内容
  • 如果后端服务出现问题(不是200响应),则抛出错误

打开-错误

  • 当APIM捕获错误时。从context.LastError变量中提取所有细节,如果在调试模式下,则发送给调用者

以下是context.LastError的示例: enter image description here

我希望这对某人有所帮助,因为我花了很长时间才达到这一点。关于这方面的文件是好的,但没有太多

答案 1 :(得分:0)

您可以使用标记更改请求的HTTP方法。 有关详细信息,请参阅https://msdn.microsoft.com/en-us/library/azure/dn894085.aspx#SetRequestMethod

答案 2 :(得分:-1)

在要更改的操作的策略的inbound部分中,您可以使用set-method策略更改请求的HTTP方法。

<inbound>
      <set-method>POST</set-method>
</inbound>