openResty IP 数据库

2016-10-22 17:13:09 +08:00
 ysz1121

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-17mon/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 官方推荐脚本。

如有任何疑问欢迎联系我: solacowa@gmail.com

或访问我 网站: LatteCake

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

4145 次点击
所在节点    NGINX
6 条回复
ivmm
2016-10-22 17:15:12 +08:00
关于 OpenResty 有个疑惑。

它都是基于 Nginx 主线版本的,如果要用于生产环境那么稳定性如何呢? 还是说生产环境需要自己用 Nginx 安装相关模块?
ysz1121
2016-10-22 20:46:15 +08:00
@ivmm OpenResty 已经把 nginx 的主要模块包含进来了,你可以查看 openresty 包目录里的 nginx 目录。
ysz1121
2016-10-22 20:46:54 +08:00
@ivmm lua 没有多线程,如果有需要可以通过协同处理器来完成,这个我有写过,下次有机会我发出来
ivmm
2016-10-22 21:10:21 +08:00
@ysz1121 不是,我是说 OpenResty 是基于 Nginx mainline 的版本,而不是 stable 的版本。 生产环境怎么用。 可靠么,而且它 OpenResty 的主线更新还不及时
cnZary
2016-10-23 11:16:12 +08:00
双标题
neoblackcap
2016-10-23 12:31:44 +08:00
@ivmm cloudflare 在生产环境里面都是用 OpenRestry ,还是挺可靠的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/314668

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX