Skip to content

Request Transformation in API Gateway — Modify Headers, Paths, and Bodies

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Request Transformation in API Gateway. We cover key concepts, practical examples, and best practices to help you master this topic.

Request transformation allows an API gateway to modify incoming requests headers, paths, query parameters, and bodies before forwarding them to backend services, decoupling external API contracts from internal implementations.

What You'll Learn

  • Common request transformations: path rewrite, header injection, body transformation
  • How to decouple external API versions from internal service versions
  • Security transformations like stripping sensitive headers

Why It Matters

Backend services evolve independently of the public API. An external client might call /api/v2/users, but the backend is /users on a different port. Request transformation lets the gateway bridge these differences without requiring client or backend changes.

Real-World Use

Durga Antivirus Pro's public API uses /v1/threats/report, but the threat analysis service expects /report with a service-specific authentication header. The gateway rewrites the path, strips the public API key, and injects internal auth headers before forwarding.

flowchart LR
    Client["Client\n/v1/users/42"] --> GW["Gateway\nTransform"]
    GW -->|"Rewrite to /users/42"| Backend["Backend\nService"]
    style GW fill:#dbeafe,stroke:#2563eb

Path Rewriting

Path rewriting changes the URL path before forwarding. The client sees a different path than the backend receives.

from flask import Flask, request
import requests
import re

app = Flask(__name__)

PATH_RULES = [
    (r"^/api/v1/users/(.*)$", "http://user-srv:8080/users/{}"),
    (r"^/api/v1/orders/(.*)$", "http://order-srv:8080/api/orders/{}"),
]

@app.route("/api/v1/<path:rest>")
def transform_and_proxy(rest):
    full_path = f"/api/v1/{rest}"
    for pattern, backend_template in PATH_RULES:
        match = re.match(pattern, full_path)
        if match:
            backend_url = backend_template.format(*match.groups())
            resp = requests.request(
                method=request.method,
                url=backend_url,
                data=request.get_data(),
                headers=request.headers
            )
            return (resp.content, resp.status_code, resp.headers.items())
    return {"error": "Route not found"}, 404

Header Injection and Stripping

The gateway adds headers for internal use and removes headers that should not reach the backend:

def prepare_forwarding_headers(original_headers):
    internal_headers = ["X-Internal-Token", "X-Debug", "X-Forwarded-For"]
    headers = {}
    for key, value in original_headers:
        if key not in internal_headers:
            headers[key] = value
    headers["X-User-ID"] = getattr(request, "user_id", "anonymous")
    headers["X-Gateway-Version"] = "2.1.0"
    return headers

Body Transformation

Sometimes the request body format must change. The gateway can parse, transform, and re-serialize:

import json

def transform_request_body(original_body):
    data = json.loads(original_body)
    transformed = {
        "user": {
            "id": data.get("user_id"),
            "name": data.get("full_name"),
            "email": data.get("email_address"),
        },
        "metadata": {
            "source": "gateway",
            "timestamp": data.get("created_at"),
        },
    }
    return json.dumps(transformed)

@app.route("/api/signup", methods=["POST"])
def signup():
    new_body = transform_request_body(request.get_data().decode())
    resp = requests.post(
        "http://user-service:8080/register",
        data=new_body,
        headers={"Content-Type": "application/json"}
    )
    return resp.content, resp.status_code

Common Mistakes

1. Modifying the Request Body for All Routes

Body transformation should be route-specific. A generic catch-all body transform may break routes that expect the original format.

2. Not Updating Content-Length Headers

After modifying the request body, update the Content-Length header. An incorrect length causes connection timeouts or truncated requests.

3. Forwarding Internal Headers from Clients

The gateway must strip any X-Internal-* headers from incoming requests. A malicious client could inject them to impersonate internal services.

4. Breaking Query Parameters

When rewriting paths, ensure query parameters are preserved. Append ?original_qs to the rewritten URL.

5. Synchronous Transformations Under Load

CPU-intensive transformations (XML-to-JSON conversion) should be async or queue-based to avoid blocking the gateway event loop.

Practice Questions

  1. Why is path rewriting useful for API Versioning?
  2. What headers should the gateway strip from incoming requests?
  3. Why must Content-Length be recalculated after body transformation?
  4. How can body transformation help migrate from legacy API formats?
  5. What is the risk of CPU-intensive transformations in the gateway?

Answers:

  1. The public API can expose stable URLs (/v1/users) while internally routing to different service versions without client changes.
  2. All X-Internal-* headers, authentication tokens after validation, and X-Forwarded-* headers that could spoof identity.
  3. The gateway adds or removes bytes during transformation, so the original length is incorrect. A mismatch causes connection errors.
  4. The gateway can transform XML to JSON or snake_case to camelCase, allowing legacy backends to serve modern clients without changes.
  5. CPU-intensive transformations block the gateway event loop, increasing latency for all requests. Offload to background workers or async processing.

Challenge: Design a transformation pipeline that accepts camelCase JSON from clients, transforms to snake_case for backends, and transforms responses back to camelCase.

FAQ

Can the gateway transform binary request bodies?

: Yes, but it is less common. Binary transformations like image resizing or compression are better handled by dedicated services.

Does request transformation break end-to-end encryption?

: If the gateway terminates TLS, it can transform plaintext. For passthrough mode, transformation is not possible.

How do you handle transformation errors gracefully?

: Return a 400 Bad Request with a clear error message like "Request body transformation failed: invalid JSON."

Can transformation rules be hot-reloaded?

: Yes. Many gateways support dynamic configuration reload via API or signal without restarting.

What is the performance impact of request transformation?

: Minimal for simple header/path changes. Body Parsing and Serialization add microseconds for JSON but can add milliseconds for XML.

Mini Project

Build a gateway that transforms incoming requests: rewrite /api/v2/products/{id} to /internal/products/{id}, strip Authorization header after validation, add X-Forwarded-Proto, and convert request body from camelCase to snake_case.

What's Next

Continue with Response Aggregation in Gateway to combine multiple backend responses, or explore Circuit Breaker Pattern for fault tolerance.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro