V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
ysz1121
V2EX  ›  NGINX

openResty IP 数据库

  •  
  •   ysz1121 · Oct 22, 2016 · 4699 views
    This topic created in 3473 days ago, the information mentioned may be changed or developed.

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

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

    或访问我 网站: LatteCake

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

    Supplement 1  ·  Oct 22, 2016

    修复一处错误:

    local ipLocation, err = ipdetail:locationApi("your sid", "your uid")
    if not ipLocation then
        ngx.log(ngx.ERR, err)
        ngx.say(failure(err))
        return
    end
    

    负费的应该使用ipdetail:locationApi("your sid", "your uid") 这个方法

    6 replies    2016-10-23 12:31:44 +08:00
    ivmm
        1
    ivmm  
       Oct 22, 2016
    关于 OpenResty 有个疑惑。

    它都是基于 Nginx 主线版本的,如果要用于生产环境那么稳定性如何呢? 还是说生产环境需要自己用 Nginx 安装相关模块?
    ysz1121
        2
    ysz1121  
    OP
       Oct 22, 2016
    @ivmm OpenResty 已经把 nginx 的主要模块包含进来了,你可以查看 openresty 包目录里的 nginx 目录。
    ysz1121
        3
    ysz1121  
    OP
       Oct 22, 2016
    @ivmm lua 没有多线程,如果有需要可以通过协同处理器来完成,这个我有写过,下次有机会我发出来
    ivmm
        4
    ivmm  
       Oct 22, 2016
    @ysz1121 不是,我是说 OpenResty 是基于 Nginx mainline 的版本,而不是 stable 的版本。 生产环境怎么用。 可靠么,而且它 OpenResty 的主线更新还不及时
    cnZary
        5
    cnZary  
       Oct 23, 2016
    双标题
    neoblackcap
        6
    neoblackcap  
       Oct 23, 2016
    @ivmm cloudflare 在生产环境里面都是用 OpenRestry ,还是挺可靠的
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   4713 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 61ms · UTC 04:05 · PVG 12:05 · LAX 21:05 · JFK 00:05
    ♥ Do have faith in what you're doing.