lua-resty-ip2region-xdb
ip2region v2.x/v3.x XDB searcher implemented via LuaJIT FFI
$ opm get Appla/lua-resty-ip2region-xdb
lua-resty-ip2region-xdb
LuaJIT FFI based ip2region xdb reader for OpenResty and plain LuaJIT.
This project reads ip2region xdb files directly from memory and supports:
IPv4 xdb databases
IPv6 xdb databases
OpenResty init/init_worker loading
low-allocation lookup paths via custom parsers
Requirements
LuaJIT
FFI support
bittable.new
This library is intended for OpenResty, but it can also run in plain LuaJIT.
Installation
Place the module under Lua's package path, for example:
lib/resty/ip2region_xdb.lua
lib/resty/ip2region_xdb_ipv6.lua
Then require it as:
local ip2region = require "resty.ip2region_xdb"
Quick Start
local ip2region = require "resty.ip2region_xdb"
local db = ip2region.new({
db_path = "/path/to/ip2region.xdb",
})
local info, err = db:lookup("8.8.8.8")
if not info then
ngx.say("lookup failed: ", err)
return
end
ngx.say(info.country)
ngx.say(info.region)
ngx.say(info.province)
ngx.say(info.city)
ngx.say(info.isp)
OpenResty Usage
The xdb file should be loaded during init_by_lua* or init_worker_by_lua*.
init_worker_by_lua_block {
local ip2region = require "resty.ip2region_xdb"
package.loaded.my_ip2region = ip2region.new({
db_path = "/path/to/ip2region.xdb",
})
}
Then use the object in request handling:
local db = package.loaded.my_ip2region
local info, err = db:lookup("1.1.1.1")
Constructor
local db = ip2region.new({
db_path = "/path/to/file.xdb",
parser_fn = optional_parser_fn,
})
Options:
db_path: required, xdb file pathparser_fn: optional default parser used bylookup_and_parse*
Behavior:
xdb file content is cached by
db_pathinside the worker processthe module detects IPv4 vs IPv6 from xdb metadata
db.metaexposes parsed header metadata
Return Formats
Most lookup methods accept an optional ct argument controlling the return shape.
ct == nil
Returns a table:
local info = db:lookup("8.8.8.8")
-- {
-- country = "...",
-- region = "...",
-- province = "...",
-- city = "...",
-- isp = "...",
-- }
ct == true
Returns multiple values:
local country, province, city, isp, region = db:lookup("8.8.8.8", true)
ct == 1..5
Returns a single field:
local city = db:lookup("8.8.8.8", db.IDX_CITY)
other values
Returns the raw region string:
local raw = db:lookup("8.8.8.8", false)
API
Common Methods
db:lookup(ip, ct?, dst_tab?)
Lookup by text IP string.
IPv4 database: dotted IPv4 string
IPv6 database: text IPv6 string
db:search_ip(ip, ct?, dst_tab?)
Alias of lookup.
db:lookup_city(ip)
Convenience wrapper returning the city field.
db:search_binary_ip(ip, ct?, dst_tab?)
Lookup by binary IP input.
IPv4 database:
numberuint32 IP4-byte Lua string
IPv6 database:
16-byte Lua string
db:set_parser(parser_fn)
Sets the instance parser used by lookup_and_parse*.
db:lookup_and_parse(ip, parser_fn?)
Performs lookup using text IP input and passes (ptr, len) or (nil, err) into parser_fn.
db:lookup_and_parse_binary(ip, parser_fn?)
Same as above, but for binary IP input.
db:ip_info_contains(ip, nds, ...)
Checks whether the region payload contains any needle.
ip: text IP stringnds: string or array of strings
db:binary_ip_info_contains(ip, nds, ...)
Same as above, but for binary IP input.
IPv6 Aliases
For IPv6 databases, these aliases are also available:
lookup_ipv6search_ipv6lookup_city_ipv6search_binary_ipv6ipv6_info_containsbinary_ipv6_info_containslookup_and_parse_ipv6lookup_and_parse_binary_ipv6
Parser Helpers
ip2region.forward_ptr
Built-in parser helper returning the raw (ptr, len) pair:
local ip2region = require "resty.ip2region_xdb"
local db = ip2region.new({
db_path = "/path/to/ip2region.xdb",
parser_fn = ip2region.forward_ptr,
})
This is useful when you want to avoid building Lua strings on the hot path.
Advanced Helpers
db.parse_ip(ip)
Current instance IP parser.
IPv4 database: text IPv4 to uint32
IPv6 database: text IPv6 to 16-byte cdata buffer
db.parse_bin_ip(ip)
Current instance binary IP parser.
IPv4 database: 4-byte string to uint32
IPv6 database: 16-byte string to 16-byte cdata buffer
db:update_idx(name, value)
Advanced override for field indexes on the current instance.
Supported names:
IDX_COUNTRYIDX_REGIONIDX_PROVINCEIDX_CITYIDX_ISPIDX_COUNTRY_CODE
This is mainly useful when adapting non-standard region field layouts.
Version Notes
The library supports xdb v2 and v3 style metadata.
Default public indexes are:
IDX_COUNTRY = 1IDX_REGION = 2IDX_PROVINCE = 3IDX_CITY = 4IDX_ISP = 5
For xdb version 3, the instance remaps indexes after loading:
IDX_COUNTRY = 1IDX_REGION = 2IDX_PROVINCE = 2IDX_CITY = 3IDX_ISP = 4IDX_COUNTRY_CODE = 5
When writing application code, prefer using instance fields such as db.IDX_CITY instead of hard-coded numbers.
Error Handling
Most methods return:
success: result
failure:
nil, err
Common errors:
invalid ipip must be a stringip must be a string(16)needle must not be emptynot foundxdb file too small or corrupted
Notes
In OpenResty, file loading is restricted to
initandinit_workerphases.xdb content is cached by file path per worker process.
Big-endian compatibility is handled in guarded branches, but little-endian Linux is the primary target.
License
Apache License 2.0.
Authors
Appla (@Appla)
License
apache2
Dependencies
luajit
Versions
-
ip2region v2.x/v3.x XDB searcher implemented via LuaJIT FFI 2026-05-23 11:10:43