Zuplo Changelog
We release improvements, new features, and fixes daily. Follow along here to see the most important updates.
Redirect Forwarding in URL Forward handler
We have added the ability to specify redirect behavior for the URL Forward
handler using a new forwardRedirects
option.
You can implement this manually from routes.oas.json
in your Zuplo project by
adding it to the options
object for urlForwardHandler
on any route you want
to use it on.
"paths": {
"/v1/links": {
"x-zuplo-path": {
"pathMode": "open-api"
},
"get": {
"summary": "Gets a list of links",
"x-zuplo-route": {
"corsPolicy": "none",
"handler": {
"export": "urlForwardHandler",
"module": "$import(@zuplo/runtime)",
"options": {
"baseUrl": "${env.BASE_URL}",
"forwardRedirects": true
}
},
"policies": {
"inbound": []
}
}
}
}
}
When set to false or not specified, redirects won't be followed - the status and
location
header will be returned as received.
New Default Compatibility Date
We’ve introduced a new default compatibility date for projects created after
March 27, 2025, which includes some breaking changes that improve the
overall behavior of Zuplo APIs.
The new default compatibility date is 2025-02-06.
Previously, special characters in open-api
formatted URLs were not escaped.
This led to unintended behavior where regex patterns could be included, even
though OpenAPI format URLs don’t support regex. This has now been fixed—all
special characters are escaped.
Additionally, some Zuplo log plugins could be enabled using undocumented
environment variables and special properties on context.custom
to set global
log attributes.
These legacy features, which predate the current plugin system, have now been removed.
Log plugins should now be enabled using the documented plugin system.
For full details on compatibility dates and the changes they include, see our documentation.
Zuplo Release v6.45.0
This release introduces new logging integrations with New Relic and Splunk, fixes several issues with the CLI and runtime, and improves documentation for fine-grained authorization policies.
New Features 🎉#
- Added New Relic logging and metrics plugin - Enable comprehensive observability by sending logs and metrics to New Relic for monitoring and analysis
- Added Splunk log transport - Stream your API logs directly to Splunk for centralized log management and analysis
Bug Fixes 🐛#
- Fixed excessive error logging in rate limiter - Rate limiter failures no longer generate unnecessary error logs, reducing log noise
- Fixed typos in CLI OpenAPI merge functionality - Corrected command syntax issues that prevented proper OpenAPI specification merging
- Fixed tunnel list command authentication - The
tunnel-list
command now properly supports the updated authentication mechanism - Fixed AWS Lambda handler query string handling - Multi-value query strings are now correctly parsed and passed to Lambda functions
Documentation 📚#
- Added documentation for Fine-Grained Authorization (FGA) policy - Learn how to implement fine-grained access control using OpenFGA
Other Changes 🔄#
- Added build script to Zudoku template - The developer portal template now includes a build script for easier deployment
- Fixed API quota documentation - Updated quota configuration examples and clarified usage limits
New Relic Logging Plugin
We've expanded our range of third-party logging plugins yet again—this time with the addition of New Relic.
Full details can be found in the documentation, but usage follows the same pattern as all the other loggers.
Add the plugin to the Zuplo runtime and configure your options.
import {
RuntimeExtensions,
NewRelicLoggingPlugin,
environment,
} from "@zuplo/runtime";
export function runtimeInit(runtime: RuntimeExtensions) {
runtime.addPlugin(
new NewRelicLoggingPlugin({
// Optional, defaults to "https://log-api.newrelic.com/log/v1"
url: "https://log-api.newrelic.com/log/v1",
apiKey: environment.NEW_RELIC_API_KEY,
service: "MyAPI", // Optional, defaults to "Zuplo"
fields: {
field1: "value1",
field2: "value2",
},
}),
);
}
As with all our loggers, the New Relic Plugin supports custom fields in addition to the standard fields.
This release introduces significant enhancements to request handling, CLI authentication, logging capabilities, and observability. Key features include a new pre-routing hook for request manipulation before routing, enhanced CLI authentication supporting both Auth0 and API Key methods, custom log fields across all logging plugins, and improved tracing for programmatically invoked policies.
New Features 🎉#
-
Pre-routing hook - Introduces a powerful new hook that allows you to manipulate incoming requests before routing checks are performed. This enables use cases like making URLs case-insensitive or normalizing URL paths. Learn more about pre-routing hooks
-
Custom log fields for all logging plugins - All logging plugins now support a
fields
option that allows you to append custom fields to every log entry. This enhancement enables better log enrichment and correlation across your observability stack. See custom log fields documentation -
Tracing for programmatically invoked policies - Policies that are invoked programmatically now include proper tracing information, improving observability and debugging capabilities when policies call other policies within your API gateway. Learn about API monitoring with OpenTelemetry
Bug Fixes 🐛#
- Enhanced error handling - Strengthened error handling checks for the
throwOnError
configuration option, ensuring more predictable behavior when errors occur in your API gateway.
Documentation 📚#
- CLI command consistency - Updated the CLI documentation and commands to
consistently use
zuplo
instead of the shortenedzup
command, improving clarity and consistency across all documentation.
New Pre-Routing Hook
The new Pre-Routing Hook allows you to manipulate an incoming request before it's checked for routing. For example, if you want all routes to be case insensitive you could just lowercase the URL as it comes into the gateway, as shown below:
runtime.addPreRoutingHook(async (request) => {
const nr = new Request(request.url.toLowerCase(), request);
return nr;
});
Another example would be URL path normalization to remove trailing slashes:
runtime.addPreRoutingHook(async (request) => {
const url = new URL(request.url);
if (url.pathname.length > 1 && url.pathname.endsWith("/")) {
url.pathname = url.pathname.slice(0, -1);
const nr = new Request(url, request);
return nr;
}
return request;
});
Keep in mind that this will run on all requests so the code you use here needs to be appropriately performant and aware it can generate weird downstream effects by changing URLs and headers.
The method is async but reading and manipulating the request body is not recommended for performance reasons.