shreemaan-abhishek commented on code in PR #13778:
URL: https://github.com/apache/apisix/pull/13778#discussion_r3728489224
##########
apisix/plugins/ai-transport/http.lua:
##########
@@ -19,17 +19,130 @@
-- Provides HTTP client lifecycle management for AI provider requests.
local core = require("apisix.core")
-local http = require("resty.http")
local ngx_now = ngx.now
local pairs = pairs
local ipairs = ipairs
local pcall = pcall
+local require = require
local type = type
local str_lower = string.lower
local tostring = tostring
+local FFI_CLIENT = "ngx_http_ffi_client"
+local LUA_RESTY_HTTP = "lua-resty-http"
+
+-- the client name in the config is not the module name
+local CLIENT_MODULES = {
+ [FFI_CLIENT] = "resty.ngx_http_ffi_client",
+ [LUA_RESTY_HTTP] = "resty.http",
+}
+
+local attr_schema = {
+ type = "object",
+ properties = {
+ http_client = {
+ type = "string",
+ enum = {FFI_CLIENT, LUA_RESTY_HTTP},
+ default = FFI_CLIENT,
+ },
+ },
+}
+
local _M = {}
+local http_client
+local http_client_is_ffi
+
+
+--- Pick the outbound HTTP client.
+-- `plugin_attr.ai-proxy.http_client` names it: "ngx_http_ffi_client", the
+-- default, or "lua-resty-http". The first is a C client with the same object
+-- API as the second and around half its outbound CPU cost, and it exists only
+-- when the gateway runtime was built with the module.
+-- Resolved on first request, because local_conf is not readable while the
+-- module is still loading, and cached only once a client has been loaded.
+local function resolve_client()
+ if http_client then
+ return http_client
+ end
+
+ local local_conf = core.config.local_conf()
+ local attr = core.table.try_read_attr(local_conf, "plugin_attr",
"ai-proxy") or {}
+
+ local ok, err = core.schema.check(attr_schema, attr)
+ if not ok then
+ core.log.error("invalid plugin_attr.ai-proxy: ", err)
+ return nil, "invalid plugin_attr.ai-proxy: " .. err
+ end
+
+ local name = attr.http_client or FFI_CLIENT
+ local module_name = CLIENT_MODULES[name]
+
+ local mod
+ ok, mod = pcall(require, module_name)
+ if not ok or type(mod) ~= "table" then
+ core.log.error(module_name, " is not available: ", mod)
+ return nil, module_name .. " is not available: " .. tostring(mod)
+ end
+
+ http_client = mod
+ http_client_is_ffi = name == FFI_CLIENT
+
+ return http_client
+end
+
+
+--- Resolve the upstream name the way every other socket in the gateway does.
+-- Cosockets are patched (apisix/patch.lua) to run names through
+-- core.resolver, which honours dns_resolver, /etc/hosts and the search
+-- domains. The C client dials on its own and only sees nginx's `resolver`,
+-- so the name is resolved here and kept for the Host header and the SNI.
+local function resolve_upstream_host(params)
Review Comment:
ngx_http_ffi_client dials from C, so it never touches the cosocket that
patch.lua wraps — it only sees nginx's `resolver`, which does not read
/etc/hosts or our dns_resolver config. That is why every `localhost` upstream
500'd. Resolving here puts it back on the same path as every other socket in
the gateway, and we keep the name for Host and SNI.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]