├── .gitignore ├── .travis.yml ├── Makefile ├── README.md ├── dist.ini ├── lib └── resty │ └── ini.lua └── t ├── sample.ini └── sanity.t /.gitignore: -------------------------------------------------------------------------------- 1 | t/servroot 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | 4 | os: linux 5 | 6 | language: c 7 | 8 | env: 9 | globals: 10 | - TEST_NGINX_BINARY=openresty 11 | 12 | addons: 13 | apt: 14 | packages: 15 | - cpanminus 16 | 17 | before_install: 18 | - sudo cpanm --notest Test::Nginx > build.log 2>&1 || (cat build.log && exit 1) 19 | 20 | install: 21 | - wget -qO - https://openresty.org/package/pubkey.gpg | sudo apt-key add - 22 | - sudo apt-get -y install software-properties-common 23 | - sudo add-apt-repository -y "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main" 24 | - sudo apt-get update 25 | - sudo apt-get install -y --no-install-recommends openresty 26 | 27 | script: 28 | - export PATH=$PATH:/usr/local/openresty/nginx/sbin 29 | - openresty -V 30 | - make test 31 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | OPENRESTY_PREFIX=/usr/local/openresty-debug 2 | 3 | PREFIX ?= /usr/local 4 | LUA_INCLUDE_DIR ?= $(PREFIX)/include 5 | LUA_LIB_DIR ?= $(PREFIX)/lib/lua/$(LUA_VERSION) 6 | INSTALL ?= install 7 | 8 | #export TEST_NGINX_NO_CLEAN=1 9 | 10 | .PHONY: all test install 11 | 12 | all: ; 13 | 14 | install: all 15 | $(INSTALL) -d $(DESTDIR)/$(LUA_LIB_DIR)/resty 16 | $(INSTALL) lib/resty/ini.lua $(DESTDIR)/$(LUA_LIB_DIR)/resty 17 | 18 | test: 19 | PATH=$(OPENRESTY_PREFIX)/nginx/sbin:$$PATH prove -I../../test-nginx/lib -r t/ 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Name 2 | ===== 3 | 4 | lua-resty-ini - Lua ini parser 5 | 6 | Table of Contents 7 | ================= 8 | 9 | * [Name](#name) 10 | * [Status](#status) 11 | * [Synopsis](#synopsis) 12 | * [Author](#author) 13 | * [Copyright and License](#copyright-and-license) 14 | * [See Also](#see-also) 15 | 16 | Status 17 | ====== 18 | 19 | This library is still under early development and is still experimental. 20 | 21 | 22 | 23 | Synopsis 24 | ======== 25 | 26 | ```lua 27 | lua_package_path "/path/to/lua-resty-ini/lib/?.lua;;"; 28 | 29 | server { 30 | location /test { 31 | content_by_lua_block { 32 | local resty_ini = require "resty.ini" 33 | 34 | local conf, err = resty_ini.parse_file("/path/to/file.ini") 35 | if not conf then 36 | ngx.say("failed to parse_file: ", err) 37 | return 38 | end 39 | 40 | for section, values in pairs(conf) do 41 | for k, v in pairs(values) do 42 | ngx.say(section, ": '", k, "', '", v, "', ", type(v)) 43 | end 44 | end 45 | } 46 | } 47 | } 48 | ``` 49 | 50 | file.ini 51 | ```ini 52 | [default] 53 | username = ngx_test 54 | password = ngx_test 55 | notes = "just for test" 56 | number = 10 57 | 58 | [guest] 59 | username= guest 60 | ; guest do not need password 61 | password = false 62 | ``` 63 | 64 | ```shell 65 | $ curl "http://127.0.0.1:80/t" 66 | guest: 'password', 'false', boolean 67 | guest: 'username', 'guest', string 68 | default: 'password', 'ngx_test', string 69 | default: 'username', 'ngx_test', string 70 | default: 'notes', 'just for test', string 71 | default: 'number', '10', number 72 | ``` 73 | 74 | 75 | Author 76 | ====== 77 | 78 | Dejiang Zhu (doujiang24) . 79 | 80 | 81 | [Back to TOC](#table-of-contents) 82 | 83 | Copyright and License 84 | ===================== 85 | 86 | This module is licensed under the BSD license. 87 | 88 | Copyright (C) 2016-2016, by Dejiang Zhu (doujiang24) . 89 | 90 | All rights reserved. 91 | 92 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 93 | 94 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 95 | 96 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 97 | 98 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 99 | 100 | 101 | [Back to TOC](#table-of-contents) 102 | 103 | See Also 104 | ======== 105 | * the ngx_lua module: http://wiki.nginx.org/HttpLuaModule 106 | 107 | [Back to TOC](#table-of-contents) 108 | 109 | -------------------------------------------------------------------------------- /dist.ini: -------------------------------------------------------------------------------- 1 | name=lua-resty-ini 2 | abstract=ini parser for OpenResty 3 | author=doujiang24 4 | is_original=yes 5 | license=bsd 6 | lib_dir=lib 7 | repo_link=https://github.com/doujiang24/lua-resty-ini 8 | -------------------------------------------------------------------------------- /lib/resty/ini.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (C) Dejiang Zhu(doujiang24) 2 | 3 | 4 | local io_open = io.open 5 | local tonumber = tonumber 6 | local re_match = ngx.re.match 7 | local substr = string.sub 8 | local str_byte = string.byte 9 | 10 | 11 | local _M = { _VERSION = "0.01" } 12 | 13 | local section_pattern = [=[ \A \[ ([^\[\]]+) \] \z ]=] 14 | local keyvalue_pattern = 15 | [[ \A \s* ( [\w_]+ ) \s* = \s* ( ' [^']* ' | " [^"]* " | \S+ ) (?:\s*)? \z ]] 16 | 17 | 18 | function _M.parse_file(filename) 19 | local fp, err = io_open(filename) 20 | if not fp then 21 | return nil, "failed to open file: " .. (err or "") 22 | end 23 | 24 | local data = {} 25 | local section = "default" 26 | 27 | for line in fp:lines() do 28 | local m = re_match(line, section_pattern, "jox") 29 | if m then 30 | section = m[1] 31 | 32 | else 33 | local m = re_match(line, keyvalue_pattern, "jox") 34 | if m then 35 | if not data[section] then 36 | data[section] = {} 37 | end 38 | 39 | local key, value = m[1], m[2] 40 | 41 | local val = tonumber(value) 42 | if val then 43 | value = val 44 | 45 | elseif value == "true" then 46 | value = true 47 | 48 | elseif value == "false" then 49 | value = false 50 | 51 | else 52 | local fst = str_byte(value, 1) 53 | if fst == 34 or fst == 39 then -- ' or " 54 | value = substr(value, 2, -2) 55 | end 56 | end 57 | 58 | data[section][key] = value 59 | end 60 | end 61 | end 62 | 63 | fp:close() 64 | 65 | return data 66 | end 67 | 68 | 69 | return _M 70 | -------------------------------------------------------------------------------- /t/sample.ini: -------------------------------------------------------------------------------- 1 | ; server info 2 | [default] 3 | server=127.0.0.1 4 | port=3306 5 | 6 | ; user info 7 | username = ngx_test 8 | passwd= "xx; foo" 9 | badkey = "bad value" ; for test, this line will skip 10 | 11 | [guest] 12 | username= guest 13 | ; guest do no need password 14 | passwd = false 15 | limit_rate = '1r/s' 16 | 17 | [spa ce] 18 | foo = bar 19 | name = "foo" 20 | -------------------------------------------------------------------------------- /t/sanity.t: -------------------------------------------------------------------------------- 1 | # vim:set ts=4 sw=4 et: 2 | 3 | use Test::Nginx::Socket::Lua; 4 | use Cwd qw(cwd); 5 | 6 | repeat_each(1); 7 | 8 | plan tests => repeat_each() * (3 * blocks()); 9 | 10 | my $pwd = cwd(); 11 | 12 | our $HttpConfig = qq{ 13 | lua_package_path "$pwd/lib/?.lua;;"; 14 | }; 15 | 16 | $ENV{TEST_NGINX_PATH} = $pwd; 17 | 18 | no_long_string(); 19 | #no_diff(); 20 | 21 | run_tests(); 22 | 23 | __DATA__ 24 | 25 | === TEST 1: sanity 26 | --- http_config eval: $::HttpConfig 27 | --- config 28 | location /t { 29 | content_by_lua_block { 30 | local function sorted_keys(t) 31 | local keys = {} 32 | for k, _ in pairs(t) do 33 | keys[#keys + 1] = k 34 | end 35 | table.sort(keys) 36 | return keys 37 | end 38 | 39 | local resty_ini = require "resty.ini" 40 | 41 | local conf, err = resty_ini.parse_file("$TEST_NGINX_PATH/t/sample.ini") 42 | if not conf then 43 | ngx.say("failed to parse_file: ", err) 44 | return 45 | end 46 | 47 | for _, section in ipairs(sorted_keys(conf)) do 48 | local values = conf[section] 49 | 50 | for __, k in ipairs(sorted_keys(values)) do 51 | local v = values[k] 52 | ngx.say(section, ": '", k, "', '", v, "'") 53 | end 54 | end 55 | } 56 | } 57 | --- request 58 | GET /t 59 | --- response_body 60 | default: 'passwd', 'xx; foo' 61 | default: 'port', '3306' 62 | default: 'server', '127.0.0.1' 63 | default: 'username', 'ngx_test' 64 | guest: 'limit_rate', '1r/s' 65 | guest: 'passwd', 'false' 66 | guest: 'username', 'guest' 67 | spa ce: 'foo', 'bar' 68 | spa ce: 'name', 'foo' 69 | --- no_error_log 70 | [error] 71 | --------------------------------------------------------------------------------