技术解析

openResty IP 数据库
0
2021-05-21 03:06:14
idczone

openResty IP 数据库

ipip.net IP 数据库之 openresty 版,为了方便 nginx 使用 ip 数据所封装的拓展包。

使用方式

本脚本封装了 ipip.net 的主要接口配制好后就可以直接使用,并不需要再去复杂的内部实现。

需要注意的是如果使用 api 访问需要 http 拓展包。

代码我已提交至 GitHub: https://github.com/icowan/lua-resty-17mon

如果对 lua 不了解请看我前段时间写的: 《 Lua 基础学习方式 (一天学会) 》

如果还没安装 openresty 请看: 《优雅的安装 openresty 》

`

nginx 配制

要使用首先得载入自己写义的 lualib ,这个根据你安装的或使用方式去修改路径。

lua_package_path "/usr/local/openresty/lualib/?.lua;/var/www/lua-resty-17mon/lualib/?.lua;;";
lua_package_cpath "/usr/local/openresty/lualib/?.so;;";

error_log /var/www/lua-resty-17mon/logs/lua-resty-17mon.debug.log debug;

server {
    listen 8080;
    server_name localhost;
    charset utf-8;
    location /ipLocation {
        resolver 8.8.8.8; # 如果要使用 api 的话 需要 dns 这可以改成中国的会快一些
        default_type "text/plain";
        content_by_lua_file "/var/www/lua-resty-1美国服务器7mon/script/ip_location.lua";
    }
}

lua 脚本使用

-- /var/www/lua-resty-17mon/script/ip_location.lua

ngx.req.read_body()
ngx.header.content_type = "application/json;charset=UTF-8"

local cjson = require "cjson"

local success = function(con)
    return cjson.encode({
        success = true,
        body = con
    })
end

local failure = function(err)
    return cjson.encode({
        success = false,
        errors = err
    })
end

-- 参数获取
local request_args = ngx.req.get_uri_args()
local ip_address = request_args['ip']

-- 如果不需要验证可以不用此拓展
local checkIp = require("ip_check"):new(ip_address)

-- 验证 ip
local ok, err = checkIp:checkIp()
if not ok then
    ngx.say(failure(err))
    return
end

-- 使用本地数据库
local ipdetail, err = require("ip_location"):new(ip_address, "/var/www/lua-resty-17mon/file/17monipdb.dat")
if not ipdetail then
    ngx.log(ngx.ERR, err)
    ngx.say(failure(err))
    return
end

local ipLocation, err = ipdetail:location()
if not ipLocation then
    ngx.log(ngx.ERR, err)
    ngx.say(failure(err))
    return
end

ngx.say(success(ipLocation))

通过免费 api 获取 ip 信息

如果通过 api 获取数据需要使用 http 服务,这里需要使用lua-resty-http 这里我已经把它直接放到lualib/resty目录了,可以直接使用 感谢pintsized提供的脚本

-- /var/www/lua-resty-17mon/script/ip_location.lua

local ipdetail, err = require("ip_location"):new(ip_address)
if not ipdetail then
    ngx.log(ngx.ERR, err)
    ngx.say(failure(err))
    return
end

local ipLocation, err = ipdetail:locationApiFree()
if not ipLocation then
    ngx.log(ngx.ERR, err)
    ngx.say(failure(err))
    return
end

ngx.say(success(ipLocation))

通过付费 api 获取 ip 信息

-- /var/www/lua-resty-17mon/script/ip_location.lua

local ipdetail, err = require("ip_location"):new(ip_address, "", "your token")
if not ipdetail then
    ngx.log(ngx.ERR, err)
    ngx.say(failure(err))
    return
end

local ipLocation, err = ipdetail:locationApiFree()
if not ipLocation then
    ngx.log(ngx.ERR, err)
    ngx.say(failure(err))
    return
end

ngx.say(success(ipLocation))

获取 aip 使用状态

-- /var/www/lua-resty-17mon/script/ip_location.lua

local ipdetail, err = require("ip_location"):new(ip_address, "your token")
if not ipdetail then
    ngx.log(ngx.ERR, err)
    ngx.say(failure(err))
    return
end

local ipLocation, err = ipdetail:apiStatus()
if not ipLocation then
    ngx.log(ngx.ERR, err)
    ngx.say(failure(err))
    return
end

ngx.say(success(ipLocation))

返回数据结构

Response

返回类型: JSON

| 参数 | 类型 | 备注 | | --- | --- | --- | | success | bool | true or false | | errors or body | string | 当 success 为 false 时 errors 有值否则返回 body |

body 返回参数详情

| 参数 | 类型 | 备注 | | --- | --- | --- | | country | string | 国家 | | city | string | 省会或直辖市(国内) | | region | string | 地区或城市 (国内) | | place | string | 学校或单位 (国内) | | operator | string | 运营商字段 | | latitude | string | 纬度 | | longitude | string | 经度 | | timeZone | string | 时区一, 可能不存在 | | timeZoneCode | string | 时区码 | | administrativeAreaCode | string | 中国行政区划代码 | | internationalPhoneCode | string | 国际电话代码 | | countryTwoDigitCode | string | 国家二位代码 | | worldContinentCode | string | 世界大洲代码 |

返回结果参考:

{
	"success": true,
	"body": {
		"country": "",  // 国家
	    "city": "",  // 省会或直辖市(国内)
	    "region": "",  // 地区或城市 (国内)
	    "place": "",  // 学校或单位 (国内)
	    "operator": "",  // 运营商字段(只有购买了带有运营商版本的数据库才会有)
	    "latitude": "",  // 纬度     (每日版本提供)
	    "longitude": "",  // 经度     (每日版本提供)
	    "timeZone": "",  // 时区一, 可能不存在  (每日版本提供)
	    "timeZoneCode": "",  // 时区码, 可能不存在  (每日版本提供)
	    "administrativeAreaCode": "",  // 中国行政区划代码    (每日版本提供)
	    "internationalPhoneCode": "",  // 国际电话代码        (每日版本提供)
	    "countryTwoDigitCode": "",  // 国家二位代码        (每日版本提供)
	    "worldContinentCode": ""  // 世界大洲代码        (每日版本提供)
	}
}

ERROR 结果参考

{
	"success": false,
	"erros": "retun messages..."
}

查询状态结果参考

{
	"success": true,
	"body": {
		"limit": false, // 是否已受访问限制
       "hour": 99680,  // 一个小时内剩余次数
       "day": 999680,  // 24 小时内剩余次数
	}
}

尾巴

难得为开源社区贡献一份力量,希望有同样需求的同学们可以不用再去写复杂的底层逻辑,应该更多的把时间估计业务流程上。

同样希望这个脚本能提供给 ipip.net 官方推荐脚本。

如有任何疑问欢迎联系我: [email protected]

或访问我 网站: LatteCake

原文地址: https://lattecake.com/post/20102


关于 OpenResty 有个疑惑。
它都是基于 Nginx 主线版本的,如果要用于生产环境那么稳定性如何呢? 还是说生产环境需要自己用 Nginx 安装相关模块?

OpenResty 已经把 nginx 的主要模块包含进来了,你可以查看 openresty 包目录里的 nginx 目录。

lua 没有多线程,如果有需要可以通过协同处理器来完成,这个我有写过,下次有机会我发出来

不是,我是说 OpenResty 是基于 Nginx mainline 的版本,而不是 stable 的版本。 生产环境怎么用。 可靠么,而且它 OpenResty 的主线更新还不及时

双标题

cloudflare 在生产环境里面都是用 OpenRestry ,还是挺可靠的

数据地带为您的网站提供全球顶级IDC资源
在线咨询
专属客服