Transform Route Parameters for URL Rewrite
This guide explains how to transform incoming route parameter values in an inbound policy before the URL Rewrite handler uses them to build the upstream URL. This pattern is useful when your public API paths use different naming conventions than your internal backend.
Overview
When you use the URL Rewrite handler, it builds the upstream URL by
interpolating values like ${params.resourceType} directly from the incoming
route parameters. Sometimes, however, you need to change those values before
the rewrite happens. Common scenarios include:
- Value mapping — translating a public-facing parameter like
orderto an internal value likecustomerorder - Case normalization — converting
Productstoproductsbefore forwarding - Path translation — mapping user-friendly slugs to internal identifiers
One approach is to read the route parameters in an inbound policy, transform
them, store the results on
context.custom, and reference the
transformed values in the URL Rewrite pattern. This keeps the original route
parameters intact while exposing the transformed values under clearly named
keys. If you prefer, you can instead modify params directly on the request —
see
Alternative: Modify Route Parameters Directly.
Step-by-Step Example
The solution has three parts: an inbound policy that reads request.params
and stores transformed values on context.custom, a URL Rewrite handler
that references those values using ${context.custom.*} in the
rewritePattern, and route configuration that wires the two together.
Imagine your public API exposes a route like /api/:resourceType/:resourceId,
but your backend expects the resource type to be prefixed with customer. A
request to /api/order/123 should be forwarded to
https://backend.example.com/api/customerorder/123.
1. Write the Inbound Policy
Create a custom inbound policy that reads the route parameters, transforms the
values, and stores them on context.custom:
Code
2. Register the Policy
Add the policy to config/policies.json:
Code
3. Configure the Route
Define the route in config/routes.oas.json with the inbound policy and a URL
Rewrite handler that references context.custom:
Code
With this configuration, a request to /api/order/123 flows through the
pipeline as follows:
- The route matches with
params.resourceType = "order"andparams.resourceId = "123" - The
transform-paramsinbound policy runs and setscontext.custom.transformedResourceType = "customerorder" - The URL Rewrite handler builds the upstream URL:
https://backend.example.com/api/customerorder/123
Alternative: Modify Route Parameters Directly
Instead of storing transformed values on context.custom, you can return a new
ZuploRequest with modified params.
The URL Rewrite handler reads ${params.*} from the request it receives, so any
parameters you set on the returned request flow through to the rewritePattern:
Code
With this policy in front of a URL Rewrite handler whose rewritePattern is
https://backend.example.com/api/${params.resourceType}/${params.resourceId},
the handler forwards a request for /api/order/123 to
https://backend.example.com/api/customerorder/123.
Both approaches work. Modify params directly when you simply want the
rewritten URL to use the transformed values. Use context.custom when you want
to keep the original route parameters available (for logging or for use
elsewhere in the pipeline) while passing transformed values alongside them.
Variations
Using a Lookup Map
For more complex mappings where the transformation is not a simple string operation, use a lookup object:
Code
Transforming Multiple Parameters
You can transform any number of route parameters and store each on
context.custom. Reference them individually in the rewrite pattern:
Code
Then use both values in the rewrite pattern:
Code
Combining with Body Transformation
If your API also needs to transform values in the request body alongside route
parameters, you can handle both in the same inbound policy. Create a new
ZuploRequest with a modified body while storing the route parameter
transformations on context.custom:
Code
Best Practices
- Use descriptive keys on
context.custom— names likecontext.custom.transformedResourceTypeare easier to debug than generic keys likecontext.custom.value - Log transformations — use
context.logto record original and transformed values so you can trace issues in production - Validate before transforming — return an appropriate error response (using
HttpProblems) if a parameter value is unexpected, rather than forwarding bad data to your backend - Keep the policy focused — if your transformation logic is complex, consider splitting it into a separate utility module imported by the policy
Next Steps
- URL Rewrite Handler — full reference for rewrite patterns and available interpolation variables
- Custom Code Patterns — common patterns for writing inbound policies, outbound policies, and handlers
- ZuploContext — reference for
context.customand other context properties - ZuploRequest — reference for
request.paramsand constructing new requests - User-Based Backend Routing — a related
pattern using
context.customwith URL Rewrite for routing by user identity