Политика APIM для преобразования входящего запроса GET в запрос POST для моей серверной службы

ПРИМЕЧАНИЕ. СМОТРИТЕ МОЙ СОБСТВЕННЫЙ ОТВЕТ НИЖЕ

Я просматривал тонкую документацию часами. Мне нужно вот это:

У меня есть входящий запрос GET от системы, которая может отправлять ТОЛЬКО запросы GET. Моей внутренней службе требуется запрос POST.

Может ли кто-нибудь указать мне в правильном направлении в отношении того, какую политику APIM я должен использовать или комбинацию политик.

Я использую ссылку на политику, но все еще не могу найти достойного решения: https://msdn.microsoft.com/en-us/library/azure/dn894081.aspx


person RuSs    schedule 15.09.2016    source источник


Ответы (3)


Тег можно использовать для изменения метода HTTP для запроса. См. https://msdn.microsoft.com/en-us/library/azure/dn894085.aspx#SetRequestMethod для получения дополнительной информации.

person stackUser67    schedule 15.09.2016

Я нашел решение этого.

Вот сценарий: у меня есть требование, чтобы клиент вызвал конечную точку APIM и получил только простые ответы. т.е. .... аутентифицированный = истина / ложь.

У меня есть входящий запрос GET от системы, которая может отправлять ТОЛЬКО запросы GET. Моей внутренней службе требуется запрос POST.

Вот мой вызов GET от клиента, который может отправлять только запросы GET: https: /// api / v1 // 10010810? Pin = 1212 & property = Sydney & subscription-key = XXXXXXXXXXXXXX & debugging = 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>

The policy does the following:

В РАМКАХ

  • Записывает некоторые операторы трассировки повсюду
  • Получает пару параметров из строки запроса для использования в политике.
  • Удаляет пару параметров, поскольку мы не можем передать их в серверную службу, поскольку вызов не будет соответствовать сигнатуре метода.

BACK-END - Отправить запрос

  • Отправляет запрос в серверную службу, используя существующий URL-адрес, который был передан, но, очевидно, без параметров, которые мы удалили
  • Устанавливает метод POST
  • Устанавливает тело сообщения с помощью другого параметра

ВНЕЗАПНО

  • Если мы получили ответ 200, значит, мы знаем, что серверная служба работает правильно.
  • Настройте переменную под названием microservice-response для хранения ответа от серверной службы.
  • Установите переменную отладки, которая будет удалена в процессе производства. Это сделано для того, чтобы тестеры могли получить более подробную информацию. Мы отобразим им содержимое микросервиса-ответа.
  • Если что-то пошло не так с серверной службой (не ответ 200), то выдает ошибку

ПРИ ОШИБКЕ

  • Когда APIM фиксирует ошибку. Извлеките все детали из переменной context.LastError, и если в режиме отладки, то отправьте вызывающему

Вот пример context.LastError:  введите описание изображения здесь

Я надеюсь, что это поможет кому-то, так как мне потребовалось много времени, чтобы добраться до этого момента. Документация по этому поводу хороша, но там не так много

person RuSs    schedule 22.11.2016
comment
Вам не нужно использовать политику send-request в бэкэнде, вы можете просто поместить set-method и set-body в раздел inbound. Когда я ответил на ваш вопрос, я не знал, что вы тоже хотите создать тело. Я был бы рад помочь дальше. - person Darrel Miller; 24.11.2016
comment
Кроме того, вы можете использовать политику rewrite-uri с параметром copy-unmatched-params=false, чтобы предотвратить пересылку параметров строки запроса на серверную часть. Извините, этого параметра нет в документации. Это довольно новая функция, и в последнее время процесс документирования претерпел большие изменения, и некоторые вещи ускользнули из-под контроля. - person Darrel Miller; 24.11.2016
comment
@darrell. Спасибо за это. Я, наверное, не объяснял, что это будет. Я отмечу ваш комментарий, если смогу. Кроме того, есть ли шанс указать мне на дополнительные документы? Нравится форум и т. Д.? - person RuSs; 25.11.2016
comment
Хотел бы я указать вам больше, чем указано на aka.ms/apimdocs. К сожалению, в настоящий момент я не могу . Кроме того, вам может быть сложно найти некоторые старые страницы, так как появился новый docs.Microsoft.com, некоторые из страниц не появлялись на новом сайте. Я бы порекомендовал следить за блогом blogs.msdn.microsoft.com/apimanagement как сейчас мы регулярно обновляем это. Использование Stackoverflow - довольно хороший вариант, в нашей команде есть некоторые из нас, которые достаточно регулярно смотрят его, чтобы задать вопросы. - person Darrel Miller; 25.11.2016
comment
@DarrelMiller спасибо за это. PDF - это то, что я хотел бы найти раньше. Я также сейчас слежу за блогом APIM. Ура Русь - person RuSs; 25.11.2016

В разделе inbound политики для операции, которую вы хотите изменить, вы можете использовать политику set-method для изменения HTTP-метода запроса.

<inbound>
      <set-method>POST</set-method>
</inbound>
person Darrel Miller    schedule 21.09.2016