Kong Transformations
Introduction
When building APIs and microservices, you'll often need to modify requests and responses as they flow through your API gateway. Kong Gateway provides a powerful set of transformation plugins that allow you to manipulate HTTP requests before they reach your upstream services and modify responses before they're sent back to clients.
In this guide, we'll explore various Kong transformation plugins, understand how they work, and see them in action through practical examples.
What are Kong Transformations?
Kong transformations are a collection of plugins that enable you to modify various aspects of HTTP requests and responses. These transformations can range from simple header additions to complex JSON payload restructuring.
Common use cases for transformations include:
- Converting between data formats (XML to JSON, etc.)
- Adding, removing, or modifying headers
- Changing request or response bodies
- Renaming parameters
- Implementing security headers
- Sanitizing data
Key Transformation Plugins
Let's explore the most commonly used transformation plugins in Kong:
1. Request-Transformer
The Request-Transformer plugin allows you to modify incoming requests before they reach your upstream services.
Installation
$ kong config db_import request-transformer.yml
Configuration Example
plugins:
- name: request-transformer
config:
add:
headers: ["x-consumer-id:$(consumer.id)"]
querystring: ["api-version:v1"]
body: ["new-field:new-value"]
remove:
headers: ["x-credential-id"]
querystring: ["old-param"]
body: ["sensitive-data"]
rename:
headers: ["original-header:new-header"]
querystring: ["old-query:new-query"]
body: ["original-field:new-field"]
replace:
headers: ["host:new-host.com"]
querystring: ["param:new-value"]
body: ["field:new-value"]
Practical Example
Let's say you have a legacy API that requires specific headers, but your clients don't provide them:
plugins:
- name: request-transformer
config:
add:
headers: ["x-api-key:${vault://secrets/api-keys/legacy-system}"]
querystring: ["version:1.0"]
rename:
body: ["user_id:accountId"]
Before Transformation:
POST /users HTTP/1.1
Host: example.com
Content-Type: application/json
{
"user_id": "12345",
"name": "John Doe"
}
After Transformation:
POST /users?version=1.0 HTTP/1.1
Host: example.com
Content-Type: application/json
x-api-key: s3cr3t-ap1-k3y
{
"accountId": "12345",
"name": "John Doe"
}
2. Response-Transformer
The Response-Transformer plugin allows you to modify outgoing responses from your upstream services before they're sent back to clients.
Configuration Example
plugins:
- name: response-transformer
config:
add:
headers: ["x-powered-by:Kong"]
json: ["metadata.timestamp:$(date)"]
remove:
json: ["internal_id", "sensitive_data"]
rename:
json: ["server_id:id"]
replace:
json: ["status:active"]
Practical Example
Imagine your upstream service returns sensitive data that should be removed before responses reach clients:
plugins:
- name: response-transformer
config:
remove:
json: ["credit_card", "password", "ssn"]
add:
headers: ["X-Content-Type-Options:nosniff", "X-Frame-Options:DENY"]
replace:
json: ["error.code:user-friendly-error"]
Before Transformation:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "user-123",
"name": "John Doe",
"credit_card": "1234-5678-9012-3456",
"password": "hashed_password",
"ssn": "123-45-6789",
"error": {
"code": "ERR-29491",
"message": "Operation completed with warnings"
}
}
After Transformation:
HTTP/1.1 200 OK
Content-Type: application/json
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"id": "user-123",
"name": "John Doe",
"error": {
"code": "user-friendly-error",
"message": "Operation completed with warnings"
}
}
3. Correlation-ID
The Correlation-ID plugin adds a unique identifier to requests flowing through Kong, which is helpful for tracing requests across microservices.
Configuration Example
plugins:
- name: correlation-id
config:
header_name: X-Correlation-ID
generator: uuid
echo_downstream: true
Practical Example
Before Request Reaches Kong:
GET /api/products HTTP/1.1
Host: example.com
After Passing Through Kong:
GET /api/products HTTP/1.1
Host: example.com
X-Correlation-ID: 706d4e10-3431-4c1a-b785-cd0a9e45ff7b
Response from Upstream with Echo Enabled:
HTTP/1.1 200 OK
Content-Type: application/json
X-Correlation-ID: 706d4e10-3431-4c1a-b785-cd0a9e45ff7b
{
"products": []
}
This ID can be used for tracking the entire request flow through your microservices architecture.
4. JSON-to-XML and XML-to-JSON Transformers
These plugins convert payloads between JSON and XML formats, useful when working with services that require different data formats.
JSON-to-XML Example
Configuration:
plugins:
- name: json-to-xml
config:
content_type: application/xml
Before (JSON):
{
"user": {
"id": 123,
"name": "John Doe",
"roles": ["admin", "developer"]
}
}
After (XML):
<?xml version="1.0" encoding="UTF-8"?>
<root>
<user>
<id>123</id>
<name>John Doe</name>
<roles>admin</roles>
<roles>developer</roles>
</user>
</root>
XML-to-JSON Example
Configuration:
plugins:
- name: xml-to-json
config:
remove_xml_declaration: true
preserve_root: false
Before (XML):
<?xml version="1.0" encoding="UTF-8"?>
<order>
<id>12345</id>
<customer>
<name>Jane Doe</name>
<email>[email protected]</email>
</customer>
<items>
<item>
<product>Widget</product>
<quantity>2</quantity>
</item>
<item>
<product>Gadget</product>
<quantity>1</quantity>
</item>
</items>
</order>
After (JSON):
{
"id": "12345",
"customer": {
"name": "Jane Doe",
"email": "[email protected]"
},
"items": {
"item": [
{
"product": "Widget",
"quantity": "2"
},
{
"product": "Gadget",
"quantity": "1"
}
]
}
}
Advanced Use Cases
Chaining Multiple Transformations
You can chain multiple transformation plugins to create complex data manipulation pipelines:
plugins:
- name: request-transformer
config:
add:
headers: ["x-version:1.0"]
- name: response-transformer
config:
remove:
json: ["internal_fields"]
- name: correlation-id
config:
header_name: X-Correlation-ID
generator: uuid
Using Transformation Templates
For more complex transformations, you can use template rendering with the request-transformer-advanced
and response-transformer-advanced
plugins, which support templating:
plugins:
- name: request-transformer-advanced
config:
add:
body:
- |
{"timestamp": "$(now)", "api_version": "$(headers.accept_version)"}
Data Masking and Compliance
You can use transformations for meeting compliance requirements like GDPR or PCI-DSS:
plugins:
- name: response-transformer
config:
replace:
json:
- "credit_card:XXXX-XXXX-XXXX-$(substring(body.credit_card,12,16))"
- "email:$(substring(body.email,0,3))***@$(substring_after(body.email,'@'))"
Best Practices
When working with Kong transformations, consider these best practices:
-
Start Simple: Begin with basic transformations and gradually add complexity.
-
Test Thoroughly: Test your transformations against different inputs to ensure they handle edge cases properly.
-
Monitor Performance: Complex transformations can impact gateway performance. Monitor latency and adjust as needed.
-
Security First: Be careful not to expose sensitive data through transformations. Always validate transformed content.
-
Documentation: Document your transformations so other developers understand the expected input and output formats.
-
Use Declarative Config: Use Kong's declarative configuration format (YAML) to version control your transformations.
Common Patterns and Solutions
API Versioning
plugins:
- name: request-transformer
config:
add:
headers: ["Accept-Version:v2"]
querystring: ["api_version:2"]
Error Response Standardization
plugins:
- name: response-transformer
config:
replace:
json:
- "error:{\"code\":\"$(body.status)\",\"message\":\"$(body.message)\",\"id\":\"$(headers.x-correlation-id)\"}"
Security Headers Addition
plugins:
- name: response-transformer
config:
add:
headers:
- "Strict-Transport-Security:max-age=31536000; includeSubDomains"
- "Content-Security-Policy:default-src 'self'"
- "X-Content-Type-Options:nosniff"
- "X-Frame-Options:DENY"
Creating Custom Transformations
For scenarios where the built-in plugins don't meet your requirements, you can create custom transformations using Lua plugins:
local CustomTransformer = {
PRIORITY = 800,
VERSION = "1.0.0",
}
function CustomTransformer:access(conf)
local request_headers = kong.request.get_headers()
local body, err = kong.request.get_body()
-- Perform custom transformations here
-- Example: Add a custom header based on body content
if body and body.user_type then
kong.service.request.set_header("X-User-Type", body.user_type)
end
end
return CustomTransformer
Summary
Kong transformations provide powerful tools for modifying HTTP requests and responses as they flow through your API gateway. By using these plugins effectively, you can:
- Standardize API interfaces
- Implement security best practices
- Convert between data formats
- Mask sensitive information
- Improve debugging and monitoring
- Create backward compatibility for APIs
The ability to transform requests and responses is one of Kong's most valuable features, allowing you to adapt different services and clients to work together seamlessly without changing their implementation.
Additional Resources
- Kong Plugin Development Guide
- Request Transformer Plugin Documentation
- Response Transformer Plugin Documentation
- Kong Correlation ID Plugin Documentation
- Understanding JSON and XML Data Formats
- Advanced Data Transformation Patterns
Exercises
-
Basic Header Transformation: Configure a request-transformer plugin to add an
X-API-Version
header to all requests. -
Body Modification: Create a response-transformer configuration that removes a sensitive field like
password
from all responses. -
Format Conversion: Set up an API route that accepts JSON but converts it to XML before sending it to the upstream service.
-
Advanced Transformation: Create a custom Lua plugin that transforms data based on complex business rules.
-
Error Standardization: Configure a response transformer that standardizes error responses across different services.
By mastering Kong transformations, you'll have powerful tools to integrate services, enhance security, and create consistent API experiences.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)