Azure API Management policy: test if param in request body exist

Viewed 93

I am trying to check if a param exists in the body of the POST request. But i get the following error :

{
  "messages": [
    {
      "message": "Expression evaluation failed.",
      "expression": "(string)context.Variables[\"param1\"] != null || ((string)context.Variables[\"param2\"] != null) || ((string)context.Variables[\"param3\"] != null) || ((string)context.Variables[\"param4\"] != null)",
      "details": "Unable to cast object of type 'Newtonsoft.Json.Linq.JValue' to type 'System.String'."
    },
    "Expression evaluation failed. Unable to cast object of type 'Newtonsoft.Json.Linq.JValue' to type 'System.String'.",
    "Unable to cast object of type 'Newtonsoft.Json.Linq.JValue' to type 'System.String'."
  ]
}

I define values like this :

<set-variable name="param1" value="@(context.Request.Body.As<JValue>(preserveContent: true).GetValueOrDefault("param1", null))" />
<set-variable name="param2" value="@(context.Request.Body.As<JValue>(preserveContent: true).GetValueOrDefault("param2", null))" />
<set-variable name="param3" value="@(context.Request.Body.As<JValue>(preserveContent: true).GetValueOrDefault("param3", null))" />
<set-variable name="param4" value="@(context.Request.Body.As<JValue>(preserveContent: true).GetValueOrDefault("param4", null))" />

This is my test code :

<when condition="@((string)context.Variables["param"] != null || ((string)context.Variables["param2"] != null) 
  || ((string)context.Variables["param3"] != null) || ((string)context.Variables["param4"] != null))">
...
</when>

This is what I send in the post body :

{"param2":false}

I also tried with

context.Request.Body.As<JObject> 

but I got the same error.

And also with just :

<set-variable name="param1" value="@(context.Request.Body.As<JObject>(preserveContent: true).GetValue("param1"))" />

What should I do?

1 Answers

This solution works for following request body:

{
    "param2": "",
    "param3": null,
    "param4": "lorem"
}

The policy checks if a parameter exists, is null or is empty. In case, the validation fails, a message will be set and returned.

<policies>
    <inbound>
        <base />
        <choose>
            <when condition="@(context.Request.Body.As<JObject>(true)["param1"] == null || context.Request.Body.As<JObject>(true)["param1"].Type == JTokenType.Null || string.IsNullOrEmpty(context.Request.Body.As<JObject>(true)["param1"].Value<string>()) )">
                <set-variable name="message" value="@(context.Variables.GetValueOrDefault<string>("message") +  "param1 missing! ")" />
            </when>
        </choose>
        <choose>
            <when condition="@(context.Request.Body.As<JObject>(true)["param2"] == null || context.Request.Body.As<JObject>(true)["param2"].Type == JTokenType.Null || string.IsNullOrEmpty(context.Request.Body.As<JObject>(true)["param2"].Value<string>()) )">
                <set-variable name="message" value="@(context.Variables.GetValueOrDefault<string>("message") +  "param2 missing! ")" />
            </when>
        </choose>
        <choose>
            <when condition="@(context.Request.Body.As<JObject>(true)["param3"] == null || context.Request.Body.As<JObject>(true)["param3"].Type == JTokenType.Null || string.IsNullOrEmpty(context.Request.Body.As<JObject>(true)["param3"].Value<string>()) )">
                <set-variable name="message" value="@(context.Variables.GetValueOrDefault<string>("message") +  "param3 missing! ")" />
            </when>
        </choose>
        <choose>
            <when condition="@(context.Request.Body.As<JObject>(true)["param4"] == null || context.Request.Body.As<JObject>(true)["param4"].Type == JTokenType.Null || string.IsNullOrEmpty(context.Request.Body.As<JObject>(true)["param4"].Value<string>()) )">
                <set-variable name="message" value="@(context.Variables.GetValueOrDefault<string>("message") +  "param4 missing! ")" />
            </when>
        </choose>
        <choose>
            <when condition="@(!String.IsNullOrEmpty(context.Variables.GetValueOrDefault<string>("message")))">
                <return-response>
                    <set-status code="400" reason="Bad Request" />
                    <set-body>@{
                            return context.Variables.GetValueOrDefault<string>("message");
                        }</set-body>
                </return-response>
            </when>
        </choose>
        <return-response>
            <set-status code="200" reason="OK" />
            <set-body>ok</set-body>
        </return-response>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

Sample with Postman:

enter image description here


Different solution

API Management has also validation policies.

By defining the OpenApi schema with required, pattern,..., the policy is able to validate it.

OpenApi:

paths:
  /validate2:
    post:
      summary: Validate2
      description: Validate2
      operationId: validate2
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Request'
            example:
              param1: string
              param2: string
              param3: string
              param4: string
      responses:
        '200':
          description: OK
components:
  schemas:
    Request:
      required:
        - param1
        - param2
        - param3
        - param4
      type: object
      properties:
        param1:
          type: string
        param2:
          type: string
        param3:
          type: string
        param4:
          type: string

Policy:

<policies>
    <inbound>
        <base />
        <validate-content unspecified-content-type-action="prevent" max-size="102400" size-exceeded-action="ignore" errors-variable-name="validateContent">
            <content type="application/json" validate-as="json" action="prevent" />
        </validate-content>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

Response:

{
    "statusCode": 400,
    "message": "Body of the request does not conform to the definition which is associated with the content type application/json. Invalid type. Expected String but got Null. Line: 3, Position: 18"
}

enter image description here

Related