by Harris Kristanto
In this vlog, I will be walking you through how to use the validate-content policy in Azure API Management (APIM) to enforce strict validation rules on incoming request payloads. This is especially useful when you want to ensure that clients send well-formed and semantically correct data before it reaches your backend.
What is validate-content?
The validate-content policy allows you to inspect and validate the body of incoming requests. You can define rules such as:
- Maximum payload size
- Content type enforcement
- Schema validation (JSON or XML)
Limitations of validate-content Policy:
- No support for conditional logic such as if-then-else statements
- No partial validation as it validates the entire payload against the schema. You can’t selectively validate only certain fields or sections.
- Validation happens at the gateway level. For large payloads or high-throughput APIs, this can introduce latency and impact performance.
Limitations of XML validation:
- More verbose and harder to maintain than JSON
- Schema complexity can impact readability and maintainability
Here’s the policy snippet I used in the demo:
<policies>
<inbound>
<base />
<validate-content unspecified-content-type-action="prevent" max-size="102400" size-exceeded-action="prevent" errors-variable-name="requestBodyValidation">
<content type="application/json" validate-as="json" action="prevent" schema-id="JSONSchema" />
</validate-content>
<mock-response status-code="200" content-type="application/json" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
This configuration ensures that:
- Only JSON payloads are accepted.
- Payloads larger than 100 KB are rejected.
- The content must match the schema defined by JSONSchema.
JSON Schema Explained
Here’s the schema I used to validate incoming requests:
{
"type": "object",
"properties": {
"username": {
"type": "string",
"minLength": 5,
"maxLength": 20,
"pattern": "^[a-zA-Z0-9_]+$"
},
"email": {
"type": "string",
"format": "email",
"maxLength": 100
},
"age": {
"type": "integer",
"minimum": 18,
"maximum": 99
}
},
"required": ["username", "email", "age"]
}
Schema Rules:
- username: Must be alphanumeric (including underscores), 5–20 characters.
- email: Must be a valid email format, max 100 characters.
- age: Must be an integer between 18 and 99.
Postman Demo Scenarios
In the video, I used Postman to test various payloads:
✅ Happy Path
Request Payload
{
"username": "user123",
"email": "user@example.com",
"age": 25
}
Response:
200 OK Response
This payload passes all validation checks.
❌ Invalid Age
{
"username": "user123",
"email": "user@example.com",
"age": 16
}
Response:
{
"statusCode": 400,
"message": "Body of the request does not conform to the definition which is associated with the content type application/json. Path:age Message: Integer 16 is less than minimum value of 18. Line: 4, Position: 11 SchemaId: #/properties/age"
}
This payload fails because age is below the minimum of 18.
❌ Invalid Email
{
"username": "user123",
"email": "not-an-email",
"age": 25
}
Response:
{
"statusCode": 400,
"message": "Body of the request does not conform to the definition which is associated with the content type application/json. Path:age Message: Integer 16 is less than minimum value of 18. Line: 4, Position: 11 SchemaId: #/properties/age"
}
This payload fails due to incorrect email format.
❌ Missing Field
{
"username": "user123",
"age": 25
}
Response:
{
"statusCode": 400,
"message": "Body of the request does not conform to the definition which is associated with the content type application/json. Path: Message: Required properties are missing from object: email. Line: 4, Position: 1 SchemaId: #"
}
This payload fails because the email field is required.
Validating XML Message Example
You can also validate XML payloads using a similar approach. Here’s an example policy snippet:
<validate-content max-size="102400" size-exceeded-action="prevent" errors-variable-name="requestbodyvalidation"></validate-content max-size="102400" size-exceeded-action="prevent" errors-variable-name="requestbodyvalidation">
<content type="application xml" validate-as="xml" action="prevent" schema-id="XMLSchema" =""></content type="application>
And a sample XML schema (XSD):
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://example.com/user"
xmlns="http://example.com/user"
elementFormDefault="qualified">
<xs:element name="user">
<xs:complexType>
<xs:sequence>
<xs:element name="username" type="UsernameType" />
<xs:element name="email" type="EmailType" />
<xs:element name="age" type="AgeType" />
</xs:sequence>
</xs:complexType>
</xs:element>
<!-- Username: 5-20 characters, alphanumeric with underscores -->
<xs:simpleType name="UsernameType">
<xs:restriction base="xs:string">
<xs:minLength value="5"/>
<xs:maxLength value="20"/>
<xs:pattern value="^[a-zA-Z0-9_]+$"/>
</xs:restriction>
</xs:simpleType>
<!-- Email: valid format, max 100 characters -->
<xs:simpleType name="EmailType">
<xs:restriction base="xs:string">
<xs:maxLength value="100"/>
<xs:pattern value="[^@]+@[^@]+\.[^@]+" />
</xs:restriction>
</xs:simpleType>
<!-- Age: integer between 18 and 99 -->
<xs:simpleType name="AgeType">
<xs:restriction base="xs:integer">
<xs:minInclusive value="18"/>
<xs:maxInclusive value="99"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
Sample XML Payload:
<user xmlns="http://example.com/user">
<username>user_123</username>
<email>user@example.com</email>
<age>25</age>
</user>
Final Thoughts
Using validate-content in APIM is a powerful way to enforce data integrity and reduce backend errors. Whether you’re working with JSON or XML, schema validation ensures that only well-formed and valid data reaches your services.
Recommended Use Cases
- Early payload validation: Catch malformed or incomplete requests before they hit your backend.
- Enforcing contract compliance: Ensure clients adhere to expected request formats (e.g., required fields, data types, value ranges).
- Reducing backend load: Filter out invalid requests at the gateway level to save processing time and resources.
When Not to Use It
- Business logic validation: Avoid using validate-content for rules like “if the user selects ‘premium’, the payment method must be provided.” These kinds of conditional dependencies between fields are better handled in your backend or application logic, where you have full control over context and flow.
- Every single endpoint: Use it selectively—typically on public-facing or critical endpoints where schema enforcement adds real value.
- Highly dynamic schemas: If your payload structure changes frequently or is client-defined, static schema validation may become a maintenance burden.
Top comments (0)