help request: native gRPC error mapping in traffic-shaping plugins (limit-conn, limit-req, limit-count)
- Dominant language
- Lua
- Stars
- 17.1k
- Forks
- 2.9k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 63
Description
### Description
Currently, when traffic-shaping plugins such as `limit-conn`, `limit-req`, or `limit-count` reject a request, they respond with a standard HTTP status code (e.g., `429 Too Many Requests`).
While this works for standard HTTP/REST traffic, it causes significant issues for gRPC clients. When a gRPC client receives a raw HTTP error with a non-200 status and text/HTML body, it cannot parse the response as a valid gRPC message. This leads to:
1. Client-side Protocol Errors: The client often falls back to a generic `Unavailable` or `Internal` error (e.g., "transport: received the unexpected content-type") instead of the actual reason.
2. Loss of Specificity: The client cannot distinguish between "Rate Limited" (`ResourceExhausted`) and "Server Down" (`Unavailable`).
3. Observability Gaps: Prometheus metrics based on the HTTP status code show a rejection, but gRPC-specified dashboards lose visibility into why the RPC failed.
### Workaround
To achieve protocol-compliant rejections and maintain observability, we have to implement a custom "post-processing" plugin with a very low priority. This plugin will catch rejections from other plugins and rewrite them during the `header_filter` & `body_filter` phases:
1. Set `ngx.status = 200`
2. Set `Content-Type: application/grpc`
3. Set `Content-Length: 0`
4. Set the appropriate HTTP status mapping for `grpc-status` and `grpc-message` headers
5. Ensure the response body is empty to satisfy the "Trailers-Only" gRPC requirement
---
I would like to inquire if there is an idiomatic or officially recommended way to handle protocol-compliant rejections for gRPC traffic within the existing APISIX architecture, or if this requirement should be considered as a candidate for a core feature enhancement to the traffic-shaping plugins.
### Environment
- APISIX version (run `apisix version`): 3.14.1
- Operating system (run `uname -a`): Linux
- OpenResty / Nginx version (run `openresty -V` or `nginx -V`): openresty/1.27.1.2
- etcd version, if relevant (run `curl http://127.0.0.1:9090/v1/server_info`):
- APISIX Dashboard version, if relevant:
- Plugin runner version, for issues related to plugin runners:
- LuaRocks version, for installation issues (run `luarocks --version`):
Contributor guide
Research direction
Start by reading the limit-conn, limit-req, and limit-count plugin implementations and the rejection paths they use. Compare those paths with the header_filter and body_filter phases described in the workaround, then document whether APISIX has an existing gRPC error-mapping entry point or define the scope of a core enhancement.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- lua, nginx
- Domain
- api, backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 32/100