Apache APISIX request and response transformation

Apache APISIX can rewrite paths, hosts, headers, methods and response bodies at the gateway, so clients and services can keep different contracts. This page explains the options, the setup sequence and where transformation should stop.

On this page

How APISIX request transformation keeps clients and services decoupled

APISIX can translate requests and responses at the gateway, so clients, legacy services and partner APIs can keep the paths, headers and payloads they already use. Consider a team where a mobile client calls /v2/orders, a legacy service only answers on /orders/legacy, and a partner expects a fixed X-Partner-Key header. Instead of changing all three, the team can place the mapping in one route. The proxy-rewrite plugin rewrites the upstream URI with uri or regex_uri, sets or overrides the Host header, adds, sets or removes request headers, and changes the HTTP method before the request is forwarded. According to the plugin documentation, URI normalization stays on unless use_real_request_uri_unsafe is set, so the team should confirm that normalization does not alter a path the legacy service depends on before going live. Response-side changes use different plugins. response-rewrite modifies response status, headers and body, and body-transformer converts request and response bodies between formats such as JSON, XML and form data. The APISIX plugin list also includes error-page, grpc-transcode, grpc-web, mocking and degraphql, which cover error bodies, gRPC mapping and GraphQL shaping. Teams should confirm the exact fields and template syntax each plugin accepts for their APISIX version, because body templates are easy to break silently.

Transformation belongs at the gateway when it is a contract between parties, and in the service when it is business logic. Renaming a path for a retired client, adding a correlation header, or mapping a partner's XML to the internal JSON model are good gateway work because they are stable and shared by many routes. Calculating prices, reshaping data by user role, or applying domain validation belongs in the service, where it can be tested with the code that owns it. Before you build, list every rewrite rule, name its owner, and decide whether removing the gateway rule would break a client. Keep rules in version-controlled route configuration, and test each one with representative requests in a non-production environment. Ask your implementation partner to show how rules are reviewed, rolled out and rolled back, because a transformation that hides errors from both sides is hard to debug.

Which transformation plugin fits which job

Use proxy-rewrite when the gateway exposes a public path or host that differs from what the upstream service expects. The plugin runs before the request is forwarded, so the upstream sees the rewritten URI, Host header, headers and HTTP method. It is the first place to look when a backend returns 404 for a path that works when called directly, or when a service requires a specific Host value.

  • Path mapping: Rewrite a public prefix such as /api/v2/ to the internal path using uri for fixed mappings or regex_uri for pattern-based mappings.
  • Host correction: Set the Host header when the upstream routes on hostname and the public hostname differs.
  • Header changes: Add, set or remove request headers before forwarding, for example to inject a tenant identifier that the gateway has already validated.
  • Method changes: Change the HTTP method for legacy clients or upstreams that only accept one verb on a given path.
  • URI normalization: Leave normalization on unless you have confirmed that the upstream depends on the raw, unnormalized URI, since use_real_request_uri_unsafe disables that protection.

Before relying on any rewrite, check the rules against a test suite that covers encoded characters and trailing slashes. Confirm the exact option names in the proxy-rewrite plugin documentation.

Configuration options in proxy-rewrite and related plugins

This table compares the proxy-rewrite fields that change the upstream request with the response-side plugins that change what the client receives. Read each row as a decision: find the change you need, then check the trade-off and the plugin that fits it. The main takeaway is that proxy-rewrite changes only what the upstream sees, so anything the client must see differently belongs in a response plugin.

OptionWhat it changesWhen it fitsTrade-off to check
uriUpstream path replaced with a fixed valueOne route maps to one backend path, such as moving a public path to an internal pathApplies the same path to every request matched by the route
regex_uriUpstream path rewritten from a regex match and replacementSeveral public paths share a prefix or pattern that the backend expects differentlyRegex errors are easy to miss, so test each pattern against sample paths before rollout
Host headerHost sent to the upstreamBackend uses virtual hosts or rejects requests not addressed to its own nameCookies, redirects and absolute URLs in responses may still reference the public host
Request headers (add, set, remove)Headers added, overwritten or stripped before forwardingInjecting internal identifiers, removing client-supplied trust headers, or adding backend-specific keysRemoving a header that a consumer plugin depends on can break authentication; confirm plugin order
methodHTTP method sent upstreamExposing a POST-only backend as a GET-friendly public endpointChanging methods can break caching, idempotency and client expectations; document the mapping
use_real_request_uri_unsafeDisables URI normalization so the raw request URI reaches the upstreamRare cases where a backend must see encoded or unnormalized paths exactly as sentNormalization is on by default; turning it off can open path-based bypasses against path rules, so confirm the need with a security review
response-rewriteStatus code, response headers and body returned to the clientAdding security headers, hiding server details, or adjusting a status code the client should seeBody changes on large or compressed responses need testing; confirm content length and encoding behavior
body-transformerRequest or response body converted between formats, such as XML and JSONA legacy backend speaks a different format than the client contractTransforming bodies adds per-request cost and makes debugging harder; keep templates versioned

When transformation belongs in the gateway and when it belongs in the service

A gateway can reshape requests and responses so clients and upstreams agree on the same contract without code changes. The same ability hides logic from the service team, so each rewrite should have a clear owner, a documented reason and a test that proves it works.

Path versioning for legacy clients

Old clients still call a path the service has retired, such as a version prefix that no longer exists upstream. A proxy-rewrite rule can map the legacy path to the current one at the gateway, which lets the old client keep working while the service moves on. The trade-off is that the service's own routes no longer match what clients call, so anyone debugging a 404 must read the gateway routes first. Record each mapping with an expiry date and check that the upstream receives the rewritten URI in logs.

Header normalization across services

When several services expect the same identifiers or security headers in different forms, the gateway can set, add or remove them once before forwarding. This keeps naming consistent and stops clients from sending headers the backend should never trust. The risk is that each service now depends on a gateway setting it never reads in its own code. Confirm which headers the gateway owns, and make sure services reject values that arrive from outside the gateway.

Partner payload shape

An external partner may require a field layout that differs from your internal model. Body transformation at the gateway can map the partner format to the internal one for a single integration, which avoids a new service only for reshaping. Keep this to structural mapping. Body transforms are harder to test and review than code, so store the mapping under version control and include sample payloads in the test suite for each partner.

Business logic and validation

Rules about what a valid order is, how prices are calculated or which fields a role may change belong in the service, where the data model and its tests live. A gateway rewrite that drops or invents fields hides a defect from the team that owns the data. Use the gateway for coarse checks such as schema shape or size limits, and leave decisions that depend on domain meaning to code the service owns and can unit test.

Data that depends on application state

Responses that depend on a database record, a feature flag or the user's account state need the service to compute them. A gateway has the request and a copy of the response, but it does not hold the business state needed to decide the correct value. Transforming such data at the gateway tends to produce stale or wrong results that are hard to trace. Ask the service owner to return the final value, and reserve gateway rewrites for presentation that is independent of state.

Response rewrites that hide errors

Rewriting error bodies or status codes with response-rewrite or error-page can make a failing service look healthy to clients and monitors. Support teams then see generic messages while the real cause sits in upstream logs. Keep the upstream status and an error identifier intact, and document every rewrite so incident responders know that a 200 or a friendly message may have been produced by the gateway.

How to set up and verify a transformation route

This sequence takes a transformation from a written contract to a verified route, so each change to paths, hosts, headers, methods and response bodies is confirmed in staging before clients depend on it. The output is a tested route definition and a short record of what was checked at the client and admin ports.

  1. Inventory client and upstream contracts

    The platform or API owner lists, for each route, the public path and method clients call, the path, host, headers and method the upstream service expects, and the response fields clients read. Name the owner of each contract so a later change has a sign-off point. Done means every transformation has a written before and after pair that someone outside the project can read. Ask your upstream teams to confirm whether they rely on the original Host header or on any encoded characters in paths.

  2. Confirm the staging instance and ports

    The operations team starts a staging APISIX instance in the deployment mode you plan to run in production, using the same plugin configuration source. In traditional mode, APISIX serves client traffic on port 9080 and the Admin API on port 9180, so confirm both are reachable from the places you expect and blocked from the places you do not. Done means you can call the Admin API from an admin host and the client listener from a test client, and you have recorded which hosts reach each port.

  3. Write the route with proxy-rewrite

    The engineer defines a route in staging with the proxy-rewrite plugin, setting the upstream URI (uri or regex_uri), the Host header, any request headers to add, set or remove, and the HTTP method if the upstream needs a different one. Keep one route per contract so a rollback changes one object. Done means the route is saved through the Admin API and appears when you read it back, with the rewrite fields exactly as written in the contract.

  4. Test path, host, header and method changes

    The tester sends curl requests to the client port 9080 for each contract case, including the original path, a path with query parameters, and a request with the original Host header. Use a test upstream that echoes the path, host, headers and method it receives, so you can compare what arrived with the contract. Done means every row in the contract table matches the echoed values, and any mismatch is fixed in the route before moving on.

  5. Check normalization on encoded paths

    Proxy-rewrite normalizes the upstream URI unless use_real_request_uri_unsafe is set, so send paths with percent-encoded characters, dot segments and double slashes, and compare what the upstream receives with what the client sent. Decide, with the upstream owner, whether any path must reach the service exactly as sent before you change that setting, because the unsafe option carries its own risk. Done means you have a recorded result for each encoded case and a documented decision on the setting.

  6. Add response-rewrite and verify client responses

    Once request handling is correct, the engineer adds response-rewrite to the same route to change response headers or body fields that clients should see. Repeat the curl tests and inspect the status code, headers and body at the client port, confirming the upstream still returns the response you expect before the rewrite runs. Done means the client-facing response matches the response contract, and a sample of error responses still reads correctly.

  7. Record evidence and promote the route

    The platform owner saves the route definition, the test cases with their results, the port checks and the normalization decision in the change record, then promotes the same definition to production through your normal change process. Ask your partner or internal team to confirm how the configuration source is versioned so production matches the tested route. Done means production returns the same client responses as staging for the recorded cases.

Security risks of rewriting traffic at the gateway

Every rewrite the gateway performs changes what the upstream service believes about the request and what the client believes about the response. The risks below share one root cause: a transformation that is convenient at the gateway can silently alter identity, routing, errors or logged data, so each one needs an owner and a check before it reaches production.

Forwarded identity headers

Transformation rules can add, set or remove headers such as those carrying user identity or client address. If a rewrite trusts a header a client can send, an upstream service may act on a spoofed identity. Confirm which headers are stripped from inbound requests before any rewrite sets them, and confirm that only the gateway writes the identity headers the services rely on. Review the header trust settings described in the hardening topic.

URI normalization turned off

The proxy-rewrite plugin normalizes the URI by default. Setting use_real_request_uri_unsafe forwards the raw path, which can let encoded or dot-segment paths reach a backend that routes or authorizes differently from the gateway. Treat this setting as an exception that needs a written reason, test cases for encoded traversal paths, and a check that route matching and backend path handling agree.

Response bodies that hide errors

Response rewriting can replace upstream error messages with generic text, or change status codes, so monitoring and client logic no longer see the real failure. The reverse risk is also real: a body transform can expose internal fields, stack traces or data the client should not receive. Test both the success and failure paths, and confirm which fields the transform removes or adds.

Admin API control over routes

A transformation is only as trustworthy as the route configuration that holds it. Anyone who can call the Admin API can add or change a rewrite on a live route, including one that strips authentication headers. Restrict Admin API access to named operators or automation, keep its credentials out of application config, and record every route change so a review can compare it against the approved configuration.

Logged rewritten values

Rewritten paths, headers and bodies often reach access logs or tracing data. A rewrite that moves a token, a customer identifier or a query parameter into a logged field spreads that value to every log consumer. Decide which fields are logged before and after transformation, mask sensitive values, and confirm with your logging team who can read those logs.

Questions teams ask before transforming requests in APISIX

What drives the implementation effort for request and response transformation?

The effort depends mainly on how many routes carry transformation logic, how varied those transformations are, and how many backends must agree on the result. A few path rewrites on one service are a small task. Header rules that differ by consumer, body rewrites that depend on payload structure, and error responses that must match a published contract take longer to design and verify. Effort also grows when transformations overlap with existing plugin configuration, because precedence between route, plugin config and global rules has to be checked. Ask any partner to break the work down by route group, transformation type and test cases so you can see where the effort sits.

Can our in-house team build transformations in APISIX without a partner?

Yes, a team with gateway and HTTP experience can build simple transformations with the documented plugins, provided it can run a test environment and review changes before they reach production. The work becomes harder when the team has to know which requests a rewrite affects, how URI normalization changes matching, and how upstream services react to altered headers or methods. Many teams keep the simple rules in-house and bring in outside help for the design of contracts, the regression suite and the rollout plan. Check your team's experience with the APISIX Admin API, configuration as code and your current gateway's rewrite behavior before you decide.

What do we need to provide before transformation work starts?

Three inputs shape almost every engagement: a route inventory, the contracts for the APIs involved, and representative test traffic. The route inventory lists each path, method, host, upstream and the transformation your current gateway applies today, including any that exist only in legacy configuration. Contracts show what each consumer and backend expects, such as header names, error formats and path versions. Test traffic, captured from a non-production environment or sanitized from logs, lets the team confirm that rewrites behave as intended for real request shapes. Without these, the testing phase expands because each assumption has to be checked by hand.

How long does testing take depending on the number of routes?

Testing time grows with the number of distinct transformation rules, not only the number of routes, because identical rules can be tested once and applied to many routes. A useful plan groups routes by transformation pattern, tests each pattern against its contract and test traffic, then checks a sample of routes in a staging environment that mirrors production. Expect the regression suite to cover normal requests, malformed input, unusual paths, and error responses. Ask any partner to show how the test plan scales with your route count and which routes will be verified manually. No fixed duration applies because the result depends on your inventory and environments.

Are request and response transformations a one-time task or an ongoing cost?

The initial design and build are one-time work, but transformations need upkeep because the APIs they front change. Each new backend version, header convention or consumer requirement can break an existing rewrite. Plugin behavior can also change between APISIX releases, so rules should be retested after upgrades. Ongoing costs usually cover reviewing transformation changes, maintaining the regression suite, and checking rules during upgrades. Ask whether a quote includes handover documentation, and whether ongoing support or a retainer is needed for changes after go-live.

How do we confirm plugin behavior for our APISIX version?

Start with the plugin documentation for the exact APISIX version you run, because option names and defaults can differ between releases. Read the proxy-rewrite reference, which covers URI rewriting, Host and header changes, method changes and the URI normalization setting, then check the plugin list for the other transformation plugins you plan to use. Confirm the version against the APISIX downloads page, and review the upstream repository's release notes for changes that affect your rules. Finally, reproduce each rule in a non-production cluster and compare results with your test traffic. Treat documentation as a starting point and the test results as the evidence.

Should transformation logic live in the gateway or in the service?

Put transformation in the gateway when it is a routing or compatibility concern shared by several clients, such as path mapping during a migration, a header that every consumer must receive, or a uniform error format. Keep it in the service when it depends on business data, requires application state, or changes the meaning of a resource. Gateway rules are easy to apply across many APIs but are harder to debug when they hide behavior from service owners. Document each rule with its owner and reason so the decision stays visible to both platform and application teams.

Does transforming requests create security or compliance risk?

It can, mainly when a rewrite changes which backend receives a request, strips a header that carries authentication or audit data, or alters a response in a way that removes a security control. Review every rule that touches authentication headers, host values, error bodies or response headers. Keep rewrites in version control, test them against negative cases, and log enough to trace which rule ran. Compliance programs care about this evidence, but no transformation setup satisfies a framework on its own, and independent auditors make that assessment.

Limits to confirm in your environment

Transformation rules look simple until they meet a specific APISIX release, a large payload or a second plugin on the same route. The cards below list the checks to run in a proof of concept before the rewrite logic is committed to production routes.

APISIX version and plugin presence

Confirm that the plugin you need, such as body-transformer or exit-transformer, exists in the exact APISIX version you plan to run, and that its configuration keys match that version's documentation. Plugin lists and options change between releases, so check the plugin page for your target version rather than the latest one. Record the version in your deployment baseline so an upgrade does not silently change rewrite behavior. The current release line on the downloads page is 3.19.0, released on September 28, 2026, but that page does not mark any release as long-term support, so confirm your support window separately.

Large payloads and body size

Body transformation reads and rewrites the full message body, so memory use and latency grow with payload size. Test your largest real request and response bodies through the gateway, not small samples. Confirm how the gateway behaves when a body exceeds the configured limit, and whether the response is truncated, rejected or passed through unchanged. Check the interaction with upstream compression, since a rewrite on compressed content can fail silently.

Interaction with gRPC transcoding

If the same route uses grpc-transcode or grpc-web, confirm the order in which body and header rewrites apply to the transcoded message. A body rewrite that runs on the JSON side may not match the protobuf fields the upstream expects, and a header rewrite may affect the gRPC-Web preflight. Build a test per method that covers the request and the response path, including error responses and streaming calls where they apply.

Plugin ordering on shared routes

Transformation plugins run alongside authentication, rate limiting, CORS and error handling. Confirm the execution order for every plugin on the route, including plugins inherited from global rules, plugin configs or the service, because a header added by proxy-rewrite may be needed before an authentication plugin reads it, or a response rewrite may run after a plugin that already set the headers. Write down the expected order and test it with a request that triggers each plugin.

Rewrite rules as code

Rewrite rules are configuration, so they need the same review and rollback path as code. Confirm that your release process can store route and plugin definitions in version control, apply them through the Admin API or standalone configuration file, and roll back a single change without redeploying services. If your team manages the gateway through Kubernetes resources, check that the rewrite definitions survive the sync cycle and are visible in review.

Keeping transformation rules maintainable over time

Transformation rules drift because the services behind them change and the gateway rules do not. A proxy-rewrite rule that maps a public path to an internal path, or a response-rewrite rule that strips a header, was correct for the service version it was written against. When a team renames an endpoint, moves a host, changes a header name or adds a required field, the rule keeps running silently and either breaks clients or hides a change that consumers now depend on. The drift is hardest to see for body-transformer and response-rewrite rules, because they often fail only for a subset of payloads. Before go-live, ask each service owner which of their endpoints are rewritten at the gateway and who is told when those endpoints change.

Keep the rules in versioned configuration rather than in edits made through the Admin API. Whether APISIX runs in traditional, decoupled or standalone mode, the route definitions with their proxy-rewrite and response-rewrite settings should live in a Git repository and be applied from there, so every change has an author, a review and a rollback point. Standalone mode with a file such as conf/apisix.yaml makes this straightforward because the file is the source of truth. Confirm with your platform team how configuration is synchronized to each gateway node and how a bad commit is reverted, since a rule that reaches production without review is the most common cause of unexplained behavior at the gateway.

Test each transformation in the release pipeline against the upstream version it targets. A useful gate sends representative requests through a gateway instance loaded with the candidate configuration and checks the rewritten URI, the forwarded headers and the response body, including the error paths. Run the same suite when the upstream service releases a new version, not only when the gateway configuration changes. Assign ownership in writing: for each rule, record which team owns the intent, which team owns the gateway configuration, and who approves a change that affects a published API contract. A short ownership register kept next to the route files answers the question that usually surfaces during an incident, which is who can change this rule and who must be told.

How DeployOpen scopes and delivers APISIX transformation work

DeployOpen plans, implements, documents and supports self-hosted open-source platforms inside your own infrastructure, including Apache APISIX. For request and response transformation, we start from a written scope that lists which routes change, which headers, paths and bodies are affected, and where each rule runs.

How we scope

  • Inventory every route that needs path, host, header or method rewriting, and record the upstream each one reaches.
  • Decide which transformations belong in APISIX and which belong in the service, and document the reasons for each.
  • Confirm the APISIX version, deployment mode and plugin set your environment supports before any rule is written.

How we build

  • Write proxy-rewrite and response-rewrite rules as versioned configuration, reviewed like application code.
  • Test URI normalization and encoded path cases against real upstream behavior before rules reach production.
  • Check that body-transformer and response changes keep content length, content type and caching headers correct.

How we hand over

  • Deliver a written rule catalog listing each transformation, its route, its owner and the upstream it protects.
  • Document rollback steps for each rule and the test cases your team can rerun after future changes.
  • Walk your platform and API teams through the configuration so they can add or change rules without guesswork.

How we support

  • Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts.
  • Ongoing support, upgrades and continuous testing are available as a retainer after handover.
  • Ask for a quote based on the written scope, which states who maintains rules after each APISIX upgrade.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.