Files
eth-rpc-proxy/nginx-proxy/lua/request_handler.lua

149 lines
5.0 KiB
Lua

local json = require("cjson")
local http = require("resty.http")
local cache = require("cache.cache")
local request_utils = require("utils.request_utils")
-- Read request body once and reuse it throughout the handler
ngx.req.read_body()
local body_data = ngx.req.get_body_data() or ""
-- Extract and validate path parameters
local chain, network, provider_type, err = request_utils.parse_url_path(ngx.var.uri)
if err then
ngx.log(ngx.ERR, err)
ngx.status = 400
ngx.say(err)
return
end
-- Get providers for the requested chain/network
local chain_network_key = request_utils.get_chain_network_key(chain, network)
local providers_str = ngx.shared.providers:get(chain_network_key)
if not providers_str then
ngx.log(ngx.ERR, "No providers found for ", chain_network_key)
ngx.status = 404
ngx.say("No providers available for this chain/network")
return
end
-- Safely decode providers JSON with error handling
local ok, providers = pcall(json.decode, providers_str)
if not ok then
ngx.log(ngx.ERR, "Invalid providers JSON for ", chain_network_key, ": ", providers)
ngx.status = 500
ngx.say("Internal server error: invalid providers configuration")
return
end
-- Check cache with unified function (handles all cache operations)
local cache_info = cache.check_cache(chain, network, body_data)
if cache_info.cached_response then
ngx.header["Content-Type"] = "application/json"
if cache_info.cache_status then
ngx.header["X-Cache-Status"] = cache_info.cache_status
end
if cache_info.cache_level then
ngx.header["X-Cache-Level"] = cache_info.cache_level
end
ngx.say(cache_info.cached_response)
return
end
if #providers == 0 then
ngx.log(ngx.ERR, "No providers found for ", chain_network_key)
ngx.status = 404
ngx.say("No providers available for this chain/network")
return
end
-- Filter providers by provider_type if specified
local providers_to_try, tried_specific_provider = request_utils.filter_providers(providers, provider_type)
if #providers_to_try == 0 then
ngx.log(ngx.ERR, "No providers found for provider_type: ", provider_type or "none")
ngx.status = 404
ngx.say("No providers available for this provider type")
return
end
local success = false
for _, provider in ipairs(providers_to_try) do
local httpc = http.new()
-- Setup authentication and headers using request_utils
local base_headers = {
["Content-Type"] = "application/json"
}
local request_url, request_headers = request_utils.setup_auth(provider, provider.url, base_headers)
local res, err = httpc:request_uri(request_url, {
method = ngx.req.get_method(),
body = body_data,
headers = request_headers,
ssl_verify = false,
options = { family = ngx.AF_INET }
})
if res then
local ok, decoded_response = pcall(json.decode, res.body)
local decoded = ok and decoded_response or nil
-- Check if we should retry with next provider using request_utils
if not request_utils.should_retry(res, decoded) then
-- Cache response if cacheable
if cache_info.cache_type then
cache.save_to_cache(cache_info, res.body)
end
-- Success! Manually set response, filtering out unwanted headers
ngx.status = res.status
-- Filter headers using request_utils
local filtered_headers = request_utils.filter_response_headers(res.headers)
for key, value in pairs(filtered_headers) do
ngx.header[key] = value
end
-- Set cache status header for non-cached responses
if cache_info.cache_status then
ngx.header["X-Cache-Status"] = cache_info.cache_status
else
-- Default to MISS if cache_status is not available
ngx.header["X-Cache-Status"] = "MISS"
end
-- Set cache level header for non-cached responses
if cache_info.cache_level then
ngx.header["X-Cache-Level"] = cache_info.cache_level
else
-- Default to MISS if cache_level is not available
ngx.header["X-Cache-Level"] = "MISS"
end
-- Set response body
ngx.say(res.body)
success = true
break
else
if res.status then
ngx.log(ngx.ERR, "Error status ", res.status, ", trying next provider")
elseif decoded and decoded.error then
ngx.log(ngx.ERR, "JSON-RPC error code ", decoded.error.code, ", trying next provider")
end
end
else
ngx.log(ngx.ERR, "HTTP request failed: ", err)
end
end
if not success then
if provider_type and provider_type ~= "" and not tried_specific_provider then
ngx.status = 404
ngx.say("Provider not found: " .. provider_type)
else
ngx.status = 502
ngx.say("All providers failed")
end
end