API7 Gateway 3.10.0
HMAC Auth — The hmac-auth plugin now defaults signed_headers to ["date"].
Release Date: 2026-06-01
Breaking Changes
Plugins
-
HMAC Auth (opens in Plugin Hub docs)
Upgrade note
The
hmac-authplugin now defaultssigned_headersto["date"]. After the Data Plane is upgraded, anyhmac-authconfiguration that does not explicitly setsigned_headersrequires the client signature to cover theDateheader. Clients that were not signingDatewill start receivingHTTP 401withclient request can't be validated.Before upgrading, ensure your clients sign the
Dateheader, or setsigned_headersexplicitly in the plugin configuration to match what your clients sign.
Control Plane
-
Service Templates and API Publishing removed
Upgrade note
The Service Template / Service Hub model has been removed. Services are now owned directly by gateway groups and managed through the APISIX Admin API — there is no longer a separate template, publish, version, rollback, or runtime-configuration layer. In the Console, the Service Hub section is replaced by a Services list under each gateway group.
When the Control Plane is upgraded to 3.10.0, existing service templates and published services are automatically migrated to the new direct-service model. The original data is preserved (not dropped), so the upgrade can be rolled back. IAM permission policies that referenced service-template or published-service ARNs are backed up and rewritten automatically.
Developer Portal
-
Developer authentication is enforced only for published API products
Upgrade note
Previously, API products in draft state also had their developer authentication rules synced to the gateway, so routes belonging to a draft product required developer authentication. Starting in 3.10.0, only published API products contribute developer-authentication rules to the data plane.
After upgrading, routes that belong to a draft (unpublished) API product no longer require developer authentication until the product is published. If you relied on draft products being protected, publish them or restrict access another way.
Upgrade Notes
Upgrade note — Data Plane runtime upgraded to OpenResty 1.29
The Data Plane gateway runtime has been upgraded from OpenResty 1.21.4.4 to OpenResty 1.29.2.4, and now builds on the open-source apisix-runtime base. The primary motivation is to pick up the latest upstream security fixes in the NGINX core, OpenSSL, LuaJIT, and the bundled libraries by moving across several major versions.
Most deployments require no action. One visible consequence is that HTTP/2 is now enabled with the NGINX 1.25+ http2 on; directive instead of the per-listen http2 parameter; HTTP/2 over cleartext (h2c) and over TLS continues to work as before. If you maintain custom NGINX configuration snippets, verify they are compatible with the newer NGINX before upgrading.
Upgrade note — additional plugin secret fields are encrypted at rest
The Control Plane now encrypts additional credential-bearing plugin fields at rest. Because API7 EE upgrades the Control Plane before the Data Plane, during the upgrade window a 3.10.0 Control Plane encrypts these fields while an older 3.9.13 Data Plane cannot decrypt them, which can cause the affected plugins to fail until the Data Plane is also upgraded.
The newly encrypted fields, by plugin, are:
- feishu-auth:
secret_fallbacks - dingtalk-auth:
secret_fallbacks
If you use any of these plugins with the listed fields, upgrade the Data Plane to 3.10.0 promptly after the Control Plane, and avoid editing those plugins until both sides are on 3.10.0.
Features
Plugins
- AI Proxy (opens in Plugin Hub docs)
- The upstream LLM request body is now JSON-encoded with sorted keys. This produces a stable, byte-identical body for equivalent requests, which improves prompt-cache hit rates on LLM providers that cache by exact request payload.
- AI Proxy Multi (opens in Plugin Hub docs)
- When an LLM endpoint domain resolves to multiple A records, the plugin now resolves all of them and builds a multi-node upstream, selecting a node per request for better load distribution and failover. The
Hostheader and TLS SNI keep the original domain name rather than the resolved IP address.
- When an LLM endpoint domain resolves to multiple A records, the plugin now resolves all of them and builds a multi-node upstream, selecting a node per request for better load distribution and failover. The
- Proxy Cache (opens in Plugin Hub docs)
- The in-memory cache strategy now honors the
Varyresponse header. Responses are cached per variant computed from the headers listed inVary, and responses withVary: *are not cached.
- The in-memory cache strategy now honors the
- CAS Auth
cas_callback_urinow accepts an absolute URL, which is used as-is as the CAS service URL. This is useful when the gateway sits behind a proxy and the externally visible callback URL differs from the request path.
Console (Dashboard)
- Added a visual editor for permission policy statements. You can now build IAM policies by selecting resource types, actions (annotated with their access level), and conditions, without hand-writing the policy JSON.
- Configuration compatibility warnings now show each affected resource with its full business hierarchy path (for example, gateway group → service → route) instead of a bare resource ID, making it easier to locate the configuration that needs attention.
Fixes
Plugins
- Error Page (opens in Plugin Hub docs)
- Fixed issue: The plugin decided whether to render a custom error page based on the upstream status variable, which could replace error responses that actually came from the upstream service. It now classifies the response source — custom error pages are rendered only for errors generated by the gateway or plugins (such as upstream connection failures or plugin-rejected requests), while genuine error responses returned by the upstream are passed through unchanged so their original body is preserved.
- Feishu Auth
- Fixed issue: A client could supply a forged
X-Userinfoheader that was forwarded upstream. The plugin now clears any client-suppliedX-Userinfoheader before authentication, so upstream services only receive plugin-verified identity information.
- Fixed issue: A client could supply a forged
- CAS Auth
- Fixed issue: The login callback did not validate the signed initiation cookie, allowing a crafted callback request to drive the post-login redirect (CSRF / open-redirect). The callback now requires a valid signed initiation cookie and is rejected with
HTTP 401otherwise.
- Fixed issue: The login callback did not validate the signed initiation cookie, allowing a crafted callback request to drive the post-login redirect (CSRF / open-redirect). The callback now requires a valid signed initiation cookie and is rejected with
- DingTalk Auth
- Fixed issue: Authentication failures and transient upstream failures were not distinguished. The plugin now returns
HTTP 401for authentication errors andHTTP 503for transient DingTalk or upstream failures, with clearer error messages.
- Fixed issue: Authentication failures and transient upstream failures were not distinguished. The plugin now returns
- Authz Casdoor
- Fixed issue: The session cookie name was shared across Casdoor clients, so sessions for different clients could collide. The session cookie is now scoped per client (derived from
client_id).
- Fixed issue: The session cookie name was shared across Casdoor clients, so sessions for different clients could collide. The session cookie is now scoped per client (derived from
- Authz Keycloak (opens in Plugin Hub docs)
- Fixed issue: When static
permissionswere combined withhttp_method_as_scope, the derived method scope was written back to the reused plugin configuration, causing scopes to accumulate across requests. The permission list is now cloned before the method scope is appended.
- Fixed issue: When static
- GraphQL Limit Count (opens in Plugin Hub docs)
- Fixed issue: The query nesting depth was miscalculated, making depth-based rate limiting inaccurate. Depth is now computed from the true maximum nesting depth with fragment expansion. Content-Type matching also tolerates a charset parameter (such as
application/json; charset=utf-8), which was previously rejected.
- Fixed issue: The query nesting depth was miscalculated, making depth-based rate limiting inaccurate. Depth is now computed from the true maximum nesting depth with fragment expansion. Content-Type matching also tolerates a charset parameter (such as
- GraphQL Proxy Cache (opens in Plugin Hub docs)
- Fixed issue: Requests whose
Content-Typeincluded a charset parameter were not recognized as GraphQL requests. Content-Type matching is now charset-tolerant, along with additional nil guards, clearer error messages, and corrected log levels.
- Fixed issue: Requests whose
Data Plane
- Fixed issue: When multiple logging plugins captured the response body on the same request (for example,
http-loggerandfile-loggerboth withinclude_resp_bodyenabled), their response-body buffers could interfere with each other, producing truncated or mixed log output. Each logger now uses an isolated buffer.