You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
set_timeout/set_timeouts: validate inputs and define the connect-stage timeout budget #24
client:set_timeout(t) / client:set_timeouts(connect, send, read) are wired through but their semantics are underspecified and untested.
Gaps
1. No validation.
client.set_timeouts (lib/resty/ngx_http_ffi_client.lua:467) stores whatever it is given: self.connect_timeout = connect_timeout or self.connect_timeout. A non-number reaches the FFI call and raises a cdata conversion error from inside the library; a negative number is converted into ngx_msec_t (unsigned) and silently becomes a huge timeout. On the C side ngx_http_ffi_client_ffi_set_timeouts() (src/ngx_http_ffi_client_request.c:1817) ignores any value <= 0, so set_timeout(0) is a silent no-op rather than "no timeout" or an error.
2. The connect deadline is per-stage, not one budget, and DNS is outside it.
DNS: rctx->timeout = clcf->resolver_timeout (src/ngx_http_ffi_client_request.c:641) — bounded by the nginx resolver_timeout directive, not by connect_timeout.
TLS handshake: a fresh ngx_add_timer(c->read, op->connect_timeout) (src/ngx_http_ffi_client_request.c:1484).
So a caller asking for a 1s connect timeout can wait resolver_timeout + 1s + 1s before connect() returns. Whether that is intended (per-stage budgets, matching cosocket) or a bug (one shared deadline) needs to be decided and documented — ai-transport maps timeouts to 504, so the wall-clock a caller can observe matters.
3. No stall tests.
There is no test that actually stalls a connect, a TLS handshake, a send, or a read and asserts the timeout fires within the configured budget with the expected error string.
Proposal
Validate arguments in set_timeouts: reject non-numbers and negatives with a clear error; define 0 (either "unlimited" or rejected, but not a silent no-op).
Decide and document the connect-stage model: one shared connect deadline covering DNS + TCP + TLS, or explicit per-stage budgets with DNS bounded by resolver_timeout.
Add real stall tests for connect, TLS handshake, send, and read, asserting both the elapsed budget and the error string (timeout / timed out, matching the lua-resty-http strings ai-transport maps to 504).
api7/rfcs#115 - RFC: bring ngx_http_ffi_client to parity with lua-resty-http [merged] #19 - feat: add TLS (https, SNI, ssl_verify) to the request path [merged] api7/aisix#809 - fix(azure): apply stream_timeout per chunk, not as a whole-response ceiling [merged] #21 - feat: resolve hostnames through the nginx resolver [merged] #22 - feat: stateful client object with buffered and streaming reads [open]
📝 Issue Planner
Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.
Create Plan
🧪 Issue enrichment is currently in open beta.
You can configure auto-planning by selecting labels in the issue_enrichment configuration.
To disable automatic issue enrichment, add the following to your .coderabbit.yaml:
issue_enrichment:
auto_enrich:
enabled: false
💬 Have feedback or questions? Drop into our discord!
Activity
coderabbitai commentedon Jul 27, 2026
🔗 Related PRs
api7/rfcs#115 - RFC: bring ngx_http_ffi_client to parity with lua-resty-http [merged]
#19 - feat: add TLS (https, SNI, ssl_verify) to the request path [merged]
api7/aisix#809 - fix(azure): apply stream_timeout per chunk, not as a whole-response ceiling [merged]
#21 - feat: resolve hostnames through the nginx resolver [merged]
#22 - feat: stateful client object with buffered and streaming reads [open]
📝 Issue Planner
Check the box below or use the
@coderabbitai plancommand to generate an implementation plan and prompts that you can use with your favorite coding assistant.🧪 Issue enrichment is currently in open beta.
You can configure auto-planning by selecting labels in the issue_enrichment configuration.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!