├── .gitignore ├── .travis.yml ├── .travis ├── platform.sh ├── setenv_lua.sh ├── setup_lua.sh └── setup_servers.sh ├── CHANGELOG.md ├── LICENSE.md ├── README-zh.md ├── README.md ├── README ├── README-V0.1.0-rc4.1.md └── README-zh-V0.1.0-rc4.1.md ├── TODO.md ├── configure ├── dist.ini ├── docker ├── Dockerfile ├── README.md └── supervisord.conf ├── rockspecs ├── vanilla-0.1.0.rc4-1.rockspec ├── vanilla-0.1.0.rc5-1.rockspec └── vanilla-0.1.0.rc6-1.rockspec ├── setup-framework ├── setup-vanilla-demoapp ├── spec ├── helper.lua └── v │ └── dispatcher_spec.lua ├── vanilla-0.1.0.rc7-1.rockspec ├── vanilla-en.png ├── vanilla-pub.png └── vanilla ├── Makefile ├── base ├── init.lua ├── opm.lua ├── registry.lua └── resty │ ├── cookie.lua │ ├── http.lua │ ├── http_headers.lua │ ├── template.lua │ └── template │ ├── html.lua │ └── microbenchmark.lua ├── bin ├── lemplate ├── v-console └── vanilla ├── install ├── spec ├── init.lua ├── runner.lua └── runners │ ├── integration.lua │ └── response.lua ├── sys ├── application.lua ├── config.lua ├── console.lua ├── nginx │ ├── config.lua │ ├── directive.lua │ └── handle.lua ├── vanilla.lua └── waf │ ├── acc.lua │ └── config.lua └── v ├── application.lua ├── bootstrap.lua ├── cache.lua ├── cache ├── base.lua ├── lru.lua ├── mc.lua ├── redis.lua └── shdict.lua ├── config ├── handle.lua ├── parse.lua └── save.lua ├── controller.lua ├── dispatcher.lua ├── error.lua ├── libs ├── ansicolors.lua ├── cache.lua ├── cookie.lua ├── http.lua ├── logs.lua ├── reqargs.lua ├── session.lua ├── shcache.lua └── utils.lua ├── plugin.lua ├── registry.lua ├── request.lua ├── response.lua ├── router.lua ├── routes ├── restful.lua └── simple.lua ├── view.lua └── views ├── lemplate.lua └── rtpl.lua /.gitignore: -------------------------------------------------------------------------------- 1 | # vanilla 2 | client_body_temp 3 | fastcgi_temp 4 | logs 5 | proxy_temp 6 | tmp 7 | uwsgi_temp 8 | build 9 | Makefile 10 | *.zj 11 | 12 | # vim 13 | .*.sw[a-z] 14 | *.un~ 15 | Session.vim 16 | 17 | # textmate 18 | *.tmproj 19 | *.tmproject 20 | tmtags 21 | 22 | # OSX 23 | .DS_Store 24 | ._* 25 | .Spotlight-V100 26 | .Trashes 27 | *.swp 28 | pretty/zj 29 | 30 | # luarocks 31 | *.rock -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | sudo: false 4 | 5 | env: 6 | global: 7 | - LUAROCKS=2.2.2 8 | matrix: 9 | # Lua 5.1 10 | - LUA=lua5.1 11 | # LuaJIT latest stable version (2.0.4) 12 | - LUA=luajit 13 | # Openresty + LuaJIT + mysql 14 | - LUA=luajit SERVER=openresty 15 | # - LUA=luajit2.0 # current head of 2.0 branch 16 | # - LUA=luajit2.1 # current head of 2.1 branch 17 | # Not supported 18 | # - LUA=lua5.2 19 | # - LUA=lua5.3 20 | # - How 21 | 22 | branches: 23 | only: master 24 | 25 | before_install: 26 | - source .travis/setenv_lua.sh 27 | 28 | install: 29 | - luarocks install https://luarocks.org/manifests/olivine-labs/busted-2.0.rc12-1.rockspec 30 | - luarocks install lrexlib-pcre 2.7.2-1 31 | - luarocks install luaposix 32 | - luarocks install lua-cjson 33 | - luarocks install luasocket 34 | - luarocks make 35 | 36 | script: busted 37 | 38 | notifications: 39 | email: 40 | on_success: change 41 | on_failure: always 42 | -------------------------------------------------------------------------------- /.travis/platform.sh: -------------------------------------------------------------------------------- 1 | if [ -z "${PLATFORM:-}" ]; then 2 | PLATFORM=$TRAVIS_OS_NAME; 3 | fi 4 | 5 | if [ "$PLATFORM" == "osx" ]; then 6 | PLATFORM="macosx"; 7 | fi 8 | 9 | if [ -z "$PLATFORM" ]; then 10 | if [ "$(uname)" == "Linux" ]; then 11 | PLATFORM="linux"; 12 | else 13 | PLATFORM="macosx"; 14 | fi; 15 | fi 16 | -------------------------------------------------------------------------------- /.travis/setenv_lua.sh: -------------------------------------------------------------------------------- 1 | export PATH=${PATH}:$HOME/.lua:$HOME/.local/bin:${TRAVIS_BUILD_DIR}/install/luarocks/bin 2 | export PATH=${PATH}:$HOME/.lua:$HOME/.local/bin:${TRAVIS_BUILD_DIR}/install/openresty/nginx/sbin 3 | export PATH=${PATH}:$HOME/.lua:$HOME/.local/bin:${TRAVIS_BUILD_DIR}/install/openresty/bin 4 | bash .travis/setup_lua.sh 5 | if [ "$SERVER" == "openresty" ]; then 6 | bash .travis/setup_servers.sh 7 | fi 8 | 9 | eval `$HOME/.lua/luarocks path` 10 | -------------------------------------------------------------------------------- /.travis/setup_lua.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # A script for setting up environment for travis-ci testing. 4 | # Sets up Lua and Luarocks. 5 | # LUA must be "lua5.1", "lua5.2" or "luajit". 6 | # luajit2.0 - master v2.0 7 | # luajit2.1 - master v2.1 8 | 9 | set -eufo pipefail 10 | 11 | LUAJIT_BASE="LuaJIT-2.0.4" 12 | 13 | source .travis/platform.sh 14 | 15 | LUA_HOME_DIR=$TRAVIS_BUILD_DIR/install/lua 16 | 17 | LR_HOME_DIR=$TRAVIS_BUILD_DIR/install/luarocks 18 | 19 | mkdir $HOME/.lua 20 | 21 | LUAJIT="no" 22 | 23 | if [ "$PLATFORM" == "macosx" ]; then 24 | if [ "$LUA" == "luajit" ]; then 25 | LUAJIT="yes"; 26 | fi 27 | if [ "$LUA" == "luajit2.0" ]; then 28 | LUAJIT="yes"; 29 | fi 30 | if [ "$LUA" == "luajit2.1" ]; then 31 | LUAJIT="yes"; 32 | fi; 33 | elif [ "$(expr substr $LUA 1 6)" == "luajit" ]; then 34 | LUAJIT="yes"; 35 | fi 36 | 37 | mkdir -p "$LUA_HOME_DIR" 38 | 39 | if [ "$LUAJIT" == "yes" ]; then 40 | 41 | git clone https://github.com/LuaJIT/LuaJIT $LUAJIT_BASE; 42 | 43 | cd $LUAJIT_BASE 44 | 45 | if [ "$LUA" == "luajit2.1" ]; then 46 | git checkout v2.1; 47 | # force the INSTALL_TNAME to be luajit 48 | perl -i -pe 's/INSTALL_TNAME=.+/INSTALL_TNAME= luajit/' Makefile 49 | else 50 | git checkout v2.0.4; 51 | fi 52 | 53 | make && make install PREFIX="$LUA_HOME_DIR" 54 | 55 | ln -s $LUA_HOME_DIR/bin/luajit $HOME/.lua/luajit 56 | ln -s $LUA_HOME_DIR/bin/luajit $HOME/.lua/lua; 57 | 58 | else 59 | 60 | if [ "$LUA" == "lua5.1" ]; then 61 | curl http://www.lua.org/ftp/lua-5.1.5.tar.gz | tar xz 62 | cd lua-5.1.5; 63 | fi 64 | 65 | # Build Lua without backwards compatibility for testing 66 | perl -i -pe 's/-DLUA_COMPAT_(ALL|5_2)//' src/Makefile 67 | make $PLATFORM 68 | make INSTALL_TOP="$LUA_HOME_DIR" install; 69 | 70 | ln -s $LUA_HOME_DIR/bin/lua $HOME/.lua/lua 71 | ln -s $LUA_HOME_DIR/bin/luac $HOME/.lua/luac; 72 | 73 | fi 74 | 75 | cd $TRAVIS_BUILD_DIR 76 | 77 | lua -v 78 | 79 | LUAROCKS_BASE=luarocks-$LUAROCKS 80 | 81 | curl --location http://luarocks.org/releases/$LUAROCKS_BASE.tar.gz | tar xz 82 | 83 | cd $LUAROCKS_BASE 84 | 85 | if [ "$LUA" == "luajit" ]; then 86 | ./configure --lua-suffix=jit --with-lua-include="$LUA_HOME_DIR/include/luajit-2.0" --prefix="$LR_HOME_DIR"; 87 | elif [ "$LUA" == "luajit2.0" ]; then 88 | ./configure --lua-suffix=jit --with-lua-include="$LUA_HOME_DIR/include/luajit-2.0" --prefix="$LR_HOME_DIR"; 89 | elif [ "$LUA" == "luajit2.1" ]; then 90 | ./configure --lua-suffix=jit --with-lua-include="$LUA_HOME_DIR/include/luajit-2.1" --prefix="$LR_HOME_DIR"; 91 | else 92 | ./configure --with-lua="$LUA_HOME_DIR" --prefix="$LR_HOME_DIR" 93 | fi 94 | 95 | make build && make install 96 | 97 | ln -s $LR_HOME_DIR/bin/luarocks $HOME/.lua/luarocks 98 | 99 | cd $TRAVIS_BUILD_DIR 100 | 101 | luarocks --version 102 | 103 | rm -rf $LUAROCKS_BASE 104 | 105 | if [ "$LUAJIT" == "yes" ]; then 106 | rm -rf $LUAJIT_BASE; 107 | elif [ "$LUA" == "lua5.1" ]; then 108 | rm -rf lua-5.1.5; 109 | fi 110 | -------------------------------------------------------------------------------- /.travis/setup_servers.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # A script for setting up environment for travis-ci testing. 4 | # Sets up openresty. 5 | OPENRESTY_VERSION="1.9.15.1" 6 | OPENRESTY_DIR=$TRAVIS_BUILD_DIR/install/openresty 7 | 8 | #if [ "$LUA" == "lua5.1" ]; then 9 | # luarocks install LuaBitOp 10 | #fi 11 | 12 | wget https://openresty.org/download/openresty-$OPENRESTY_VERSION.tar.gz 13 | tar xzvf ngx_openresty-$OPENRESTY_VERSION.tar.gz 14 | cd ngx_openresty-$OPENRESTY_VERSION/ 15 | 16 | ./configure --prefix="$OPENRESTY_DIR" --with-luajit 17 | 18 | make 19 | make install 20 | 21 | ln -s $OPENRESTY_DIR/bin/resty $HOME/.lua/resty 22 | ln -s $OPENRESTY_DIR/nginx/sbin/nginx $HOME/.lua/nginx 23 | 24 | export PATH=${PATH}:$HOME/.lua:$HOME/.local/bin:${TRAVIS_BUILD_DIR}/install/openresty/nginx/sbin 25 | export PATH=${PATH}:$HOME/.lua:$HOME/.local/bin:${TRAVIS_BUILD_DIR}/install/openresty/bin 26 | 27 | nginx -v 28 | resty -V 29 | 30 | cd ../ 31 | rm -rf ngx_openresty-$OPENRESTY_VERSION 32 | cd $TRAVIS_BUILD_DIR 33 | 34 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## vanilla-0.1.0.rc7 TODO LIST 2 | 3 | * Full support OPM 4 | * Add Lemplate as A default View engine 5 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Roberto Ostinelli 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README-zh.md: -------------------------------------------------------------------------------- 1 | ## Vanilla / (香草[中文文档](README-zh.md)) / OSC [Git](http://git.oschina.net/idevz/vanilla) 2 | 3 | [![https://travis-ci.org/idevz/vanilla.svg?branch=master](https://travis-ci.org/idevz/vanilla.svg?branch=master)](https://travis-ci.org/idevz/vanilla) 4 | [![Join the chat at https://gitter.im/idevz/vanilla](https://badges.gitter.im/idevz/vanilla.svg)](https://gitter.im/idevz/vanilla?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 5 | [![Issue Stats](http://issuestats.com/github/idevz/vanilla/badge/pr)](http://issuestats.com/github/idevz/vanilla) 6 | [![Issue Stats](http://issuestats.com/github/idevz/vanilla/badge/issue)](http://issuestats.com/github/idevz/vanilla) 7 | 8 | *香草/Vanilla是一个基于Openresty实现的高性能Web应用开发框架.* 9 | 10 | ![Vanilla](vanilla-pub.png) 11 | 12 | ### *邮件列表* 13 | - vanilla-en 14 | - vanilla-devel 15 | - vanilla中文邮件列表 16 | 17 | 18 | ## 特性 19 | 20 | - 提供很多优良组件诸如:bootstrap、 router、 controllers、 models、 views。 21 | - 强劲的插件体系。 22 | - 多 Application 部署。 23 | - 多版本框架共存,支持便捷的框架升级。 24 | - 一键 nginx 配置、 应用部署。 25 | - 便捷的服务批量管理。 26 | - 你只需关注自身业务逻辑。 27 | 28 | ## 安装 29 | 30 | ##### *Vanilla-V0.1.0-rc4.1 或之前版本的 Vanilla 安装请参见 : [README-V0.1.0-rc4.1.md](README/README-zh-V0.1.0-rc4.1.md)* 31 | 32 | ``` bash 33 | $ ./setup-framework -v $VANILLA_PROJ_ROOT -o $OPENRESTY_ROOT #运行 ./setup-framework -h 查看更多参数细节 34 | ``` 35 | 36 | ## 快速开始 37 | 38 | **部署你的第一个Vanilla Application** 39 | 40 | ``` bash 41 | $ ./setup-vanilla-demoapp [-a $VANILLA_APP_ROOT -u $VANILLA_APP_USER -g $VANILLA_APP_GROUP -e $VANILLA_RUNNING_ENV] #运行 ./setup-vanilla-demoapp -h 查看更多参数细节 42 | ``` 43 | 44 | **启动你的 Vanilla 服务** 45 | 46 | ``` bash 47 | $ ./$VANILLA_APP_ROOT/va-appname-service start 48 | ``` 49 | 50 | ## 更多信息 51 | 52 | - 参见 [文档](https://idevz.gitbook.io/vanilla-zh/) 53 | 54 | ## License 55 | 56 | MIT 57 | 58 | 59 | ### 社区组织 60 | #### *QQ群&&微信公众号* 61 | - *Openresty/Vanilla 开发 1 群:205773855* 62 | - *Openresty/Vanilla 开发 2 群:419191655* 63 | - *Openresty 技术交流 1 群:34782325* 64 | - *Openresty 技术交流 2 群:481213820* 65 | - *Openresty 技术交流 3 群:124613000* 66 | - *Vanilla开发微信公众号:Vanilla-OpenResty(Vanilla相关资讯、文档推送)* 67 | 68 | 69 | [![QQ](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=673157ee0f0207ce2fb305d15999225c5aa967e88913dfd651a8cf59e18fd459) 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Vanilla / (香草[中文文档](README-zh.md)) / OSC [Git](http://git.oschina.net/idevz/vanilla) 2 | 3 | [![https://travis-ci.org/idevz/vanilla.svg?branch=master](https://travis-ci.org/idevz/vanilla.svg?branch=master)](https://travis-ci.org/idevz/vanilla) 4 | [![Join the chat at https://gitter.im/idevz/vanilla](https://badges.gitter.im/idevz/vanilla.svg)](https://gitter.im/idevz/vanilla?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 5 | 6 | *Vanilla is An OpenResty Lua MVC Web Framework.* 7 | 8 | ![Vanilla](vanilla-en.png) 9 | 10 | ### *MailList* 11 | - vanilla-en 12 | - vanilla-devel 13 | - vanilla中文邮件列表 14 | 15 | ## Features 16 | 17 | - Provide many good components such as bootstrap, router, controllers, models, views. 18 | - Powerful plugin system. 19 | - Multi applications deployment. 20 | - Multi version of framework coexistence, easier framwork upgrade. 21 | - Auto complete the Nginx configration. 22 | - A convenient way to manage Services. 23 | - You only need to focus your business logic. 24 | 25 | ## Installation 26 | 27 | ##### *Vanilla-V0.1.0-rc4.1 Or the older Vanillas Installation to see: [README-V0.1.0-rc4.1.md](README/README-V0.1.0-rc4.1.md)* 28 | 29 | ``` bash 30 | $ ./setup-framework -v $VANILLA_PROJ_ROOT -o $OPENRESTY_ROOT #see ./setup-framework -h for more details 31 | ``` 32 | 33 | ## Quick Start 34 | 35 | **Setup your Own Application** 36 | 37 | ``` bash 38 | $ ./setup-vanilla-demoapp [-a $VANILLA_APP_ROOT -u $VANILLA_APP_USER -g $VANILLA_APP_GROUP -e $VANILLA_RUNNING_ENV] #see ./setup-vanilla-demoapp -h for more details 39 | ``` 40 | 41 | **Start the server** 42 | 43 | ``` bash 44 | $ ./$VANILLA_APP_ROOT/va-appname-service start 45 | ``` 46 | 47 | ## More Information 48 | 49 | - Read the [documentation](https://idevz.gitbook.io/vanilla-zh/) 50 | 51 | ## License 52 | 53 | MIT 54 | 55 | 56 | ### Community 57 | #### *QQ Groups&&WeChat public no.* 58 | - *Openresty/Vanilla Dev:205773855 (Vanilla panel discussion related topics)* 59 | - *Openresty:34782325(Discuss OpenResty and all kinds of advanced technology)* 60 | - *WeChat public no. of Vanilla Dev:Vanilla-OpenResty(Vanilla related information, document push)* 61 | 62 | [![QQ](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=673157ee0f0207ce2fb305d15999225c5aa967e88913dfd651a8cf59e18fd459) 63 | -------------------------------------------------------------------------------- /README/README-V0.1.0-rc4.1.md: -------------------------------------------------------------------------------- 1 | ## Vanilla / (香草[中文文档](README-zh.md)) / OSC [Git](http://git.oschina.net/idevz/vanilla) 2 | 3 | [![https://travis-ci.org/idevz/vanilla.svg?branch=master](https://travis-ci.org/idevz/vanilla.svg?branch=master)](https://travis-ci.org/idevz/vanilla) 4 | [![Join the chat at https://gitter.im/idevz/vanilla](https://badges.gitter.im/idevz/vanilla.svg)](https://gitter.im/idevz/vanilla?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 5 | [![Issue Stats](http://issuestats.com/github/idevz/vanilla/badge/pr)](http://issuestats.com/github/idevz/vanilla) 6 | [![Issue Stats](http://issuestats.com/github/idevz/vanilla/badge/issue)](http://issuestats.com/github/idevz/vanilla) 7 | 8 | *Vanilla is An OpenResty Lua MVC Web Framework.* 9 | 10 | ![Vanilla](vanilla-en.png) 11 | 12 | ### *MailList* 13 | - vanilla-en 14 | - vanilla-devel 15 | - vanilla中文邮件列表 16 | 17 | ### *Install* 18 | *There are two ways to install:* 19 | 20 | - Make (recommended way) 21 | - Luarocks 22 | 23 | #### *Tips of ```make install```:* 24 | *Vanilla support many configuration options, many of those option have default value.* 25 | 26 | You can use default installation but if your enviroment values different from which vanilla default, please config it with yours. 27 | Especially the ```--openresty-path``` option. you should make sure it's point to your turely OpenResty install path. 28 | You can run command ```./configure --help``` to learn how to use those options. 29 | 30 | Below is the installation of a simple example: 31 | 32 | ~~~ 33 | ./configure --prefix=/usr/local/vanilla --openresty-path=/usr/local/openresty 34 | 35 | make install 36 | ~~~ 37 | 38 | #### *Tips of ```luarocks install```:* 39 | *You can use luarocks to install vanilla, but three point should be clear:* 40 | 41 | 1. Your luarocks should install with lua5.1.x because of the compatibility problems in ABIs between Lua and Luajit. 42 | 2. parameter NGX_PATH will be disabled in the nginx.conf. 43 | 3. make sure that command nginx is in your environment PATH. 44 | 45 | ### Vanilla usage 46 | #### *Vanilla CMDs* 47 | *Vanilla provide two commands ```vanilla```, and ```vanilla-console```.* 48 | 49 | - ```vanilla``` is for application building, service start, stop and so on. 50 | - ```vanilla-console``` is an interactive command line, you can use it for debugging, testing, Lua learning... 51 | 52 | Run ```vanilla``` in command line, you can find command ```vanilla``` provide three options. 53 | 54 | ``` 55 | vanilla 56 | Vanilla v0.1.0-rc3, A MVC web framework for Lua powered by OpenResty. 57 | 58 | Usage: vanilla COMMAND [ARGS] [OPTIONS] 59 | 60 | The available vanilla commands are: 61 | new [name] Create a new Vanilla application 62 | start Starts the Vanilla server 63 | stop Stops the Vanilla server 64 | restart First Stops and then Starts the Vanilla servers 65 | reload Reload nginx.conf of Vanilla server 66 | 67 | Options: 68 | --trace Shows additional logs 69 | ``` 70 | 71 | #### *Building up an application skeleton* 72 | ``` 73 | vanilla new app_name 74 | cd app_name 75 | vanilla start [--trace] -- default running in development environment. 76 | -- under bash on linux 77 | VA_ENV=production vanilla start [--trace] -- add VA_ENV to set the running environment. 78 | -- under tcsh on BSD 79 | setenv VA_ENV production ; vanilla start [--trace] -- add VA_ENV to set the running environment. 80 | ``` 81 | #### *Directory Structure* 82 | ``` 83 |  /Users/zj-git/app_name/ tree ./ 84 | ./ 85 | ├── application 86 | │   ├── bootstrap.lua --application boot 87 | │   ├── controllers 88 | │   │   ├── error.lua --application error handling, dealing with corresponding business under this path error 89 | │   │   └── index.lua --vanilla hello world 90 | │   ├── library --local libs 91 | │   ├── models 92 | │   │   ├── dao --data handles for DB, APIs 93 | │   │   │   └── table.lua 94 | │   │   └── service --encapsulations of DAOs 95 | │   │   └── user.lua 96 | │   ├── nginx --openresy http phases 97 | │   │   └── init.lua --init_by_lua demo 98 | │   ├── plugins 99 | │   └── views --one to one correspondence to controllers 100 | │   ├── error --error handle view layout 101 | │   │   └── error.html 102 | │   └── index --index controller views 103 | │   └── index.html 104 | ├── config 105 | │   ├── application.lua --app basic configuration such as router,initialization settings... 106 | │   ├── errors.lua --app error conf 107 | │   ├── nginx.conf --nginx.conf skeleton 108 | │   ├── nginx.lua --nginx settings like lua_code_cache. 109 | │   ├── waf-regs --WAF rules 110 | │   │   ├── args 111 | │   │   ├── cookie 112 | │   │   ├── post 113 | │   │   ├── url 114 | │   │   ├── user-agent 115 | │   │   └── whiteurl 116 | │   └── waf.lua --app WAF config 117 | ├── logs 118 | │   └── hack --attack logs, keep path can be write 119 | ├── pub --app content_by_lua_file path 120 | └── index.lua --entrance file 121 | ``` 122 | #### *IndexController Demo* 123 | ``` 124 | local IndexController = {} 125 | 126 | function IndexController:index() 127 | local view = self:getView() 128 | local p = {} 129 | p['vanilla'] = 'Welcome To Vanilla...' 130 | p['zhoujing'] = 'Power by Openresty' 131 | view:assign(p) 132 | return view:display() 133 | end 134 | 135 | return IndexController 136 | ``` 137 | ##### *Template demo (views/index/index.html)* 138 | ``` 139 | 140 | 141 | 142 | 143 |

{{vanilla}}

{{zhoujing}}
144 | 145 | 146 | ``` 147 | 148 | ### Why Vanilla 149 | *To answer this question, we just need to see what Openresty has done and Vanilla has done.* 150 | #### *Openresty* 151 | - Provides processing HTTP requests a full set of the overall solution 152 | - Opened up a new way for Nginx module development, we can use Lua to deal with Web requests 153 | - Formed an increasingly perfect ecology, the ecological covers all aspects of high-performance Web services 154 | 155 | #### *Vanilla* 156 | - Implement a Web development routine debugging, error handling, exception handling 157 | - Implement complete processing of the request and plug-in mechanism, support routing protocol, the template engine configuration 158 | - Integration, encapsulates a series of Web development commonly used tool set, class library (cookies, application firewall, etc.) 159 | - Features easy to use and extend 160 | - Support different environment (development, test, online) 161 | - Focus on the business development, not any about nginx nor OpenResty 162 | - Based on OpenResty, have all the good qualities of OpenResty 163 | - Automated, Nginx instruction set of configuration management 164 | - More reasonable use Openresty encapsulation of request processing Phase 165 | 166 | ### Community 167 | #### *QQ Groups&&WeChat public no.* 168 | - *Openresty/Vanilla Dev:205773855 (Vanilla panel discussion related topics)* 169 | - *Openresty:34782325(Discuss OpenResty and all kinds of advanced technology)* 170 | - *WeChat public no. of Vanilla Dev:Vanilla-OpenResty(Vanilla related information, document push)* 171 | 172 | 173 | [![QQ](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=673157ee0f0207ce2fb305d15999225c5aa967e88913dfd651a8cf59e18fd459) 174 | -------------------------------------------------------------------------------- /README/README-zh-V0.1.0-rc4.1.md: -------------------------------------------------------------------------------- 1 | ## Vanilla / (香草[中文文档](README-zh.md)) / OSC [Git](http://git.oschina.net/idevz/vanilla) 2 | 3 | [![https://travis-ci.org/idevz/vanilla.svg?branch=master](https://travis-ci.org/idevz/vanilla.svg?branch=master)](https://travis-ci.org/idevz/vanilla) 4 | [![Join the chat at https://gitter.im/idevz/vanilla](https://badges.gitter.im/idevz/vanilla.svg)](https://gitter.im/idevz/vanilla?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 5 | [![Issue Stats](http://issuestats.com/github/idevz/vanilla/badge/pr)](http://issuestats.com/github/idevz/vanilla) 6 | [![Issue Stats](http://issuestats.com/github/idevz/vanilla/badge/issue)](http://issuestats.com/github/idevz/vanilla) 7 | 8 | *香草/Vanilla是一个基于Openresty实现的高性能Web应用开发框架.* 9 | 10 | ![Vanilla](vanilla-pub.png) 11 | 12 | ### *邮件列表* 13 | - vanilla-en 14 | - vanilla-devel 15 | - vanilla中文邮件列表 16 | 17 | ### *安装* 18 | *目前Vanilla支持两种安装方式* 19 | 20 | - Make(推荐使用此种) 21 | - Luarocks 22 | 23 | #### *```make install```安装须知* 24 | Vanilla 支持的选项都提供了默认值,如果你的环境与默认值不一样,请configure时指定成你自己的。 25 | 26 | 特别注意选项```--openresty-path```,默认为```/usr/local/openresty```,请确保设置正确。 27 | 28 | 可以在源码目录下执行```configure --help```来查看安装选项的使用方法。 29 | 30 | 下面是一个简单的安装示例: 31 | ``` 32 | ./configure --prefix=/usr/local/vanilla --openresty-path=/usr/local/openresty 33 | 34 | make install (如果没有C模块【目前支持lua-filesystem】,则不需要make,直接make install) 35 | ``` 36 | #### *```luarocks install```安装须知* 37 | *可以使用luarocks安装vanilla,但是下面三点请注意* 38 | 1. Luarocks应该基于lua5.1.x的版本安装,因为其他版本Lua和Luajit的ABI存在兼容性问题。 39 | 2. Luarocks安装的Vanilla在nginx.conf文件的NGX_PATH变量不可用。 40 | 3. 请确保nginx命令可以直接运行(nginx命令在你的环境变量中) 41 | 42 | ### Vanilla 使用 43 | #### *Vanilla命令* 44 | *Vanilla 目前提供了两个命令 ```vanilla```,和 ```vanilla-console```* 45 | - ```vanilla```用来初始化应用骨架,停启服务(添加--trace参数可以看到执行的命令) 46 | - ```vanilla-console``` 是一个交互式命令行,主要提供一种方便学习Lua入门的工具,可以使用一些vanilla开发环境下的包,比如table输出的lprint_r方法。 47 | 48 | 命令行执行 ```vanilla```就能清晰看到 ```vanilla```命令提供的选项。 49 | 50 | ~~~ 51 | vanilla 52 | Vanilla v0.1.0-rc3, A MVC web framework for Lua powered by OpenResty. 53 | 54 | Usage: vanilla COMMAND [ARGS] [OPTIONS] 55 | 56 | 目前可用Vanilla命令选项如下: 57 | new [name] 创建一个名字为name的新应用 58 | start 启动Vanilla应用 59 | stop 停止Vanilla应用 60 | restart 先停止再启动Vanilla应用 61 | reload 重新加载Vanilla应用中的nginx.conf文件 62 | 63 | Options: 64 | --trace 显式显示日志 65 | ~~~ 66 | 67 | #### *创建应用* 68 | ``` 69 | vanilla new app_name 70 | cd app_name 71 | vanilla start [--trace] -- 默认运行在development环境 72 | 73 | ## 在linux的bash环境下: 74 | VA_ENV=production vanilla start [--trace] -- 运行在生产环境 75 | ## 在BSD等tcsh环境下: 76 | setenv VA_ENV production;vanilla start [--trace] -- 运行在生产环境 77 | ``` 78 | #### *代码目录结构* 79 | ``` 80 |  /Users/zj-git/app_name/ tree ./ 81 | ./ 82 | ├── application(应用代码主体目录) 83 | │   ├── bootstrap.lua(应用初始化 / 可选<以下未标可选为必选>) 84 | │   ├── controllers(应用业务代码主体目录) 85 | │   │   ├── error.lua(应用业务错误处理,处理本路径下相应业务报错) 86 | │   │   └── index.lua(hello world示例) 87 | │   ├── library(应用本地类包) 88 | │   ├── models(应用数据处理类) 89 | │   │   ├── dao(数据层业务处理) 90 | │   │   │   └── table.lua 91 | │   │   └── service(服务化业务处理,对DAO的再次封装) 92 | │   │   └── user.lua 93 | │   ├── nginx(*Openresty所封装Nginx请求处理各Phase) 94 | │   │   └── init.lua(*init_by_lua示例) 95 | │   ├── plugins(插件目录) 96 | │   └── views(视图层,与controllers一一对应) 97 | │   ├── error(错误模板) 98 | │   │   └── error.html 99 | │   └── index(index controller模板) 100 | │   └── index.html 101 | ├── config(应用配置目录) 102 | │   ├── application.lua(应用基础配置 / 路由器、初始化等设置) 103 | │   ├── errors.lua(应用错误信息配置) 104 | │   ├── nginx.conf(nginx配置文件模板) 105 | │   ├── nginx.lua(服务各种运行环境配置 / 是否开启lua_code_cache等) 106 | │   ├── waf-regs(应用防火墙规则配置目录) 107 | │   │   ├── args 108 | │   │   ├── cookie 109 | │   │   ├── post 110 | │   │   ├── url 111 | │   │   ├── user-agent 112 | │   │   └── whiteurl 113 | │   └── waf.lua(服务防火墙配置) 114 | ├── logs(日志目录) 115 | │   └── hack(攻击日志目录 / 保持可写权限) 116 | ├── pub(应用Nginx配置根路径) 117 | └── index.lua(应用请求入口) 118 | ``` 119 | #### *业务代码示例 IndexController* 120 | ``` 121 | local IndexController = {} 122 | 123 | function IndexController:index() 124 | local view = self:getView() 125 | local p = {} 126 | p['vanilla'] = 'Welcome To Vanilla...' 127 | p['zhoujing'] = 'Power by Openresty' 128 | view:assign(p) 129 | return view:display() 130 | end 131 | 132 | return IndexController 133 | ``` 134 | #### *模板示例 views/index/index.html* 135 | ``` 136 | 137 | 138 | 139 | 140 |

{{vanilla}}

{{zhoujing}}
141 | 142 | 143 | ``` 144 | 145 | ### 为什么需要Vanilla 146 | 回答这个问题,我们只需要看清楚Openresty和Vanilla各自做了什么即可。 147 | #### *Openresty* 148 | 149 | - 提供了处理HTTP请求的全套整体解决方案 150 | - 给Nginx模块开发开辟了一条全新的道路,我们可以使用Lua来处理Web请求 151 | - 形成了一个日趋完善的生态,这个生态涵盖了高性能Web服务方方面面 152 | 153 | #### *Vanilla* 154 | - 使复杂的Nginx配置对Web业务开发者更透明化 155 | - 开发者不再需要了解Openresty的实现细节,而更关注业务本身 156 | - 实现了Web开发常规的调试,错误处理,异常捕获 157 | - 实现了请求的完整处理流程和插件机制,支持路由协议、模板引擎的配置化 158 | - 整合、封装了一系列Web开发常用的工具集、类库(cookie、应用防火墙等) 159 | - 实现了自动化、配置化的Nginx指令集管理 160 | - 更合理的利用Openresty封装的8个处理请求Phase 161 | - 支持不同运行环境(开发、测试、上线)服务的自动化配置和运行管理 162 | - 功能使用方便易于扩展 163 | - 基于Openresty开发,具备Openresty一切优良特性 164 | 165 | ### 社区组织 166 | #### *QQ群&&微信公众号* 167 | - *Openresty/Vanilla开发QQ群:205773855(专题讨论Vanilla相关话题)* 168 | - *Openresty 技术交流QQ群:34782325(讨论OpenResty和各种高级技术)* 169 | - *Vanilla开发微信公众号:Vanilla-OpenResty(Vanilla相关资讯、文档推送)* 170 | 171 | 172 | [![QQ](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=673157ee0f0207ce2fb305d15999225c5aa967e88913dfd651a8cf59e18fd459) 173 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | #ADD 2 | #UPDATE 3 | * Lemplate 4 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use 5.006; 4 | use strict; 5 | use warnings; 6 | 7 | use File::Spec; 8 | use Data::Dumper; 9 | 10 | sub shell ($@); 11 | sub env ($$); 12 | sub cd ($); 13 | sub auto_complete ($); 14 | sub usage ($); 15 | sub trim ($); 16 | 17 | our $vanilla_version = '0.1.0.rc7'; 18 | our $vanilla_version_dir_str = '0_1_0_rc7'; 19 | 20 | my (@make_cmds, @make_install_cmds); 21 | 22 | my $root_dir = `pwd`; 23 | chomp $root_dir; 24 | 25 | my $OS = $^O; 26 | 27 | if (-f 'Makefile') { 28 | unlink 'Makefile' or die "ERROR: failed to remove existing Makefile: $!\n"; 29 | } 30 | 31 | for my $opt (@ARGV) { 32 | if ($opt =~ /^--platform=(.*)/) { 33 | $OS = $1; 34 | undef $opt; 35 | } 36 | } 37 | 38 | my ($platform, $on_solaris); 39 | 40 | if ($OS =~ /solaris|sunos/i) { 41 | $platform = 'solaris'; 42 | $on_solaris = $platform; 43 | 44 | } elsif ($OS eq 'linux') { 45 | $platform = $OS; 46 | 47 | } elsif ($OS eq 'MSWin32') { 48 | die "MS Windows not supported. Abort.\n"; 49 | 50 | } elsif ($OS =~ /^(?:MacOS|darwin|rhapsody)$/) { 51 | $platform = 'macosx'; 52 | 53 | } elsif ($OS eq 'freebsd') { 54 | $platform = $OS; 55 | 56 | } elsif ($OS =~ /^(?:openbsd|netbsd|dragonfly)$/) { 57 | $platform = 'bsd'; 58 | 59 | } else { 60 | $platform = 'posix'; 61 | } 62 | 63 | my $prefix = '/usr/local/vanilla'; 64 | my $openresty_prefix = '/usr/local/openresty'; 65 | my $vanilla_bin_path = '/usr/local/bin'; 66 | my %resty_opts; 67 | my $cc; 68 | my $vanilla_root = $prefix; 69 | 70 | for my $opt (@ARGV) { 71 | next unless defined $opt; 72 | 73 | if ($opt =~ /^--prefix=(.*)/) { 74 | $vanilla_root = $1; 75 | 76 | } elsif ($opt =~ /^--vanilla-bin-path=(.*)/) { 77 | $vanilla_bin_path = $1; 78 | 79 | } elsif ($opt =~ /^--openresty-path=(.*)/) { 80 | $openresty_prefix = $1; 81 | 82 | } 83 | # elsif ($opt eq '--with-lua-filesystem') { 84 | # $resty_opts{lua_filesystem} = 1; 85 | 86 | # } 87 | elsif ($opt =~ /^--with-openresty-luajit-include-path=(.*)/) { 88 | $resty_opts{or_jit_inc_path} = $1; 89 | 90 | } elsif ($opt =~ /^--with-luajit-or-lua-bin=(.*)/) { 91 | $resty_opts{luajit_or_lua_bin} = $1; 92 | 93 | } 94 | # elsif ($opt eq '--without-lua-resty-cookie') { 95 | # $resty_opts{no_lua_resty_cookie} = 1; 96 | 97 | # } elsif ($opt eq '--without-lua-resty-template') { 98 | # $resty_opts{no_lua_resty_template} = 1; 99 | 100 | # } elsif ($opt eq '--without-lua-resty-http') { 101 | # $resty_opts{no_lua_resty_http} = 1; 102 | 103 | # } elsif ($opt eq '--without-lua-resty-logger-socket') { 104 | # $resty_opts{no_lua_resty_logger_socket} = 1; 105 | 106 | # } elsif ($opt eq '--without-lua-resty-session') { 107 | # $resty_opts{no_lua_resty_session} = 1; 108 | 109 | # } elsif ($opt eq '--without-lua-resty-shcache') { 110 | # $resty_opts{no_lua_resty_shcache} = 1; 111 | 112 | # } 113 | elsif ($opt eq '--help') { 114 | usage 0; 115 | 116 | } else { 117 | die "Invalid option $opt\n"; 118 | } 119 | } 120 | 121 | $prefix = $vanilla_root . '/' . $vanilla_version_dir_str; 122 | 123 | my $luajit_or_lua_bin = glob "$openresty_prefix/luajit/bin/luajit*"; 124 | my $ngx_path = "$openresty_prefix/nginx"; 125 | 126 | if ($resty_opts{luajit_or_lua_bin}) { 127 | $luajit_or_lua_bin = $resty_opts{luajit_or_lua_bin}; 128 | } 129 | 130 | if (!$luajit_or_lua_bin) { 131 | die "Didn't set luajit or lua bin. Or did't exists:" ,"$openresty_prefix/luajit/bin/luajit*"; 132 | } 133 | 134 | build_resty_opts(\%resty_opts); 135 | 136 | my $vanilla_extra_opts = " DESTDIR=\$(DESTDIR) VANILLA_LIB_DIR=$prefix" 137 | # ." INSTALL=$root_dir/build/install" 138 | ." INSTALL=$root_dir/vanilla/install" 139 | ." VANILLA_BIN_PATH=$vanilla_bin_path" 140 | ." VANILLA_ROOT=$vanilla_root" 141 | ." VANILLA_VERSION=$vanilla_version"; 142 | 143 | push @make_install_cmds, "cd $root_dir/build/vanilla && " . 144 | "\$(MAKE) install$vanilla_extra_opts"; 145 | 146 | gen_vanilla_bins(); 147 | 148 | cd '..'; # to the root 149 | #die "pwd: " .. `pwd`; 150 | # env LIBPQ_LIB => $pg_lib; 151 | 152 | gen_makefile(); 153 | 154 | sub env ($$) { 155 | my ($name, $val) = @_; 156 | print "export $name='$val'\n"; 157 | $ENV{$name} = $val; 158 | } 159 | 160 | sub shell ($@) { 161 | my ($cmd, $dry_run) = @_; 162 | 163 | print "$cmd\n"; 164 | 165 | unless ($dry_run) { 166 | system($cmd) == 0 or 167 | die "ERROR: failed to run command: ", trim($cmd), "\n"; 168 | } 169 | } 170 | 171 | sub trim ($) { 172 | my $cmd = shift; 173 | $cmd =~ s/\n.*/.../s; 174 | $cmd; 175 | } 176 | 177 | sub auto_complete ($) { 178 | my $name = shift; 179 | my @dirs = glob "$name-[0-9]*" or 180 | die "No source directory found for $name\n"; 181 | 182 | if (@dirs > 1) { 183 | die "More than one hits for $name: @dirs\n"; 184 | } 185 | 186 | return $dirs[0]; 187 | } 188 | 189 | sub cd ($) { 190 | my $dir = shift; 191 | print("cd $dir\n"); 192 | chdir $dir or die "failed to cd $dir: $!\n"; 193 | } 194 | 195 | sub build_resty_opts { 196 | my $opts = shift; 197 | 198 | my $make; 199 | 200 | if (-d 'build') { 201 | system("rm -rf build") == 0 or 202 | die "failed to remove directory build/.\n"; 203 | } 204 | 205 | if (-e 'build') { 206 | die "file or directory \"build\" already exists. please remove it first.\n"; 207 | } 208 | shell "mkdir -p build/vanilla"; 209 | shell "cp -rp vanilla/* build/vanilla"; 210 | # shell "cp -rp resty/* build"; 211 | # shell "cp -rp lualib/* build"; 212 | 213 | cd 'build'; 214 | 215 | # my $lualib_prefix = "$prefix/lualib"; 216 | 217 | # if ($opts->{lua_filesystem}) { 218 | # if (!$opts->{or_jit_inc_path}) { 219 | # die "luafilesystem need add --with-openresty-luajit-include-path option."; 220 | # } 221 | # my $dir = auto_complete 'luafilesystem'; 222 | # if (!defined $dir) { 223 | # die "No luafilesystem found"; 224 | # } 225 | 226 | # my $lua_inc = $opts->{or_jit_inc_path}; 227 | 228 | # my $lib_option; 229 | # if ($platform eq 'macosx') { 230 | # $lib_option = "-bundle -undefined dynamic_lookup"; 231 | # } else { 232 | # $lib_option = "-shared"; 233 | # } 234 | 235 | # my $extra_opts = " DESTDIR=\$(DESTDIR) LUA_INC=$lua_inc LUA_LIBDIR=$lualib_prefix " . 236 | # "LUA_CMODULE_DIR=$lualib_prefix LUA_MODULE_DIR=$lualib_prefix" . 237 | # " LIB_OPTION='$lib_option'"; 238 | 239 | # if (defined $cc) { 240 | # $extra_opts .= " CC='$cc'"; 241 | # } else { 242 | # $extra_opts .= " CC=cc"; 243 | # } 244 | 245 | # push @make_cmds, "cd $root_dir/build/$dir && ". 246 | # "\$(MAKE)$extra_opts"; 247 | 248 | # push @make_install_cmds, "cd $root_dir/build/$dir && " . 249 | # "\$(MAKE) install$extra_opts"; 250 | # } 251 | 252 | # for my $key (qw(cookie http logger_socket session shcache template)) 253 | # { 254 | # unless ($opts->{"no_lua_resty_$key"}) { 255 | # (my $key2 = $key) =~ s/_/-/g; 256 | # my $name = "lua-resty-$key2"; 257 | # my $dir = auto_complete $name; 258 | # if (!defined $dir) { 259 | # die "No $name found"; 260 | # } 261 | 262 | # my $extra_opts = " DESTDIR=\$(DESTDIR) LUA_LIB_DIR=$prefix/vanilla" 263 | # ." INSTALL=$root_dir/build/install"; 264 | 265 | # push @make_install_cmds, "cd $root_dir/build/$dir && " . 266 | # "\$(MAKE) install$extra_opts"; 267 | # } 268 | # } 269 | } 270 | 271 | sub usage ($) { 272 | my $retval = shift; 273 | my $msg = <<'_EOC_'; 274 | --help this message 275 | 276 | --prefix=PATH set the installation prefix (default to /usr/local/vanilla) 277 | --vanilla-bin-path=PATH set vanilla bin path (default to /usr/local/bin) 278 | --platform= set platform(darwin, linux...) 279 | 280 | --openresty-path=PATH set openresty install path (default to /usr/local/openresty) 281 | --with-openresty-luajit-include-path=PATH 282 | set openresty luajit include path for install C moudle 283 | (like: /usr/local/openresty/luajit/include/luajit-2.1) 284 | --with-luajit-or-lua-bin=BIN set openresty luajit or standard lua bin for run vanilla vanilla-console 285 | (default to $openresty_path/luajit/bin/luajit*) 286 | 287 | _EOC_ 288 | 289 | # --without-lua-resty-cookie disable the lua-resty-cookie library 290 | # --without-lua-resty-template disable the lua-resty-template library 291 | # --without-lua-resty-http disable the lua-resty-http library 292 | # --without-lua-resty-logger-socket disable the lua-resty-logger-socket library 293 | # --without-lua-resty-session disable the lua-resty-session library 294 | # --without-lua-resty-shcache disable the lua-resty-shcache library 295 | 296 | # --with-lua-filesystem enable and build lua-filesystem 297 | # (must need option --with-openresty-luajit-include-path) 298 | 299 | warn $msg; 300 | exit $retval; 301 | } 302 | 303 | sub gen_vanilla_bins { 304 | for my $bin_name (qw(vanilla v-console)) { 305 | my $rs_bin_name = "$bin_name-$vanilla_version"; 306 | 307 | open my $out, ">vanilla/$rs_bin_name" or 308 | die "Cannot open $rs_bin_name for writing: $!\n"; 309 | 310 | my $cmd_str = <<"_EOC_"; 311 | #!/bin/sh 312 | exec '$luajit_or_lua_bin' -e 'VANILLA_ROOT="$vanilla_root"; VANILLA_VERSION_DIR_STR="$vanilla_version_dir_str"; VANILLA_VERSION="$vanilla_version"; VANILLA_NGX_PATH="$ngx_path"; VANILLA_JIT_BIN="$luajit_or_lua_bin"; package.path="$prefix/?.lua;$prefix/?/init.lua;/?.lua;/?/init.lua;"; package.cpath="$prefix/?.so"' '$prefix/bin/$bin_name' "\$@" 313 | _EOC_ 314 | 315 | print $out $cmd_str; 316 | close $out; 317 | chmod 0755, "vanilla/$rs_bin_name"; 318 | } 319 | shell "cp -p vanilla/bin/lemplate ./vanilla/lemplate-$vanilla_version"; 320 | } 321 | 322 | sub gen_makefile { 323 | open my $out, ">Makefile" or 324 | die "Cannot open Makefile for writing: $!\n"; 325 | 326 | print $out ".PHONY: all install clean\n\n"; 327 | 328 | print $out "all:\n\t" . join("\n\t", @make_cmds) . "\n\n"; 329 | 330 | print $out "install: all\n\t" . join("\n\t", @make_install_cmds) . "\n\n"; 331 | 332 | print $out "clean:\n\trm -rf build\n"; 333 | 334 | close $out; 335 | } 336 | 337 | # check if we can run some command 338 | sub can_run { 339 | my ($cmd) = @_; 340 | 341 | #warn "can run: @_\n"; 342 | my $_cmd = $cmd; 343 | return $_cmd if -x $_cmd; 344 | 345 | return undef if $_cmd =~ m{[\\/]}; 346 | 347 | # FIXME: this is a hack; MSWin32 is not supported anyway 348 | my $path_sep = ':'; 349 | 350 | for my $dir ((split /$path_sep/, $ENV{PATH}), '.') { 351 | next if $dir eq ''; 352 | my $abs = File::Spec->catfile($dir, $_[0]); 353 | return $abs if -x $abs; 354 | } 355 | 356 | return undef; 357 | } -------------------------------------------------------------------------------- /dist.ini: -------------------------------------------------------------------------------- 1 | name = vanilla 2 | abstract = An OpenResty Lua MVC Web Framework 3 | author = idevz 4 | version = 0.1.0.rc7 5 | is_original = yes 6 | license = mit 7 | lib_dir = vanilla 8 | doc_dir = README 9 | repo_link = https://github.com/idevz/vanilla 10 | main_module = vanilla/base/opm.lua 11 | requires = luajit -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos:latest 2 | MAINTAINER zhoujing_k49@163.com zhoujing00k@gmail.com https://hub.docker.com/u/zhoujing/ 3 | WORKDIR /tmp 4 | RUN yum localinstall http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm -y && yum -y install supervisor && \ 5 | yum install -y automake autoconf libtool make gcc wget lua-devel git unzip readline-devel pcre-devel openssl-devel && \ 6 | wget https://github.com/keplerproject/luarocks/archive/v2.2.2.tar.gz && wget https://openresty.org/download/ngx_openresty-1.9.3.1.tar.gz && \ 7 | tar zxf v2.2.2.tar.gz && cd luarocks-2.2.2 && ./configure && make build && make install && cd .. && \ 8 | luarocks install vanilla && \ 9 | tar zxf ngx_openresty-1.9.3.1.tar.gz && cd ngx_openresty-1.9.3.1 && ./configure && gmake && gmake install && cd .. && \ 10 | ln -sf /usr/local/openresty/nginx/sbin/nginx /usr/bin/nginx 11 | ADD ./supervisord.conf /etc/ 12 | EXPOSE 9110 13 | CMD ["/usr/bin/supervisord"] 14 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | ## Build 2 | 3 | ```` 4 | wget https://raw.githubusercontent.com/idevz/vanilla/master/docker/Dockerfile \ 5 | https://raw.githubusercontent.com/idevz/vanilla/master/docker/supervisord.conf && \ 6 | docker build -t idevz/vanilla . 7 | ```` 8 | 9 | ## Create your app 10 | 11 | ``` 12 | docker run -v "$PWD":/tmp --rm idevz/vanilla vanilla new $your_app 13 | ``` 14 | 15 | Here `$your_app` should be the name of your app, such as 'pet_store'. 16 | 17 | ## Start the server 18 | 19 | ```` 20 | docker run -v "$your_app_dir":/tmp -d -p 9110:9110 idevz/vanilla 21 | ```` 22 | 23 | Here `$your_app_dir` should be where your app locates on, such as '/home/vanilla/pet_store'. 24 | -------------------------------------------------------------------------------- /docker/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log) 3 | logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB) 4 | logfile_backups=10 ; (num of main logfile rotation backups;default 10) 5 | loglevel=info ; (log level;default info; others: debug,warn,trace) 6 | pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) 7 | nodaemon=true ; (start in foreground if true;default false) 8 | ;nodaemon=false ; (start in foreground if true;default false) 9 | minfds=1024 ; (min. avail startup file descriptors;default 1024) 10 | minprocs=200 ; (min. avail process descriptors;default 200) 11 | ;umask=022 ; (process file creation umask;default 022) 12 | ;user=chrism ; (default is current user, required if root) 13 | ;identifier=supervisor ; (supervisord identifier, default is 'supervisor') 14 | ;directory=/tmp ; (default is not to cd during start) 15 | ;nocleanup=true ; (don't clean up tempfiles at start;default false) 16 | ;childlogdir=/tmp ; ('AUTO' child log dir, default $TEMP) 17 | ;environment=KEY=value ; (key value pairs to add to environment) 18 | ;strip_ansi=false ; (strip ansi escape codes in logs; def. false) 19 | 20 | [program:vanilla] 21 | command=vanilla start 22 | 23 | [include] 24 | files = supervisord.d/*.ini 25 | -------------------------------------------------------------------------------- /rockspecs/vanilla-0.1.0.rc4-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "vanilla" 2 | version = "0.1.0.rc4-1" 3 | 4 | source ={ 5 | url ="git://github.com/idevz/vanilla.git" 6 | } 7 | 8 | description ={ 9 | summary ="A Lightweight Openresty Web Framework", 10 | homepage ="http://idevz.github.io/vanilla", 11 | maintainer ="zhoujing", 12 | license ="MIT", 13 | detailed = [[ 14 | ##install 15 | ``` 16 | yum install lua-devel luarocks 17 | luarocks install vanilla 18 | ```]] 19 | } 20 | 21 | dependencies ={ 22 | "lua=5.1", 23 | "luafilesystem=1.6.2-2", 24 | "lua-resty-template=1.5-1", 25 | "lua-resty-cookie=0.1.0-1", 26 | "lua-resty-session=2.2-1", 27 | "lua-resty-http=0.06-0" 28 | } 29 | 30 | build = { 31 | type = "builtin", 32 | modules = { 33 | ["vanilla.sys.application"] = "vanilla/sys/application.lua", 34 | ["vanilla.sys.config"] = "vanilla/sys/config.lua", 35 | ["vanilla.sys.console"] = "vanilla/sys/console.lua", 36 | ["vanilla.sys.nginx.config"] = "vanilla/sys/nginx/config.lua", 37 | ["vanilla.sys.nginx.directive"] = "vanilla/sys/nginx/directive.lua", 38 | ["vanilla.sys.nginx.handle"] = "vanilla/sys/nginx/handle.lua", 39 | ["vanilla.sys.vanilla"] = "vanilla/sys/vanilla.lua", 40 | ["vanilla.sys.waf.acc"] = "vanilla/sys/waf/acc.lua", 41 | ["vanilla.sys.waf.config"] = "vanilla/sys/waf/config.lua", 42 | ["vanilla.v.application"] = "vanilla/v/application.lua", 43 | ["vanilla.v.bootstrap"] = "vanilla/v/bootstrap.lua", 44 | ["vanilla.v.controller"] = "vanilla/v/controller.lua", 45 | ["vanilla.v.dispatcher"] = "vanilla/v/dispatcher.lua", 46 | ["vanilla.v.error"] = "vanilla/v/error.lua", 47 | ["vanilla.v.libs.ansicolors"] = "vanilla/v/libs/ansicolors.lua", 48 | ["vanilla.v.libs.cookie"] = "vanilla/v/libs/cookie.lua", 49 | ["vanilla.v.libs.http"] = "vanilla/v/libs/http.lua", 50 | ["vanilla.v.libs.logs"] = "vanilla/v/libs/logs.lua", 51 | ["vanilla.v.libs.session"] = "vanilla/v/libs/session.lua", 52 | ["vanilla.v.libs.shcache"] = "vanilla/v/libs/shcache.lua", 53 | ["vanilla.v.libs.utils"] = "vanilla/v/libs/utils.lua", 54 | ["vanilla.v.plugin"] = "vanilla/v/plugin.lua", 55 | ["vanilla.v.registry"] = "vanilla/v/registry.lua", 56 | ["vanilla.v.request"] = "vanilla/v/request.lua", 57 | ["vanilla.v.response"] = "vanilla/v/response.lua", 58 | ["vanilla.v.router"] = "vanilla/v/router.lua", 59 | ["vanilla.v.routes.simple"] = "vanilla/v/routes/simple.lua", 60 | ["vanilla.v.view"] = "vanilla/v/view.lua", 61 | ["vanilla.v.views.rtpl"] = "vanilla/v/views/rtpl.lua" 62 | }, 63 | install ={ 64 | bin ={ 65 | "vanilla/bin/vanilla", 66 | "vanilla/bin/vanilla-console" 67 | } 68 | }, 69 | } -------------------------------------------------------------------------------- /rockspecs/vanilla-0.1.0.rc5-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "vanilla" 2 | version = "0.1.0.rc5-1" 3 | 4 | source ={ 5 | url ="git://github.com/idevz/vanilla.git" 6 | } 7 | 8 | description ={ 9 | summary ="An OpenResty Lua MVC Web Framework", 10 | homepage ="http://idevz.github.io/vanilla", 11 | maintainer ="zhoujing", 12 | license ="MIT", 13 | detailed = [[ 14 | ##install 15 | ``` 16 | yum install lua-devel luarocks 17 | luarocks install vanilla 18 | ```]] 19 | } 20 | 21 | dependencies ={ 22 | "lua=5.1", 23 | "luafilesystem=1.6.2-2", 24 | "lua-resty-template=1.5-1", 25 | "lua-resty-cookie=0.1.0-1", 26 | "lua-resty-session=2.2-1", 27 | "lua-resty-http=0.06-0" 28 | } 29 | 30 | build = { 31 | type = "builtin", 32 | modules = { 33 | ["spec.helper"] = "spec/helper.lua", 34 | ["spec.v.dispatcher_spec"] = "spec/v/dispatcher_spec.lua", 35 | ["vanilla.resty.template"] = "vanilla/resty/template.lua", 36 | ["vanilla.resty.template.html"] = "vanilla/resty/template/html.lua", 37 | ["vanilla.resty.template.microbenchmark"] = "vanilla/resty/template/microbenchmark.lua", 38 | ["vanilla.spec"] = "vanilla/spec/init.lua", 39 | ["vanilla.spec.runner"] = "vanilla/spec/runner.lua", 40 | ["vanilla.spec.runners.integration"] = "vanilla/spec/runners/integration.lua", 41 | ["vanilla.spec.runners.response"] = "vanilla/spec/runners/response.lua", 42 | ["vanilla.sys.application"] = "vanilla/sys/application.lua", 43 | ["vanilla.sys.config"] = "vanilla/sys/config.lua", 44 | ["vanilla.sys.console"] = "vanilla/sys/console.lua", 45 | ["vanilla.sys.nginx.config"] = "vanilla/sys/nginx/config.lua", 46 | ["vanilla.sys.nginx.directive"] = "vanilla/sys/nginx/directive.lua", 47 | ["vanilla.sys.nginx.handle"] = "vanilla/sys/nginx/handle.lua", 48 | ["vanilla.sys.vanilla"] = "vanilla/sys/vanilla.lua", 49 | ["vanilla.sys.waf.acc"] = "vanilla/sys/waf/acc.lua", 50 | ["vanilla.sys.waf.config"] = "vanilla/sys/waf/config.lua", 51 | ["vanilla.v.application"] = "vanilla/v/application.lua", 52 | ["vanilla.v.bootstrap"] = "vanilla/v/bootstrap.lua", 53 | ["vanilla.v.controller"] = "vanilla/v/controller.lua", 54 | ["vanilla.v.dispatcher"] = "vanilla/v/dispatcher.lua", 55 | ["vanilla.v.error"] = "vanilla/v/error.lua", 56 | ["vanilla.v.libs.ansicolors"] = "vanilla/v/libs/ansicolors.lua", 57 | ["vanilla.v.libs.cookie"] = "vanilla/v/libs/cookie.lua", 58 | ["vanilla.v.libs.http"] = "vanilla/v/libs/http.lua", 59 | ["vanilla.v.libs.logs"] = "vanilla/v/libs/logs.lua", 60 | ["vanilla.v.libs.reqargs"] = "vanilla/v/libs/reqargs.lua", 61 | ["vanilla.v.libs.session"] = "vanilla/v/libs/session.lua", 62 | ["vanilla.v.libs.shcache"] = "vanilla/v/libs/shcache.lua", 63 | ["vanilla.v.libs.utils"] = "vanilla/v/libs/utils.lua", 64 | ["vanilla.v.plugin"] = "vanilla/v/plugin.lua", 65 | ["vanilla.v.registry"] = "vanilla/v/registry.lua", 66 | ["vanilla.v.request"] = "vanilla/v/request.lua", 67 | ["vanilla.v.response"] = "vanilla/v/response.lua", 68 | ["vanilla.v.router"] = "vanilla/v/router.lua", 69 | ["vanilla.v.routes.restful"] = "vanilla/v/routes/restful.lua", 70 | ["vanilla.v.routes.simple"] = "vanilla/v/routes/simple.lua", 71 | ["vanilla.v.view"] = "vanilla/v/view.lua", 72 | ["vanilla.v.views.rtpl"] = "vanilla/v/views/rtpl.lua" 73 | }, 74 | install ={ 75 | bin ={ 76 | "vanilla/bin/vanilla", 77 | "vanilla/bin/v-console" 78 | } 79 | }, 80 | } 81 | -------------------------------------------------------------------------------- /rockspecs/vanilla-0.1.0.rc6-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "vanilla" 2 | version = "0.1.0.rc6-1" 3 | 4 | source ={ 5 | url ="git://github.com/idevz/vanilla.git" 6 | } 7 | 8 | description ={ 9 | summary ="An OpenResty Lua MVC Web Framework", 10 | homepage ="http://idevz.github.io/vanilla", 11 | maintainer ="zhoujing", 12 | license ="MIT", 13 | detailed = [[ 14 | ##install 15 | ``` 16 | yum install lua-devel luarocks 17 | luarocks install vanilla 18 | ```]] 19 | } 20 | 21 | dependencies ={ 22 | "lua=5.1", 23 | "luafilesystem=1.6.2-2", 24 | "lua-resty-template=1.5-1", 25 | "lua-resty-cookie=0.1.0-1", 26 | "lua-resty-session=2.2-1", 27 | "lua-resty-http=0.06-0" 28 | } 29 | 30 | build = { 31 | type = "builtin", 32 | modules = { 33 | ["spec.helper"] = "spec/helper.lua", 34 | ["spec.v.dispatcher_spec"] = "spec/v/dispatcher_spec.lua", 35 | ["vanilla.base"] = "vanilla/base/init.lua", 36 | ["vanilla.base.registry"] = "vanilla/base/registry.lua", 37 | ["vanilla.base.resty.cookie"] = "vanilla/base/resty/cookie.lua", 38 | ["vanilla.base.resty.http"] = "vanilla/base/resty/http.lua", 39 | ["vanilla.base.resty.http_headers"] = "vanilla/base/resty/http_headers.lua", 40 | ["vanilla.base.resty.template"] = "vanilla/base/resty/template.lua", 41 | ["vanilla.base.resty.template.html"] = "vanilla/base/resty/template/html.lua", 42 | ["vanilla.base.resty.template.microbenchmark"] = "vanilla/base/resty/template/microbenchmark.lua", 43 | ["vanilla.spec"] = "vanilla/spec/init.lua", 44 | ["vanilla.spec.runner"] = "vanilla/spec/runner.lua", 45 | ["vanilla.spec.runners.integration"] = "vanilla/spec/runners/integration.lua", 46 | ["vanilla.spec.runners.response"] = "vanilla/spec/runners/response.lua", 47 | ["vanilla.sys.application"] = "vanilla/sys/application.lua", 48 | ["vanilla.sys.config"] = "vanilla/sys/config.lua", 49 | ["vanilla.sys.console"] = "vanilla/sys/console.lua", 50 | ["vanilla.sys.nginx.config"] = "vanilla/sys/nginx/config.lua", 51 | ["vanilla.sys.nginx.directive"] = "vanilla/sys/nginx/directive.lua", 52 | ["vanilla.sys.nginx.handle"] = "vanilla/sys/nginx/handle.lua", 53 | ["vanilla.sys.vanilla"] = "vanilla/sys/vanilla.lua", 54 | ["vanilla.sys.waf.acc"] = "vanilla/sys/waf/acc.lua", 55 | ["vanilla.sys.waf.config"] = "vanilla/sys/waf/config.lua", 56 | ["vanilla.v.application"] = "vanilla/v/application.lua", 57 | ["vanilla.v.bootstrap"] = "vanilla/v/bootstrap.lua", 58 | ["vanilla.v.cache"] = "vanilla/v/cache.lua", 59 | ["vanilla.v.cache.base"] = "vanilla/v/cache/base.lua", 60 | ["vanilla.v.cache.lru"] = "vanilla/v/cache/lru.lua", 61 | ["vanilla.v.cache.mc"] = "vanilla/v/cache/mc.lua", 62 | ["vanilla.v.cache.redis"] = "vanilla/v/cache/redis.lua", 63 | ["vanilla.v.cache.shdict"] = "vanilla/v/cache/shdict.lua", 64 | ["vanilla.v.config.handle"] = "vanilla/v/config/handle.lua", 65 | ["vanilla.v.config.parse"] = "vanilla/v/config/parse.lua", 66 | ["vanilla.v.config.save"] = "vanilla/v/config/save.lua", 67 | ["vanilla.v.controller"] = "vanilla/v/controller.lua", 68 | ["vanilla.v.dispatcher"] = "vanilla/v/dispatcher.lua", 69 | ["vanilla.v.error"] = "vanilla/v/error.lua", 70 | ["vanilla.v.libs.ansicolors"] = "vanilla/v/libs/ansicolors.lua", 71 | ["vanilla.v.libs.cache"] = "vanilla/v/libs/cache.lua", 72 | ["vanilla.v.libs.cookie"] = "vanilla/v/libs/cookie.lua", 73 | ["vanilla.v.libs.http"] = "vanilla/v/libs/http.lua", 74 | ["vanilla.v.libs.logs"] = "vanilla/v/libs/logs.lua", 75 | ["vanilla.v.libs.reqargs"] = "vanilla/v/libs/reqargs.lua", 76 | ["vanilla.v.libs.session"] = "vanilla/v/libs/session.lua", 77 | ["vanilla.v.libs.shcache"] = "vanilla/v/libs/shcache.lua", 78 | ["vanilla.v.libs.utils"] = "vanilla/v/libs/utils.lua", 79 | ["vanilla.v.plugin"] = "vanilla/v/plugin.lua", 80 | ["vanilla.v.registry"] = "vanilla/v/registry.lua", 81 | ["vanilla.v.request"] = "vanilla/v/request.lua", 82 | ["vanilla.v.response"] = "vanilla/v/response.lua", 83 | ["vanilla.v.router"] = "vanilla/v/router.lua", 84 | ["vanilla.v.routes.restful"] = "vanilla/v/routes/restful.lua", 85 | ["vanilla.v.routes.simple"] = "vanilla/v/routes/simple.lua", 86 | ["vanilla.v.view"] = "vanilla/v/view.lua", 87 | ["vanilla.v.views.rtpl"] = "vanilla/v/views/rtpl.lua" 88 | }, 89 | install ={ 90 | bin ={ 91 | "vanilla/bin/vanilla", 92 | "vanilla/bin/v-console" 93 | } 94 | }, 95 | } 96 | -------------------------------------------------------------------------------- /setup-framework: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### BEGIN ### 4 | # Author: idevz 5 | # Since: 2016/04/09 6 | # Description: Setup Vanilla Framework 7 | ### END ### 8 | 9 | VANILLA_VERSION=0.1.0.rc7 10 | VANILLA_VERSION_DIR_STR=0_1_0_rc7 11 | VANILLA_PROJ_ROOT=/data/vanilla 12 | OPENRESTY_ROOT=/usr/local/openresty 13 | TIME_MARK=`date "+%Y_%m_%d_%H_%M_%S"` 14 | PLATFORM=`uname` 15 | ECHO_E=" -e " 16 | [ $PLATFORM = "Darwin" ] && ECHO_E="" 17 | 18 | 19 | alert() 20 | { 21 | MSG=$1 22 | echo $ECHO_E"\033[31m$MSG \033[0m\n" 23 | } 24 | 25 | install_vanilla_framework() 26 | { 27 | echo $ECHO_E"\033[45mBegin install Vanilla Frameowrk! \033[0m\n" 28 | VANILLA_PROJ_ROOT=$1 29 | VANILLA_FRAMEWORK_ROOT=$1/framework 30 | VANILLA_FRAMEWORK_V=$VANILLA_FRAMEWORK_ROOT/$VANILLA_VERSION_DIR_STR 31 | [ -n $2 ] && OPENRESTY_ROOT=$2 32 | [ ! -d $OPENRESTY_ROOT ] && alert "OPENRESTY_ROOT set ERROR, OpenResty Path "$OPENRESTY_ROOT" didn't exist, and -o to set the ture OPENRESTY_ROOT" && exit 1 33 | VANILLA_BIN=/usr/local/bin/vanilla-$VANILLA_VERSION 34 | VANILLA_CONSOLE_BIN=/usr/local/bin/v-console-$VANILLA_VERSION 35 | 36 | echo $VANILLA_FRAMEWORK_V 37 | 38 | [ -f $VANILLA_BIN ] && mv -f $VANILLA_BIN $VANILLA_BIN".old_"$TIME_MARK 39 | [ -f $VANILLA_CONSOLE_BIN ] && mv -f $VANILLA_CONSOLE_BIN $VANILLA_CONSOLE_BIN".old_"$TIME_MARK 40 | [ -d $VANILLA_FRAMEWORK_V ] && mv -f $VANILLA_FRAMEWORK_V $VANILLA_FRAMEWORK_V".old_"$TIME_MARK 41 | 42 | make clean 43 | ./configure --prefix=$VANILLA_FRAMEWORK_ROOT --openresty-path=$OPENRESTY_ROOT 44 | make install 45 | 46 | if [ $? -ne 0 ];then 47 | alert "Install Vanilla Frameowrk Fail. Pleas check your access permissions." 48 | exit 1 49 | fi 50 | echo $ECHO_E"\033[35mVanilla Frameowrk Installed $VANILLA_FRAMEWORK_ROOT \033[0m\n" 51 | } 52 | 53 | show_usage() 54 | { 55 | echo $ECHO_E"`printf %-16s "Usage: $0"`" 56 | echo $ECHO_E"`printf %-16s ` -h show this help info" 57 | echo $ECHO_E"`printf %-16s ` -v VANILLA_PROJ_ROOT, vanilla project root, will contain vanilla framework and apps" 58 | echo $ECHO_E"`printf %-16s ` -o OPENRESTY_ROOT, openresty install path(openresty root)" 59 | } 60 | 61 | while getopts v:o:h OPT; do 62 | case "$OPT" in 63 | v ) 64 | VANILLA_PROJ_ROOT=$OPTARG 65 | ;; 66 | o ) 67 | OPENRESTY_ROOT=$OPTARG 68 | ;; 69 | h ) 70 | show_usage && exit 0 71 | ;; 72 | -- ) 73 | shift break 74 | ;; 75 | ? ) 76 | alert "ERROR: unknown argument!" && show_usage && exit 1 77 | ;; 78 | esac 79 | done 80 | 81 | install_vanilla_framework $VANILLA_PROJ_ROOT $OPENRESTY_ROOT 82 | 83 | echo 84 | echo $ECHO_E"You are setup Vanilla-$VANILLA_VERSION and using:" 85 | echo $ECHO_E"`printf %-30s "\"$OPENRESTY_ROOT\""` ---- as OpenResty install path(OpenResty root)" 86 | echo $ECHO_E"`printf %-30s "\"$VANILLA_PROJ_ROOT\""` ---- as vanilla project root(will contain vanilla framework and apps)" 87 | echo 88 | 89 | exit 0 -------------------------------------------------------------------------------- /setup-vanilla-demoapp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### BEGIN ### 4 | # Author: idevz 5 | # Since: 2016/04/09 6 | # Description: Setup Vanilla DemoApp named vademo 7 | ### END ### 8 | 9 | VANILLA_VERSION=0.1.0.rc7 10 | VANILLA_VERSION_DIR_STR=0_1_0_rc7 11 | VANILLA_APP_ROOT=/data/vanilla/vademo 12 | VANILLA_APP_USER=idevz 13 | VANILLA_APP_GROUP=sina 14 | VANILLA_RUNNING_ENV='' #default '' is for production environment 15 | TIME_MARK=`date "+%Y_%m_%d_%H_%M_%S"` 16 | PLATFORM=`uname` 17 | ECHO_E=" -e " 18 | [ $PLATFORM = "Darwin" ] && ECHO_E="" 19 | 20 | 21 | alert() 22 | { 23 | MSG=$1 24 | echo $ECHO_E"\033[31m$MSG \033[0m\n" 25 | } 26 | 27 | init_vanilla_app() 28 | { 29 | VANILLA_APP_ROOT=$1 30 | echo $ECHO_E"\033[40mBegin init Vanilla App: $VANILLA_APP_ROOT \033[0m\n" 31 | [ -n $2 ] && VANILLA_APP_USER=$2 32 | [ -n $3 ] && VANILLA_APP_GROUP=$3 33 | [ -n $4 ] && APP_NAME=$4 34 | [ -n $5 ] && VANILLA_RUNNING_ENV=$5 35 | 36 | SERVICE_SH=$VANILLA_APP_ROOT/va-$APP_NAME-service 37 | VANILLA_BIN=/usr/local/bin/vanilla-$VANILLA_VERSION 38 | [ -d $VANILLA_APP_ROOT ] && mv -f $VANILLA_APP_ROOT $VANILLA_APP_ROOT".old_"$TIME_MARK 39 | [ -x $VANILLA_BIN ] && $VANILLA_BIN new $VANILLA_APP_ROOT 40 | if [[ $? -ne 0 ]];then 41 | alert $VANILLA_BIN" is not exist, You shoud install vanilla first, to see './setup-framework -h' for more info." 42 | exit 1 43 | fi 44 | sed "s/#user zhoujing staff/user $VANILLA_APP_USER $VANILLA_APP_GROUP/" $VANILLA_APP_ROOT/nginx_conf/va-nginx-development.conf>$VANILLA_APP_ROOT/nginx_conf/va-nginx-development.conf.tmp 45 | sed "s/#user zhoujing staff/user $VANILLA_APP_USER $VANILLA_APP_GROUP/" $VANILLA_APP_ROOT/nginx_conf/va-nginx.conf>$VANILLA_APP_ROOT/nginx_conf/va-nginx.conf.tmp 46 | mv -f $VANILLA_APP_ROOT/nginx_conf/va-nginx-development.conf.tmp $VANILLA_APP_ROOT/nginx_conf/va-nginx-development.conf 47 | mv -f $VANILLA_APP_ROOT/nginx_conf/va-nginx.conf.tmp $VANILLA_APP_ROOT/nginx_conf/va-nginx.conf 48 | chmod +x $SERVICE_SH 49 | sudo $SERVICE_SH initconf $VANILLA_RUNNING_ENV 50 | sudo $SERVICE_SH start $VANILLA_RUNNING_ENV 51 | sudo $SERVICE_SH restart $VANILLA_RUNNING_ENV 52 | echo $ECHO_E"\033[40mVanilla App: $APP_NAME is running \033[0m\n" 53 | } 54 | 55 | show_usage() 56 | { 57 | echo $ECHO_E"`printf %-16s "Usage: $0"` -h show this help info" 58 | echo $ECHO_E"`printf %-16s ` -a VANILLA_APP_ROOT, app absolute path(which path to init app)" 59 | echo $ECHO_E"`printf %-16s ` -u VANILLA_APP_USER, user to run app" 60 | echo $ECHO_E"`printf %-16s ` -g VANILLA_APP_GROUP, user group to run app" 61 | echo $ECHO_E"`printf %-16s ` -e VANILLA_RUNNING_ENV, app running environment" 62 | } 63 | 64 | while getopts a:u:g:e:h OPT; do 65 | case "$OPT" in 66 | a ) 67 | VANILLA_APP_ROOT=$OPTARG 68 | ;; 69 | u ) 70 | VANILLA_APP_USER=$OPTARG 71 | ;; 72 | g ) 73 | VANILLA_APP_GROUP=$OPTARG 74 | ;; 75 | e ) 76 | VANILLA_RUNNING_ENV=$OPTARG 77 | ;; 78 | h ) 79 | show_usage && exit 0 80 | ;; 81 | -- ) 82 | shift break 83 | ;; 84 | ? ) 85 | alert "ERROR: unknown argument!" && show_usage && exit 1 86 | ;; 87 | esac 88 | done 89 | 90 | APP_NAME=`basename $VANILLA_APP_ROOT` 91 | init_vanilla_app $VANILLA_APP_ROOT $VANILLA_APP_USER $VANILLA_APP_GROUP $APP_NAME $VANILLA_RUNNING_ENV 92 | 93 | echo 94 | echo $ECHO_E"You are setup $APP_NAME and using:" 95 | echo $ECHO_E"`printf %-36s "\"$VANILLA_APP_ROOT\""` ---- as vanilla app root" 96 | echo $ECHO_E"`printf %-36s "\"$VANILLA_RUNNING_ENV\""` ---- as running environment" 97 | echo $ECHO_E"`printf %-36s "\"$VANILLA_APP_USER\""` ---- as vanilla app nginx user" 98 | echo $ECHO_E"`printf %-36s "\"$VANILLA_APP_GROUP\""` ---- as vanilla app nginx group" 99 | echo 100 | 101 | exit 0 -------------------------------------------------------------------------------- /spec/helper.lua: -------------------------------------------------------------------------------- 1 | package.loaded['config.routes'] = { } 2 | package.loaded['config.application'] = {} 3 | package.loaded['resty.upload'] = {} 4 | package.loaded['resty.memcached'] = {} 5 | package.loaded['resty.lrucache'] = {} 6 | package.loaded['resty.lrucache.pureffi'] = {} 7 | package.loaded['resty.redis'] = {} 8 | 9 | LoadV = function ( ... ) 10 | return require(...) 11 | end 12 | 13 | local _class = function(_, classname, parent) 14 | local mttt = { 15 | __call = function(self, ... ) 16 | return self:new(...) 17 | end 18 | } 19 | local parent_type = type(parent) 20 | if parent_type ~= "function" and parent_type ~= "table" then 21 | parent = nil 22 | end 23 | local cls = {} 24 | if parent then 25 | mttt.__index = parent 26 | cls.parent = parent 27 | end 28 | cls.new = function(self, ...) 29 | local instance = { class = self } 30 | setmetatable(instance, self) 31 | if instance.__construct and type(instance.__construct) == 'function' then 32 | instance:__construct(...) 33 | end 34 | return instance 35 | end 36 | cls["is" .. classname] =true 37 | cls.__cname = classname 38 | cls.__index = cls 39 | setmetatable(cls, mttt) 40 | return cls 41 | end 42 | 43 | local class = {} 44 | Class = setmetatable(class, { __call = function(...) return _class(...) end }) 45 | 46 | Registry={} 47 | Registry['APP_NAME'] = 'vanilla-app' 48 | 49 | local reg = require "rex_pcre" 50 | -- DICT Proxy 51 | -- https://github.com/bsm/fakengx/blob/master/fakengx.lua 52 | 53 | local SharedDict = {} 54 | 55 | local function set(data, key, value) 56 | data[key] = { 57 | value = value, 58 | info = {expired = false} 59 | } 60 | end 61 | 62 | function SharedDict:new() 63 | return setmetatable({data = {}}, {__index = self}) 64 | end 65 | 66 | function SharedDict:get(key) 67 | return self.data[key] and self.data[key].value, nil 68 | end 69 | 70 | function SharedDict:set(key, value) 71 | set(self.data, key, value) 72 | return true, nil, false 73 | end 74 | 75 | SharedDict.safe_set = SharedDict.set 76 | 77 | function SharedDict:add(key, value) 78 | if self.data[key] ~= nil then 79 | return false, "exists", false 80 | end 81 | 82 | set(self.data, key, value) 83 | return true, nil, false 84 | end 85 | 86 | function SharedDict:replace(key, value) 87 | if self.data[key] == nil then 88 | return false, "not found", false 89 | end 90 | 91 | set(self.data, key, value) 92 | return true, nil, false 93 | end 94 | 95 | function SharedDict:delete(key) 96 | self.data[key] = nil 97 | end 98 | 99 | function SharedDict:incr(key, value) 100 | if not self.data[key] then 101 | return nil, "not found" 102 | elseif type(self.data[key].value) ~= "number" then 103 | return nil, "not a number" 104 | end 105 | 106 | self.data[key].value = self.data[key].value + value 107 | return self.data[key].value, nil 108 | end 109 | 110 | function SharedDict:flush_all() 111 | for _, item in pairs(self.data) do 112 | item.info.expired = true 113 | end 114 | end 115 | 116 | function SharedDict:flush_expired(n) 117 | local data = self.data 118 | local flushed = 0 119 | 120 | for key, item in pairs(self.data) do 121 | if item.info.expired then 122 | data[key] = nil 123 | flushed = flushed + 1 124 | if n and flushed == n then 125 | break 126 | end 127 | end 128 | end 129 | 130 | self.data = data 131 | 132 | return flushed 133 | end 134 | 135 | local shared = {} 136 | local shared_mt = { 137 | __index = function(self, key) 138 | if shared[key] == nil then 139 | shared[key] = SharedDict:new() 140 | end 141 | return shared[key] 142 | end 143 | } 144 | 145 | -- NGX Prototype 146 | local protoype = { 147 | 148 | -- Log constants 149 | STDERR = 0, 150 | EMERG = 1, 151 | ALERT = 2, 152 | CRIT = 3, 153 | ERR = 4, 154 | WARN = 5, 155 | NOTICE = 6, 156 | INFO = 7, 157 | DEBUG = 8, 158 | 159 | -- HTTP Method Constants 160 | HTTP_GET = "GET", 161 | HTTP_HEAD = "HEAD", 162 | HTTP_POST = "POST", 163 | HTTP_PUT = "PUT", 164 | HTTP_DELETE = "DELETE", 165 | 166 | -- HTTP Status Constants 167 | HTTP_OK = 200, 168 | HTTP_CREATED = 201, 169 | HTTP_ACCEPTED = 202, 170 | HTTP_NO_CONTENT = 204, 171 | HTTP_PARTIAL_CONTENT = 206, 172 | HTTP_SPECIAL_RESPONSE = 300, 173 | HTTP_MOVED_PERMANENTLY = 301, 174 | HTTP_MOVED_TEMPORARILY = 302, 175 | HTTP_SEE_OTHER = 303, 176 | HTTP_NOT_MODIFIED = 304, 177 | HTTP_BAD_REQUEST = 400, 178 | HTTP_UNAUTHORIZED = 401, 179 | HTTP_FORBIDDEN = 403, 180 | HTTP_NOT_FOUND = 404, 181 | HTTP_NOT_ALLOWED = 405, 182 | HTTP_REQUEST_TIME_OUT = 408, 183 | HTTP_CONFLICT = 409, 184 | HTTP_LENGTH_REQUIRED = 411, 185 | HTTP_PRECONDITION_FAILED = 412, 186 | HTTP_REQUEST_ENTITY_TOO_LARGE = 413, 187 | HTTP_REQUEST_URI_TOO_LARGE = 414, 188 | HTTP_UNSUPPORTED_MEDIA_TYPE = 415, 189 | HTTP_RANGE_NOT_SATISFIABLE = 416, 190 | HTTP_CLOSE = 444, 191 | HTTP_NGINX_CODES = 494, 192 | HTTP_REQUEST_HEADER_TOO_LARGE = 494, 193 | HTTP_INTERNAL_SERVER_ERROR = 500, 194 | HTTP_NOT_IMPLEMENTED = 501, 195 | HTTP_BAD_GATEWAY = 502, 196 | HTTP_SERVICE_UNAVAILABLE = 503, 197 | HTTP_GATEWAY_TIME_OUT = 504, 198 | HTTP_INSUFFICIENT_STORAGE = 507, 199 | 200 | } 201 | 202 | _G.ngx = { 203 | ctx = {}, 204 | exit = function(code) return end, 205 | print = function(print) return end, 206 | log = function() end, 207 | status = 200, 208 | location = {}, 209 | say = print, 210 | eof = os.exit, 211 | header = {}, 212 | socket = { tcp = {} }, 213 | now = function() return os.time() end, 214 | time = function() return os.time() end, 215 | timer = { 216 | at = function() end 217 | }, 218 | shared = setmetatable({}, shared_mt), 219 | re = { 220 | match = reg.match, 221 | gsub = function(str, pattern, sub) 222 | local res_str, _, sub_made = reg.gsub(str, pattern, sub) 223 | return res_str, sub_made 224 | end 225 | }, 226 | shared = setmetatable({}, shared_mt), 227 | req = { 228 | read_body = function() return {} end, 229 | get_body_data = function() return {} end, 230 | get_headers = function() return {} end, 231 | get_uri_args = function() return {} end, 232 | get_method = function() return {} end, 233 | get_post_args = function() return {busted = 'busted'} end, 234 | }, 235 | encode_base64 = function(str) 236 | return string.format("base64_%s", str) 237 | end, 238 | -- Builds a querystring from a table, separated by `&` 239 | -- @param `tab` The key/value parameters 240 | -- @param `key` The parent key if the value is multi-dimensional (optional) 241 | -- @return `querystring` A string representing the built querystring 242 | encode_args = function(tab, key) 243 | local query = {} 244 | local keys = {} 245 | 246 | for k in pairs(tab) do 247 | keys[#keys+1] = k 248 | end 249 | 250 | table.sort(keys) 251 | 252 | for _, name in ipairs(keys) do 253 | local value = tab[name] 254 | if key then 255 | name = string.format("%s[%s]", tostring(key), tostring(name)) 256 | end 257 | if type(value) == "table" then 258 | query[#query+1] = ngx.encode_args(value, name) 259 | else 260 | value = tostring(value) 261 | if value ~= "" then 262 | query[#query+1] = string.format("%s=%s", name, value) 263 | else 264 | query[#query+1] = name 265 | end 266 | end 267 | end 268 | 269 | return table.concat(query, "&") 270 | end, 271 | var = { 272 | uri = "/users", 273 | document_root = './', 274 | VANILLA_VERSION = './test-vanilla', 275 | request_method = 'GET' 276 | } 277 | } 278 | 279 | for k, v in pairs(protoype) do 280 | _G.ngx[k] = v 281 | end 282 | setmetatable(ngx, getmetatable(protoype)) 283 | 284 | local config={} 285 | config.name = 'bluebird' 286 | 287 | config.vanilla_root = '{{VANILLA_ROOT}}' 288 | config.vanilla_version = '{{VANILLA_VERSION_DIR_STR}}' 289 | config.route='vanilla.v.routes.simple' 290 | config.bootstrap='application.bootstrap' 291 | config.app={} 292 | config.app.root='./' 293 | 294 | config.controller={} 295 | config.controller.path=config.app.root .. 'application/controllers/' 296 | 297 | config.view={} 298 | config.view.path=config.app.root .. 'application/views/' 299 | config.view.suffix='.html' 300 | config.view.auto_render=true 301 | 302 | _G['config'] = config 303 | 304 | require 'vanilla.spec.runner' -------------------------------------------------------------------------------- /spec/v/dispatcher_spec.lua: -------------------------------------------------------------------------------- 1 | require('spec.helper') 2 | 3 | describe("Dispatcher", function() 4 | before_each(function() 5 | Application = require 'vanilla.v.application' 6 | Dispatcher = require 'vanilla.v.dispatcher' 7 | Controller = require 'vanilla.v.controller' 8 | Request = require 'vanilla.v.request' 9 | Response = require 'vanilla.v.response' 10 | View = require 'vanilla.v.views.rtpl' 11 | Error = require 'vanilla.v.error' 12 | Plugin = require 'vanilla.v.plugin' 13 | 14 | application = Application:new(ngx, config) 15 | dispatcher = Dispatcher:new(application) 16 | request = Request:new() 17 | response = Response:new() 18 | plugin = Plugin:new() 19 | end) 20 | 21 | after_each(function() 22 | package.loaded['vanilla.v.application'] = nil 23 | package.loaded['vanilla.v.dispatcher'] = nil 24 | package.loaded['vanilla.v.controller'] = nil 25 | package.loaded['vanilla.v.request'] = nil 26 | package.loaded['vanilla.v.response'] = nil 27 | package.loaded['vanilla.v.views.rtpl'] = nil 28 | package.loaded['vanilla.v.error'] = nil 29 | package.loaded['vanilla.v.plugin'] = nil 30 | Application = nil 31 | Dispatcher = nil 32 | Controller = nil 33 | Request = nil 34 | Response = nil 35 | View = nil 36 | Error = nil 37 | Plugin = nil 38 | 39 | application = nil 40 | dispatcher = nil 41 | request = nil 42 | response = nil 43 | plugin = nil 44 | end) 45 | 46 | describe("#new", function() 47 | it("creates a new instance of a dispatcher with application", function() 48 | assert.are.same(application, dispatcher.application) 49 | end) 50 | end) 51 | 52 | describe("#getRequest", function() 53 | it("get a request instance", function() 54 | assert.are.same(request, dispatcher.request) 55 | end) 56 | end) 57 | 58 | describe("#setRequest", function() 59 | it("set a request instance", function() 60 | assert.are.same(request, dispatcher.request) 61 | end) 62 | end) 63 | 64 | describe("#getResponse", function() 65 | it("get a response instance", function() 66 | assert.are.same(response, dispatcher.response) 67 | end) 68 | end) 69 | 70 | describe("#setResponse", function() 71 | it("set a response instance", function() 72 | assert.are.same(response, dispatcher.response) 73 | end) 74 | end) 75 | 76 | describe("#registerPlugin", function() 77 | it("register a plugin to app", function() 78 | assert.are.same(plugin, dispatcher.plugins) 79 | end) 80 | end) 81 | 82 | -- describe("#_router", function() 83 | -- it("raises an error with a code", function() 84 | -- local ok, err = pcall(function() controller:raise_error(1000) end) 85 | 86 | -- assert.are.equal(false, ok) 87 | -- assert.are.equal(1000, err.code) 88 | -- end) 89 | 90 | -- it("raises an error with a code and custom attributes", function() 91 | -- local custom_attrs = { custom_attr_1 = "1", custom_attr_2 = "2" } 92 | -- local ok, err = pcall(function() controller:raise_error(1000, custom_attrs) end) 93 | 94 | -- assert.are.equal(false, ok) 95 | -- assert.are.equal(1000, err.code) 96 | -- assert.are.same(custom_attrs, err.custom_attrs) 97 | -- end) 98 | -- end) 99 | 100 | -- describe("#dispatch", function() 101 | -- before_each(function() 102 | -- local Response = require 'gin.core.response' 103 | -- response = Response.new({ 104 | -- status = 200, 105 | -- headers = { ['one'] = 'first', ['two'] = 'second' }, 106 | -- body = { name = 'gin'} 107 | -- }) 108 | -- end) 109 | 110 | -- it("sets the ngx status", function() 111 | -- Router.respond(ngx, response) 112 | 113 | -- assert.are.equal(200, ngx.status) 114 | -- end) 115 | -- end) 116 | end) -------------------------------------------------------------------------------- /vanilla-0.1.0.rc7-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "vanilla" 2 | version = "0.1.0.rc7-1" 3 | 4 | source ={ 5 | url ="git://github.com/idevz/vanilla.git" 6 | } 7 | 8 | description ={ 9 | summary ="An OpenResty Lua MVC Web Framework", 10 | homepage ="http://idevz.github.io/vanilla", 11 | maintainer ="zhoujing", 12 | license ="MIT", 13 | detailed = [[ 14 | ##install 15 | ``` 16 | yum install lua-devel luarocks 17 | luarocks install vanilla 18 | ```]] 19 | } 20 | 21 | dependencies ={ 22 | "lua=5.1", 23 | "luafilesystem=1.6.2-2", 24 | "lua-resty-template=1.5-1", 25 | "lua-resty-cookie=0.1.0-1", 26 | "lua-resty-session=2.2-1", 27 | "lua-resty-http=0.06-0" 28 | } 29 | 30 | build = { 31 | type = "builtin", 32 | modules = { 33 | ["spec.helper"] = "spec/helper.lua", 34 | ["spec.v.dispatcher_spec"] = "spec/v/dispatcher_spec.lua", 35 | ["vanilla.base"] = "vanilla/base/init.lua", 36 | ["vanilla.base.registry"] = "vanilla/base/registry.lua", 37 | ["vanilla.base.resty.cookie"] = "vanilla/base/resty/cookie.lua", 38 | ["vanilla.base.resty.http"] = "vanilla/base/resty/http.lua", 39 | ["vanilla.base.resty.http_headers"] = "vanilla/base/resty/http_headers.lua", 40 | ["vanilla.base.resty.template"] = "vanilla/base/resty/template.lua", 41 | ["vanilla.base.resty.template.html"] = "vanilla/base/resty/template/html.lua", 42 | ["vanilla.base.resty.template.microbenchmark"] = "vanilla/base/resty/template/microbenchmark.lua", 43 | ["vanilla.spec"] = "vanilla/spec/init.lua", 44 | ["vanilla.spec.runner"] = "vanilla/spec/runner.lua", 45 | ["vanilla.spec.runners.integration"] = "vanilla/spec/runners/integration.lua", 46 | ["vanilla.spec.runners.response"] = "vanilla/spec/runners/response.lua", 47 | ["vanilla.sys.application"] = "vanilla/sys/application.lua", 48 | ["vanilla.sys.config"] = "vanilla/sys/config.lua", 49 | ["vanilla.sys.console"] = "vanilla/sys/console.lua", 50 | ["vanilla.sys.nginx.config"] = "vanilla/sys/nginx/config.lua", 51 | ["vanilla.sys.nginx.directive"] = "vanilla/sys/nginx/directive.lua", 52 | ["vanilla.sys.nginx.handle"] = "vanilla/sys/nginx/handle.lua", 53 | ["vanilla.sys.vanilla"] = "vanilla/sys/vanilla.lua", 54 | ["vanilla.sys.waf.acc"] = "vanilla/sys/waf/acc.lua", 55 | ["vanilla.sys.waf.config"] = "vanilla/sys/waf/config.lua", 56 | ["vanilla.v.application"] = "vanilla/v/application.lua", 57 | ["vanilla.v.bootstrap"] = "vanilla/v/bootstrap.lua", 58 | ["vanilla.v.cache"] = "vanilla/v/cache.lua", 59 | ["vanilla.v.cache.base"] = "vanilla/v/cache/base.lua", 60 | ["vanilla.v.cache.lru"] = "vanilla/v/cache/lru.lua", 61 | ["vanilla.v.cache.mc"] = "vanilla/v/cache/mc.lua", 62 | ["vanilla.v.cache.redis"] = "vanilla/v/cache/redis.lua", 63 | ["vanilla.v.cache.shdict"] = "vanilla/v/cache/shdict.lua", 64 | ["vanilla.v.config.handle"] = "vanilla/v/config/handle.lua", 65 | ["vanilla.v.config.parse"] = "vanilla/v/config/parse.lua", 66 | ["vanilla.v.config.save"] = "vanilla/v/config/save.lua", 67 | ["vanilla.v.controller"] = "vanilla/v/controller.lua", 68 | ["vanilla.v.dispatcher"] = "vanilla/v/dispatcher.lua", 69 | ["vanilla.v.error"] = "vanilla/v/error.lua", 70 | ["vanilla.v.libs.ansicolors"] = "vanilla/v/libs/ansicolors.lua", 71 | ["vanilla.v.libs.cache"] = "vanilla/v/libs/cache.lua", 72 | ["vanilla.v.libs.cookie"] = "vanilla/v/libs/cookie.lua", 73 | ["vanilla.v.libs.http"] = "vanilla/v/libs/http.lua", 74 | ["vanilla.v.libs.logs"] = "vanilla/v/libs/logs.lua", 75 | ["vanilla.v.libs.reqargs"] = "vanilla/v/libs/reqargs.lua", 76 | ["vanilla.v.libs.session"] = "vanilla/v/libs/session.lua", 77 | ["vanilla.v.libs.shcache"] = "vanilla/v/libs/shcache.lua", 78 | ["vanilla.v.libs.utils"] = "vanilla/v/libs/utils.lua", 79 | ["vanilla.v.plugin"] = "vanilla/v/plugin.lua", 80 | ["vanilla.v.registry"] = "vanilla/v/registry.lua", 81 | ["vanilla.v.request"] = "vanilla/v/request.lua", 82 | ["vanilla.v.response"] = "vanilla/v/response.lua", 83 | ["vanilla.v.router"] = "vanilla/v/router.lua", 84 | ["vanilla.v.routes.restful"] = "vanilla/v/routes/restful.lua", 85 | ["vanilla.v.routes.simple"] = "vanilla/v/routes/simple.lua", 86 | ["vanilla.v.view"] = "vanilla/v/view.lua", 87 | ["vanilla.v.views.rtpl"] = "vanilla/v/views/rtpl.lua" 88 | }, 89 | install ={ 90 | bin ={ 91 | "vanilla/bin/vanilla", 92 | "vanilla/bin/v-console" 93 | } 94 | }, 95 | } 96 | -------------------------------------------------------------------------------- /vanilla-en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla/6eb4d7af8cc8cb8419e7d539420e7f6149077686/vanilla-en.png -------------------------------------------------------------------------------- /vanilla-pub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idevz/vanilla/6eb4d7af8cc8cb8419e7d539420e7f6149077686/vanilla-pub.png -------------------------------------------------------------------------------- /vanilla/Makefile: -------------------------------------------------------------------------------- 1 | OPENRESTY_PREFIX=/usr/local/openresty 2 | 3 | PREFIX ?= /usr/local/vanilla 4 | VANILLA_LIB_DIR ?= $(PREFIX)/ 5 | INSTALL ?= install 6 | MKDIR ?= mkdir -p 7 | DEV_ROCKS = busted luacov luacov-coveralls luacheck lrexlib-pcre 8 | 9 | .PHONY: all test install dev 10 | 11 | all: ; 12 | 13 | install: all 14 | # $(INSTALL) -d $(VANILLA_LIB_DIR)/vanilla/resty/ 15 | $(INSTALL) ./bin/ $(VANILLA_LIB_DIR)/bin 16 | $(MKDIR) $(VANILLA_LIB_DIR)/vanilla 17 | $(INSTALL) ./base/* $(VANILLA_ROOT)/ 18 | $(INSTALL) ./v $(VANILLA_LIB_DIR)/vanilla 19 | $(INSTALL) ./sys $(VANILLA_LIB_DIR)/vanilla 20 | $(INSTALL) ./spec $(VANILLA_LIB_DIR)/vanilla 21 | $(INSTALL) ./vanilla-$(VANILLA_VERSION) $(VANILLA_BIN_PATH)/vanilla-$(VANILLA_VERSION) 22 | $(INSTALL) ./v-console-$(VANILLA_VERSION) $(VANILLA_BIN_PATH)/v-console-$(VANILLA_VERSION) 23 | $(INSTALL) ./lemplate-$(VANILLA_VERSION) $(VANILLA_BIN_PATH)/lemplate-$(VANILLA_VERSION) 24 | 25 | test: all 26 | PATH=$(OPENRESTY_PREFIX)/nginx/sbin:$$PATH prove -I../test-nginx/lib -r t 27 | 28 | dev: install 29 | @for rock in $(DEV_ROCKS) ; do \ 30 | if ! command -v $$rock &> /dev/null ; then \ 31 | echo $$rock not found, installing via luarocks... ; \ 32 | luarocks install $$rock ; \ 33 | else \ 34 | echo $$rock already installed, skipping ; \ 35 | fi \ 36 | done; 37 | -------------------------------------------------------------------------------- /vanilla/base/init.lua: -------------------------------------------------------------------------------- 1 | -- Request moudle 2 | -- @since 2015-08-17 10:54 3 | -- @author idevz 4 | -- version $Id$ 5 | 6 | 7 | -- local helpers = require '/media/psf/g/idevz/code/www/vanilla/framework/0_1_0_rc7/vanilla.v.libs.utils' 8 | -- function sprint_r( ... ) 9 | -- return helpers.sprint_r(...) 10 | -- end 11 | 12 | -- function lprint_r( ... ) 13 | -- local rs = sprint_r(...) 14 | -- print(rs) 15 | -- end 16 | 17 | -- function print_r( ... ) 18 | -- local rs = sprint_r(...) 19 | -- ngx.say(rs) 20 | -- end 21 | 22 | Registry = require('registry'):new() 23 | 24 | 25 | --+--------------------------------------------------------------------------------+-- 26 | local _class = function(_, classname, parent) 27 | local mttt = { 28 | __call = function(self, ... ) 29 | return self:new(...) 30 | end 31 | } 32 | local parent_type = type(parent) 33 | if parent_type ~= "function" and parent_type ~= "table" then 34 | parent = nil 35 | end 36 | local cls = {} 37 | if parent then 38 | mttt.__index = parent 39 | cls.parent = parent 40 | end 41 | cls.new = function(self, ...) 42 | local instance = { class = self } 43 | setmetatable(instance, self) 44 | if instance.__construct and type(instance.__construct) == 'function' then 45 | instance:__construct(...) 46 | end 47 | return instance 48 | end 49 | cls["is" .. classname] =true 50 | cls.__cname = classname 51 | cls.__index = cls 52 | setmetatable(cls, mttt) 53 | return cls 54 | end 55 | 56 | local class = {} 57 | Class = setmetatable(class, { __call = function(...) return _class(...) end }) 58 | 59 | -- local old_require = require 60 | -- require = function( ... ) 61 | -- -- ngx.say(...) 62 | -- return old_require(...) 63 | -- end 64 | 65 | 66 | --+--------------------------------------------------------------------------------+-- 67 | local require = require 68 | LoadLibrary = function ( ... ) 69 | return require(Registry['APP_ROOT'] .. '/application/library/' .. ...) 70 | end 71 | 72 | LoadController = function ( ... ) 73 | return require(Registry['APP_ROOT'] .. '/application/controllers/' .. ...) 74 | end 75 | 76 | LoadModel = function ( ... ) 77 | return require(Registry['APP_ROOT'] .. '/application/models/' .. ...) 78 | end 79 | 80 | LoadPlugin = function ( ... ) 81 | return require(Registry['APP_ROOT'] .. '/application/plugins/' .. ...) 82 | end 83 | 84 | LoadApplication = function ( ... ) 85 | return require(Registry['APP_ROOT'] .. '/application/' .. ...) 86 | end 87 | 88 | LoadApp = function ( ... ) 89 | return require(Registry['APP_ROOT'] .. '/' .. ...) 90 | end 91 | 92 | LoadV = function ( ... ) 93 | return require(Registry['VANILLA_ROOT'] .. '/' .. Registry['VANILLA_VERSION'] .. '/' .. ...) 94 | end 95 | 96 | 97 | --+--------------------------------------------------------------------------------+-- 98 | local LoadSysConf = function() 99 | local sysconf_files = Registry['APP_CONF']['sysconf'] 100 | local conf_handle = LoadV('vanilla.v.config.handle')('ini') 101 | Registry['sys_conf'] = {} 102 | for _,v in ipairs(sysconf_files) do 103 | Registry['sys_conf'][v] = conf_handle:get('sys/' .. v) 104 | end 105 | end 106 | 107 | 108 | --+--------------------------------------------------------------------------------+-- 109 | init_vanilla = function () 110 | local ngx_var = ngx.var 111 | local ngx_req = ngx.req 112 | Registry.namespace = ngx_var.APP_NAME 113 | 114 | local REQ_Registry = require('registry'):new() 115 | REQ_Registry.namespace = ngx_var.APP_NAME 116 | 117 | REQ_Registry['REQ_URI'] = ngx_var.uri 118 | REQ_Registry['REQ_ARGS'] = ngx_var.args 119 | REQ_Registry['REQ_ARGS_ARR'] = ngx_req.get_uri_args() 120 | REQ_Registry['REQ_HEADERS'] = ngx_req.get_headers() 121 | REQ_Registry['APP_CACHE_PURGE'] = REQ_Registry['REQ_ARGS_ARR']['vapurge'] 122 | ngx.ctx.REQ_Registry = REQ_Registry 123 | 124 | 125 | if Registry['VANILLA_INIT'] then return end 126 | Registry['VA_ENV'] = ngx_var.VA_ENV 127 | Registry['APP_NAME'] = Registry.namespace 128 | Registry['APP_ROOT'] = ngx_var.document_root 129 | Registry['APP_HOST'] = ngx_var.host 130 | Registry['APP_PORT'] = ngx_var.server_port 131 | Registry['VANILLA_ROOT'] = ngx_var.VANILLA_ROOT 132 | Registry['VANILLA_VERSION'] = ngx_var.VANILLA_VERSION 133 | 134 | Registry['VANILLA_APPLICATION'] = LoadV 'vanilla.v.application' 135 | Registry['VANILLA_UTILS'] = LoadV 'vanilla.v.libs.utils' 136 | Registry['VANILLA_CACHE_LIB'] = LoadV 'vanilla.v.cache' 137 | Registry['VANILLA_COOKIE_LIB'] = LoadV 'vanilla.v.libs.cookie' 138 | 139 | Registry['APP_CONF'] = LoadApp 'config.application' 140 | Registry['APP_BOOTS'] = LoadApp 'application.bootstrap' 141 | Registry['APP_PAGE_CACHE_CONF'] = Registry['APP_CONF']['page_cache'] 142 | LoadSysConf() 143 | Registry['VANILLA_INIT'] = true 144 | end 145 | 146 | --+--------------------------------------------------------------------------------+-- 147 | local ngx_re_find = ngx.re.find 148 | use_page_cache = function () 149 | local REQ_Registry = ngx.ctx.REQ_Registry 150 | local cookie_lib = Registry['VANILLA_COOKIE_LIB'] 151 | local cookie = cookie_lib() 152 | local no_cache_uris = Registry['APP_PAGE_CACHE_CONF']['no_cache_uris'] 153 | for _, uri in ipairs(no_cache_uris) do 154 | if ngx_re_find(REQ_Registry['REQ_URI'], uri) ~= nil then return false end 155 | end 156 | REQ_Registry['COOKIES'] = cookie:getAll() 157 | if Registry['APP_PAGE_CACHE_CONF']['cache_on'] then 158 | if REQ_Registry['COOKIES'] and REQ_Registry['COOKIES'][Registry['APP_PAGE_CACHE_CONF']['no_cache_cookie']] then return false else return true end 159 | else 160 | return false 161 | end 162 | end 163 | 164 | 165 | --+--------------------------------------------------------------------------------+-- 166 | local tab_concat = table.concat 167 | local function clean_args(args) 168 | local del_keys = Registry['APP_PAGE_CACHE_CONF']['build_cache_key_without_args'] 169 | for _,v in pairs(del_keys) do 170 | args[v] = nil 171 | end 172 | if args['vapurge'] ~= nil then args['vapurge'] = nil end 173 | return args 174 | end 175 | 176 | local function build_url_key(args) 177 | local rs = {} 178 | local tmp = 1 179 | for k,v in pairs(args) do 180 | rs[tmp] = k .. '=' .. tostring(v) 181 | tmp = tmp + 1 182 | end 183 | return tab_concat( rs, "_") 184 | end 185 | 186 | page_cache = function () 187 | local ngx_var = ngx.var 188 | local REQ_Registry = ngx.ctx.REQ_Registry 189 | REQ_Registry['USE_PAGE_CACHE'] = use_page_cache() 190 | if not REQ_Registry['USE_PAGE_CACHE'] then ngx.header['X-Cache'] = 'PASSBY' return end 191 | local cache_lib = Registry['VANILLA_CACHE_LIB'] 192 | Registry['page_cache_handle'] = Registry['APP_PAGE_CACHE_CONF']['cache_handle'] or 'shared_dict' 193 | local cache = cache_lib(Registry['page_cache_handle']) 194 | REQ_Registry['APP_PAGE_CACHE_KEY'] = REQ_Registry['REQ_URI'] .. ngx.encode_args(clean_args(REQ_Registry['REQ_ARGS_ARR'])) 195 | 196 | if REQ_Registry['APP_CACHE_PURGE'] then 197 | cache:del(REQ_Registry['APP_PAGE_CACHE_KEY']) 198 | ngx.header['X-Cache'] = 'XX' 199 | return 200 | end 201 | 202 | local rs = cache:get(REQ_Registry['APP_PAGE_CACHE_KEY']) 203 | if rs then 204 | ngx.header['X-Cache'] = 'HIT' 205 | ngx_var.va_cache_status = 'HIT' 206 | ngx.header['Power_By'] = 'Vanilla-Page-Cache' 207 | if ngx_re_find(REQ_Registry['REQ_HEADERS']['accept'], 'json') then 208 | ngx.header['Content_type'] = 'application/json' 209 | else 210 | ngx.header['Content_type'] = 'text/html' 211 | end 212 | ngx.print(rs) 213 | ngx.exit(ngx.HTTP_OK) 214 | else 215 | ngx.header['X-Cache'] = 'MISS' 216 | ngx_var.va_cache_status = 'MISS' 217 | end 218 | end 219 | 220 | 221 | --+--------------------------------------------------------------------------------+-- 222 | -------------------------------------------------------------------------------- /vanilla/base/opm.lua: -------------------------------------------------------------------------------- 1 | -- Request moudle 2 | -- @since 2017-02-16 00:54 3 | -- @author idevz 4 | -- version $Id$ 5 | 6 | _VERSION = '0.1.0.rc7' -------------------------------------------------------------------------------- /vanilla/base/registry.lua: -------------------------------------------------------------------------------- 1 | -- Vanilla Registry 2 | -- @since 2016-04-09 20:34 3 | -- @author idevz 4 | -- version $Id$ 5 | 6 | local ok, new_tab = pcall(require, "table.new") 7 | if not ok or type(new_tab) ~= "function" then 8 | new_tab = function (narr, nrec) return {} end 9 | end 10 | 11 | local setmetatable = setmetatable 12 | 13 | local Registry = new_tab(0, 6) 14 | 15 | function Registry:del(key) 16 | local data = rawget(self, "_data") 17 | if data[self.namespace] ~= nil and data[self.namespace][key] ~= nil then 18 | data[self.namespace][key] = nil 19 | end 20 | return true 21 | end 22 | 23 | function Registry:has(key) 24 | local data = rawget(self, "_data") 25 | if data[self.namespace][key] ~= nil then 26 | return true 27 | else 28 | return false 29 | end 30 | end 31 | 32 | function Registry:dump(namespace) 33 | local data = rawget(self, "_data") 34 | if namespace ~= nil then return data[namespace] else return data end 35 | end 36 | 37 | function Registry:new() 38 | local data = new_tab(0, 36) 39 | local instance = { 40 | namespace = 'vanilla_app', 41 | del = self.del, 42 | has = self.has, 43 | dump = self.dump, 44 | _data = data 45 | } 46 | return setmetatable(instance, {__index = self.__index, __newindex = self.__newindex}) 47 | end 48 | 49 | function Registry:__newindex(index, value) 50 | local data = rawget(self, "_data") 51 | if data[self.namespace] == nil then data[self.namespace] = {} end 52 | if index ~= nil then 53 | data[self.namespace][index]=value 54 | end 55 | end 56 | 57 | function Registry:__index(index) 58 | local data = rawget(self, "_data") 59 | if data[self.namespace] == nil then data[self.namespace] = {} end 60 | local out = data[self.namespace][index] 61 | if out then return out else return false end 62 | end 63 | 64 | return Registry 65 | -------------------------------------------------------------------------------- /vanilla/base/resty/cookie.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (C) 2013-2016 Jiale Zhi (calio), CloudFlare Inc. 2 | -- See RFC6265 http://tools.ietf.org/search/rfc6265 3 | -- require "luacov" 4 | 5 | local type = type 6 | local byte = string.byte 7 | local sub = string.sub 8 | local format = string.format 9 | local log = ngx.log 10 | local ERR = ngx.ERR 11 | local WARN = ngx.WARN 12 | local ngx_header = ngx.header 13 | 14 | local EQUAL = byte("=") 15 | local SEMICOLON = byte(";") 16 | local SPACE = byte(" ") 17 | local HTAB = byte("\t") 18 | 19 | -- table.new(narr, nrec) 20 | local ok, new_tab = pcall(require, "table.new") 21 | if not ok then 22 | new_tab = function () return {} end 23 | end 24 | 25 | local ok, clear_tab = pcall(require, "table.clear") 26 | if not ok then 27 | clear_tab = function(tab) for k, _ in pairs(tab) do tab[k] = nil end end 28 | end 29 | 30 | local _M = new_tab(0, 2) 31 | 32 | _M._VERSION = '0.01' 33 | 34 | 35 | local function get_cookie_table(text_cookie) 36 | if type(text_cookie) ~= "string" then 37 | log(ERR, format("expect text_cookie to be \"string\" but found %s", 38 | type(text_cookie))) 39 | return {} 40 | end 41 | 42 | local EXPECT_KEY = 1 43 | local EXPECT_VALUE = 2 44 | local EXPECT_SP = 3 45 | 46 | local n = 0 47 | local len = #text_cookie 48 | 49 | for i=1, len do 50 | if byte(text_cookie, i) == SEMICOLON then 51 | n = n + 1 52 | end 53 | end 54 | 55 | local cookie_table = new_tab(0, n + 1) 56 | 57 | local state = EXPECT_SP 58 | local i = 1 59 | local j = 1 60 | local key, value 61 | 62 | while j <= len do 63 | if state == EXPECT_KEY then 64 | if byte(text_cookie, j) == EQUAL then 65 | key = sub(text_cookie, i, j - 1) 66 | state = EXPECT_VALUE 67 | i = j + 1 68 | end 69 | elseif state == EXPECT_VALUE then 70 | if byte(text_cookie, j) == SEMICOLON 71 | or byte(text_cookie, j) == SPACE 72 | or byte(text_cookie, j) == HTAB 73 | then 74 | value = sub(text_cookie, i, j - 1) 75 | cookie_table[key] = value 76 | 77 | key, value = nil, nil 78 | state = EXPECT_SP 79 | i = j + 1 80 | end 81 | elseif state == EXPECT_SP then 82 | if byte(text_cookie, j) ~= SPACE 83 | and byte(text_cookie, j) ~= HTAB 84 | then 85 | state = EXPECT_KEY 86 | i = j 87 | j = j - 1 88 | end 89 | end 90 | j = j + 1 91 | end 92 | 93 | if key ~= nil and value == nil then 94 | cookie_table[key] = sub(text_cookie, i) 95 | end 96 | 97 | return cookie_table 98 | end 99 | 100 | function _M.new(self) 101 | local _cookie = ngx.var.http_cookie 102 | --if not _cookie then 103 | --return nil, "no cookie found in current request" 104 | --end 105 | return setmetatable({ _cookie = _cookie, set_cookie_table = new_tab(4, 0) }, 106 | { __index = self }) 107 | end 108 | 109 | function _M.get(self, key) 110 | if not self._cookie then 111 | return nil, "no cookie found in the current request" 112 | end 113 | if self.cookie_table == nil then 114 | self.cookie_table = get_cookie_table(self._cookie) 115 | end 116 | 117 | return self.cookie_table[key] 118 | end 119 | 120 | function _M.get_all(self) 121 | if not self._cookie then 122 | return nil, "no cookie found in the current request" 123 | end 124 | 125 | if self.cookie_table == nil then 126 | self.cookie_table = get_cookie_table(self._cookie) 127 | end 128 | 129 | return self.cookie_table 130 | end 131 | 132 | local function bake(cookie) 133 | if not cookie.key or not cookie.value then 134 | return nil, 'missing cookie field "key" or "value"' 135 | end 136 | 137 | if cookie["max-age"] then 138 | cookie.max_age = cookie["max-age"] 139 | end 140 | 141 | if (cookie.samesite) then 142 | local samesite = cookie.samesite 143 | 144 | -- if we dont have a valid-looking attribute, ignore the attribute 145 | if (samesite ~= "Strict" and samesite ~= "Lax") then 146 | log(WARN, "SameSite value must be 'Strict' or 'Lax'") 147 | cookie.samesite = nil 148 | end 149 | end 150 | 151 | local str = cookie.key .. "=" .. cookie.value 152 | .. (cookie.expires and "; Expires=" .. cookie.expires or "") 153 | .. (cookie.max_age and "; Max-Age=" .. cookie.max_age or "") 154 | .. (cookie.domain and "; Domain=" .. cookie.domain or "") 155 | .. (cookie.path and "; Path=" .. cookie.path or "") 156 | .. (cookie.secure and "; Secure" or "") 157 | .. (cookie.httponly and "; HttpOnly" or "") 158 | .. (cookie.samesite and "; SameSite=" .. cookie.samesite or "") 159 | .. (cookie.extension and "; " .. cookie.extension or "") 160 | return str 161 | end 162 | 163 | function _M.set(self, cookie) 164 | local cookie_str, err = bake(cookie) 165 | if not cookie_str then 166 | return nil, err 167 | end 168 | 169 | local set_cookie = ngx_header['Set-Cookie'] 170 | local set_cookie_type = type(set_cookie) 171 | local t = self.set_cookie_table 172 | clear_tab(t) 173 | 174 | if set_cookie_type == "string" then 175 | -- only one cookie has been setted 176 | if set_cookie ~= cookie_str then 177 | t[1] = set_cookie 178 | t[2] = cookie_str 179 | ngx_header['Set-Cookie'] = t 180 | end 181 | elseif set_cookie_type == "table" then 182 | -- more than one cookies has been setted 183 | local size = #set_cookie 184 | 185 | -- we can not set cookie like ngx.header['Set-Cookie'][3] = val 186 | -- so create a new table, copy all the values, and then set it back 187 | for i=1, size do 188 | t[i] = ngx_header['Set-Cookie'][i] 189 | if t[i] == cookie_str then 190 | -- new cookie is duplicated 191 | return true 192 | end 193 | end 194 | t[size + 1] = cookie_str 195 | ngx_header['Set-Cookie'] = t 196 | else 197 | -- no cookie has been setted 198 | ngx_header['Set-Cookie'] = cookie_str 199 | end 200 | return true 201 | end 202 | 203 | return _M 204 | -------------------------------------------------------------------------------- /vanilla/base/resty/http_headers.lua: -------------------------------------------------------------------------------- 1 | local rawget, rawset, setmetatable = 2 | rawget, rawset, setmetatable 3 | 4 | local str_gsub = string.gsub 5 | local str_lower = string.lower 6 | 7 | 8 | local _M = { 9 | _VERSION = '0.01', 10 | } 11 | 12 | 13 | -- Returns an empty headers table with internalised case normalisation. 14 | -- Supports the same cases as in ngx_lua: 15 | -- 16 | -- headers.content_length 17 | -- headers["content-length"] 18 | -- headers["Content-Length"] 19 | function _M.new(self) 20 | local mt = { 21 | normalised = {}, 22 | } 23 | 24 | 25 | mt.__index = function(t, k) 26 | local k_hyphened = str_gsub(k, "_", "-") 27 | local matched = rawget(t, k) 28 | if matched then 29 | return matched 30 | else 31 | local k_normalised = str_lower(k_hyphened) 32 | return rawget(t, mt.normalised[k_normalised]) 33 | end 34 | end 35 | 36 | 37 | -- First check the normalised table. If there's no match (first time) add an entry for 38 | -- our current case in the normalised table. This is to preserve the human (prettier) case 39 | -- instead of outputting lowercased header names. 40 | -- 41 | -- If there's a match, we're being updated, just with a different case for the key. We use 42 | -- the normalised table to give us the original key, and perorm a rawset(). 43 | mt.__newindex = function(t, k, v) 44 | -- we support underscore syntax, so always hyphenate. 45 | local k_hyphened = str_gsub(k, "_", "-") 46 | 47 | -- lowercase hyphenated is "normalised" 48 | local k_normalised = str_lower(k_hyphened) 49 | 50 | if not mt.normalised[k_normalised] then 51 | mt.normalised[k_normalised] = k_hyphened 52 | rawset(t, k_hyphened, v) 53 | else 54 | rawset(t, mt.normalised[k_normalised], v) 55 | end 56 | end 57 | 58 | return setmetatable({}, mt) 59 | end 60 | 61 | 62 | return _M 63 | -------------------------------------------------------------------------------- /vanilla/base/resty/template/html.lua: -------------------------------------------------------------------------------- 1 | local template = require "resty.template" 2 | local setmetatable = setmetatable 3 | local escape = template.escape 4 | local concat = table.concat 5 | local pairs = pairs 6 | local type = type 7 | 8 | local function tag(name, content, attr) 9 | local r, a, content = {}, {}, content or attr 10 | r[#r + 1] = "<" 11 | r[#r + 1] = name 12 | if attr then 13 | for k, v in pairs(attr) do 14 | if type(k) == "number" then 15 | a[#a + 1] = escape(v) 16 | else 17 | a[#a + 1] = k .. '="' .. escape(v) .. '"' 18 | end 19 | end 20 | if #a > 0 then 21 | r[#r + 1] = " " 22 | r[#r + 1] = concat(a, " ") 23 | end 24 | end 25 | if type(content) == "string" then 26 | r[#r + 1] = ">" 27 | r[#r + 1] = escape(content) 28 | r[#r + 1] = "" 31 | else 32 | r[#r + 1] = " />" 33 | end 34 | return concat(r) 35 | end 36 | 37 | local html = { __index = function(_, name) 38 | return function(attr) 39 | if type(attr) == "table" then 40 | return function(content) 41 | return tag(name, content, attr) 42 | end 43 | else 44 | return tag(name, attr) 45 | end 46 | end 47 | end } 48 | 49 | template.html = setmetatable(html, html) 50 | 51 | return template.html 52 | -------------------------------------------------------------------------------- /vanilla/base/resty/template/microbenchmark.lua: -------------------------------------------------------------------------------- 1 | local template = require "resty.template" 2 | 3 | local ok, new_tab = pcall(require, "table.new") 4 | if not ok then 5 | new_tab = function() return {} end 6 | end 7 | 8 | local function run(iterations) 9 | local gc, total, print, parse, compile, iterations, clock, format = collectgarbage, 0, ngx and ngx.say or print, template.parse, template.compile, iterations or 1000, os.clock, string.format 10 | local view = [[ 11 |
    12 | {% for _, v in ipairs(context) do %} 13 |
  • {{v}}
  • 14 | {% end %} 15 |
]] 16 | 17 | print(format("Running %d iterations in each test", iterations)) 18 | 19 | gc() 20 | gc() 21 | 22 | local x = clock() 23 | for _ = 1, iterations do 24 | parse(view, true) 25 | end 26 | local z = clock() - x 27 | print(format(" Parsing Time: %.6f", z)) 28 | total = total + z 29 | 30 | gc() 31 | gc() 32 | 33 | x = clock() 34 | for _ = 1, iterations do 35 | compile(view, nil, true) 36 | template.cache = {} 37 | end 38 | z = clock() - x 39 | print(format("Compilation Time: %.6f (template)", z)) 40 | total = total + z 41 | 42 | compile(view, nil, true) 43 | 44 | gc() 45 | gc() 46 | 47 | x = clock() 48 | for _ = 1, iterations do 49 | compile(view, 1, true) 50 | end 51 | z = clock() - x 52 | print(format("Compilation Time: %.6f (template, cached)", z)) 53 | total = total + z 54 | 55 | local context = { "Emma", "James", "Nicholas", "Mary" } 56 | 57 | template.cache = {} 58 | 59 | gc() 60 | gc() 61 | 62 | x = clock() 63 | for _ = 1, iterations do 64 | compile(view, 1, true)(context) 65 | template.cache = {} 66 | end 67 | z = clock() - x 68 | print(format(" Execution Time: %.6f (same template)", z)) 69 | total = total + z 70 | 71 | template.cache = {} 72 | compile(view, 1, true) 73 | 74 | gc() 75 | gc() 76 | 77 | x = clock() 78 | for _ = 1, iterations do 79 | compile(view, 1, true)(context) 80 | end 81 | z = clock() - x 82 | print(format(" Execution Time: %.6f (same template, cached)", z)) 83 | total = total + z 84 | 85 | template.cache = {} 86 | 87 | local views = new_tab(iterations, 0) 88 | for i = 1, iterations do 89 | views[i] = "

Iteration " .. i .. "

\n" .. view 90 | end 91 | 92 | gc() 93 | gc() 94 | 95 | x = clock() 96 | for i = 1, iterations do 97 | compile(views[i], i, true)(context) 98 | end 99 | z = clock() - x 100 | print(format(" Execution Time: %.6f (different template)", z)) 101 | total = total + z 102 | 103 | gc() 104 | gc() 105 | 106 | x = clock() 107 | for i = 1, iterations do 108 | compile(views[i], i, true)(context) 109 | end 110 | z = clock() - x 111 | print(format(" Execution Time: %.6f (different template, cached)", z)) 112 | total = total + z 113 | 114 | local contexts = new_tab(iterations, 0) 115 | 116 | for i = 1, iterations do 117 | contexts[i] = { "Emma", "James", "Nicholas", "Mary" } 118 | end 119 | 120 | template.cache = {} 121 | 122 | gc() 123 | gc() 124 | 125 | x = clock() 126 | for i = 1, iterations do 127 | compile(views[i], i, true)(contexts[i]) 128 | end 129 | z = clock() - x 130 | print(format(" Execution Time: %.6f (different template, different context)", z)) 131 | total = total + z 132 | 133 | gc() 134 | gc() 135 | 136 | x = clock() 137 | for i = 1, iterations do 138 | compile(views[i], i, true)(contexts[i]) 139 | end 140 | z = clock() - x 141 | print(format(" Execution Time: %.6f (different template, different context, cached)", z)) 142 | total = total + z 143 | print(format(" Total Time: %.6f", total)) 144 | end 145 | 146 | return { 147 | run = run 148 | } -------------------------------------------------------------------------------- /vanilla/bin/v-console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env luajit 2 | 3 | LoadV = function ( ... ) 4 | return require(VANILLA_ROOT .. '/' .. VANILLA_VERSION_DIR_STR .. '/' .. ...) 5 | end 6 | 7 | local console = LoadV('vanilla.sys.console') 8 | console.start() -------------------------------------------------------------------------------- /vanilla/bin/vanilla: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env luajit 2 | package.path = './?.lua;' .. package.path --;; didn't contains ./?.lua in cli 3 | 4 | LoadV = function ( ... ) 5 | return require(VANILLA_ROOT .. '/' .. VANILLA_VERSION_DIR_STR .. '/' .. ...) 6 | end 7 | 8 | local V = LoadV 'vanilla.sys.config' 9 | 10 | local help_description = [[ 11 | _| _| _|_| _| _| _|_|_| _| _| _|_| 12 | _| _| _| _| _|_| _| _| _| _| _| _| 13 | _| _| _|_|_|_| _| _| _| _| _| _| _|_|_|_| 14 | _| _| _| _| _| _|_| _| _| _| _| _| 15 | _| _| _| _| _| _|_|_| _|_|_|_| _|_|_|_| _| _| 16 | 17 | Vanilla v]] .. V.version .. [[, A MVC web framework for Lua powered by OpenResty. 18 | 19 | Usage: vanilla COMMAND [ARGS] [OPTIONS] 20 | 21 | The available vanilla commands are: 22 | new [name] Create a new Vanilla application 23 | ]] 24 | 25 | local launcher = LoadV 'vanilla.sys.vanilla' 26 | local application = LoadV 'vanilla.sys.application' 27 | 28 | -- check trace 29 | -- V_TRACE = false 30 | -- if arg[#arg] == '--trace' then 31 | -- table.remove(arg, #arg) 32 | -- 33 | -- V_TRACE = true 34 | -- end 35 | 36 | -- check args 37 | if arg[1] == 'new' and arg[2] then application.new(arg[2]) 38 | -- elseif arg[1] == 'start' then launcher.start() 39 | -- elseif arg[1] == 'stop' then launcher.stop() 40 | -- elseif arg[1] == 'restart' then 41 | -- launcher.stop() 42 | -- launcher.start() 43 | -- elseif arg[1] == 'reload' then launcher.reload() 44 | else print(help_description) 45 | end 46 | -------------------------------------------------------------------------------- /vanilla/install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Getopt::Std qw(getopts); 7 | 8 | my %opts; 9 | getopts("dm:", \%opts) or usage(); 10 | 11 | my $mode = $opts{m}; 12 | 13 | if ($opts{d}) { 14 | shell("mkdir -p @ARGV"); 15 | exit; 16 | } 17 | 18 | if (@ARGV < 2) { 19 | usage(); 20 | } 21 | 22 | my $dst = pop; 23 | 24 | my @src = @ARGV; 25 | 26 | my $target_dir; 27 | 28 | if (@src > 1 || $dst =~ m{/$}) { 29 | $target_dir = $dst; 30 | 31 | } elsif (-d $dst) { 32 | $target_dir = $dst; 33 | 34 | } elsif ($dst =~ m{(.+)/}) { 35 | $target_dir = $1; 36 | 37 | } else { 38 | $target_dir = '.'; 39 | } 40 | 41 | if (!-d $target_dir) { 42 | shell("mkdir -p $target_dir"); 43 | } 44 | 45 | if (-f $dst) { 46 | shell("rm $dst"); 47 | 48 | } else { 49 | for my $f (@src) { 50 | if (-f $f) { 51 | (my $name = $f) =~ s{.*/}{}g; 52 | my $target = "$target_dir/$name"; 53 | if (-f $target) { 54 | shell("rm $target"); 55 | } 56 | } 57 | } 58 | } 59 | 60 | shell("cp -r @src $dst"); 61 | 62 | if (-f $dst) { 63 | if (defined $mode) { 64 | chmod oct($mode), $dst or 65 | die "failed to change mode of $dst to $mode.\n"; 66 | } 67 | 68 | exit; 69 | } 70 | 71 | for my $src (@src) { 72 | my $name; 73 | 74 | if ($src =~ m{/([^/]+)$}) { 75 | $name = $1; 76 | 77 | } else { 78 | $name = $src; 79 | } 80 | 81 | if (defined $mode) { 82 | my $target = "$target_dir/$name"; 83 | chmod oct($mode), $target or 84 | die "failed to change mode of $target to $mode.\n"; 85 | } 86 | } 87 | 88 | sub usage { 89 | die "Usage: install [-d] [-m ] ... \n"; 90 | } 91 | 92 | sub shell { 93 | my $cmd = shift; 94 | #warn $cmd; 95 | system($cmd) == 0 or 96 | die "failed to run command $cmd\n"; 97 | } 98 | 99 | -------------------------------------------------------------------------------- /vanilla/spec/init.lua: -------------------------------------------------------------------------------- 1 | -- vanilla 2 | local helpers = LoadV "vanilla.v.libs.utils" 3 | function sprint_r( ... ) 4 | return helpers.sprint_r(...) 5 | end 6 | 7 | function lprint_r( ... ) 8 | local rs = sprint_r(...) 9 | print(rs) 10 | end 11 | 12 | function print_r( ... ) 13 | local rs = sprint_r(...) 14 | ngx.say(rs) 15 | end -------------------------------------------------------------------------------- /vanilla/spec/runner.lua: -------------------------------------------------------------------------------- 1 | -- vanilla 2 | LoadV 'vanilla.spec.init' 3 | 4 | -- add integration runner 5 | local IntegrationRunner = LoadV 'vanilla.spec.runners.integration' 6 | 7 | -- helpers 8 | function cgi(request) 9 | return IntegrationRunner.cgi(request) 10 | end 11 | -------------------------------------------------------------------------------- /vanilla/spec/runners/integration.lua: -------------------------------------------------------------------------------- 1 | -- dep 2 | local http = require 'socket.http' 3 | local url = require 'socket.url' 4 | local json = require 'cjson' 5 | 6 | local IntegrationRunner = {} 7 | 8 | -- Code portion taken from: 9 | -- 10 | function IntegrationRunner.encode_table(args) 11 | if args == nil or next(args) == nil then return "" end 12 | 13 | local strp = "" 14 | for key, vals in pairs(args) do 15 | if type(vals) ~= "table" then vals = {vals} end 16 | 17 | for i, val in ipairs(vals) do 18 | strp = strp .. "&" .. key .. "=" .. url.escape(val) 19 | end 20 | end 21 | 22 | return string.sub(strp, 2) 23 | end 24 | 25 | local function ensure_content_length(request) 26 | if request.headers == nil then request.headers = {} end 27 | if request.headers["content-length"] == nil and request.headers["Content-Length"] == nil then 28 | if request.body ~= nil then 29 | request.headers["Content-Length"] = request.body:len() 30 | else 31 | request.headers["Content-Length"] = 0 32 | end 33 | end 34 | return request 35 | end 36 | 37 | local function hit_server(request) 38 | local full_url = url.build({ 39 | scheme = 'http', 40 | host = '127.0.0.1', 41 | port = 80, 42 | path = request.path, 43 | query = IntegrationRunner.encode_table(request.uri_params) 44 | }) 45 | 46 | local response_body = {} 47 | local ok, response_status, response_headers = http.request({ 48 | method = request.method, 49 | url = full_url, 50 | source = ltn12.source.string(request.body), 51 | headers = request.headers, 52 | sink = ltn12.sink.table(response_body), 53 | redirect = false 54 | }) 55 | 56 | response_body = table.concat(response_body, "") 57 | return ok, response_status, response_headers, response_body 58 | end 59 | 60 | function IntegrationRunner.cgi(request) 61 | local ResponseSpec = LoadV 'vanilla.spec.runners.response' 62 | 63 | -- convert body to JSON request 64 | if request.body ~= nil then 65 | request.body = json.encode(request.body) 66 | end 67 | 68 | -- ensure content-length is set 69 | request = ensure_content_length(request) 70 | 71 | -- start nginx 72 | 73 | -- hit server 74 | local ok, response_status, response_headers, response_body = hit_server(request) 75 | 76 | -- stop nginx 77 | 78 | if ok == nil then error("An error occurred while connecting to the test server.") end 79 | 80 | -- build response object and return 81 | local response = ResponseSpec.new({ 82 | status = response_status, 83 | headers = response_headers, 84 | body = response_body 85 | }) 86 | 87 | return response 88 | end 89 | 90 | return IntegrationRunner 91 | -------------------------------------------------------------------------------- /vanilla/spec/runners/response.lua: -------------------------------------------------------------------------------- 1 | -- dep 2 | local json = require 'cjson' 3 | 4 | 5 | local ResponseSpec = {} 6 | ResponseSpec.__index = ResponseSpec 7 | 8 | 9 | local function trim(str) 10 | return str:match'^%s*(.*%S)' or '' 11 | end 12 | 13 | function ResponseSpec.new(options) 14 | options = options or {} 15 | 16 | -- body 17 | local json_body = {} 18 | local ok 19 | if options.body ~= nil and trim(options.body) ~= "" then 20 | ok, json_body = pcall(function() return json.decode(options.body) end) 21 | if ok == false then json_body = nil end 22 | end 23 | 24 | -- init instance 25 | local instance = { 26 | status = options.status, 27 | headers = options.headers or {}, 28 | body = json_body, 29 | body_raw = options.body 30 | } 31 | setmetatable(instance, ResponseSpec) 32 | return instance 33 | end 34 | 35 | return ResponseSpec 36 | -------------------------------------------------------------------------------- /vanilla/sys/config.lua: -------------------------------------------------------------------------------- 1 | -- perf 2 | local helpers = require 'vanilla.v.libs.utils' 3 | local Registry = require('vanilla.v.registry'):new('sys_env') 4 | local ogetenv = os.getenv 5 | 6 | local Sysconf = {} 7 | 8 | -- version 9 | Sysconf.version = '0.1.0-rc7' 10 | 11 | -- environment 12 | -- Sysconf.env = ogetenv("VA_ENV") or 'development' 13 | Sysconf.env = Registry['VA_ENV'] or 'development' 14 | 15 | -- directories 16 | Sysconf.app_dirs = { 17 | tmp = 'tmp', 18 | logs = 'logs' 19 | } 20 | 21 | if Sysconf.env == 'development' or Sysconf.env == 'test' then 22 | function sprint_r( ... ) 23 | return helpers.sprint_r(...) 24 | end 25 | 26 | function lprint_r( ... ) 27 | local rs = sprint_r(...) 28 | print(rs) 29 | end 30 | 31 | function print_r( ... ) 32 | local rs = sprint_r(...) 33 | ngx.say(rs) 34 | end 35 | 36 | function err_log(msg) 37 | ngx.log(ngx.ERR, "===zjdebug" .. msg .. "===") 38 | end 39 | end 40 | 41 | return Sysconf -------------------------------------------------------------------------------- /vanilla/sys/console.lua: -------------------------------------------------------------------------------- 1 | local Console = {} 2 | 3 | function Console.start() 4 | local lua = 'lua' 5 | -- if VANILLA_JIT_BIN ~= nil then 6 | -- lua = VANILLA_JIT_BIN 7 | -- end 8 | local cmd = lua .. " -i -e \"_PROMPT='v-console>';package.path='" .. package.path 9 | .. "' package.cpath='" .. package.cpath 10 | .. "' require 'vanilla.sys.config';require 'vanilla.v.libs.utils'\"" 11 | os.execute(cmd) 12 | end 13 | 14 | return Console -------------------------------------------------------------------------------- /vanilla/sys/nginx/config.lua: -------------------------------------------------------------------------------- 1 | -- vanilla 2 | local helpers = require 'vanilla.v.libs.utils' 3 | 4 | -- perf 5 | local pairs = pairs 6 | local ogetenv = os.getenv 7 | local app_run_evn = ogetenv("VA_ENV") or 'development' 8 | 9 | local va_ngx_conf = {} 10 | va_ngx_conf.common = { 11 | VA_ENV = app_run_evn, 12 | } 13 | 14 | if VANILLA_NGX_PATH ~= nil then 15 | va_ngx_conf.common.NGX_PATH = VANILLA_NGX_PATH 16 | end 17 | 18 | va_ngx_conf.env = {} 19 | va_ngx_conf.env.development = { 20 | LUA_CODE_CACHE = false, 21 | PORT = 9110 22 | } 23 | 24 | va_ngx_conf.env.test = { 25 | LUA_CODE_CACHE = true, 26 | PORT = 9111 27 | } 28 | 29 | va_ngx_conf.env.production = { 30 | LUA_CODE_CACHE = true, 31 | PORT = 80 32 | } 33 | 34 | local function getNgxConf(conf_arr) 35 | if conf_arr['common'] ~= nil then 36 | local common_conf = conf_arr['common'] 37 | if common_conf['BASE_LIBRARY'] ~= nil then 38 | package.path = package.path .. ';' .. common_conf['BASE_LIBRARY'] .. '/?.lua;' 39 | .. common_conf['BASE_LIBRARY'] .. '/?/init.lua' 40 | package.cpath = package.cpath .. ';' .. common_conf['BASE_LIBRARY'] .. '/?.so' 41 | end 42 | local env_conf = conf_arr['env'][app_run_evn] 43 | for directive, info in pairs(common_conf) do 44 | env_conf[directive] = info 45 | end 46 | return env_conf 47 | elseif conf_arr['env'] ~= nil then 48 | return conf_arr['env'][app_run_evn] 49 | end 50 | return {} 51 | end 52 | 53 | local function buildConf() 54 | local get_app_va_ngx_conf = helpers.try_require('config.nginx', {}) 55 | local app_ngx_conf = getNgxConf(get_app_va_ngx_conf) 56 | local sys_ngx_conf = getNgxConf(va_ngx_conf) 57 | if app_ngx_conf ~= nil then 58 | for k,v in pairs(app_ngx_conf) do 59 | sys_ngx_conf[k] = v 60 | end 61 | end 62 | return sys_ngx_conf 63 | end 64 | 65 | local ngx_directive_handle = require('vanilla.sys.nginx.directive'):new(app_run_evn) 66 | local ngx_directives = ngx_directive_handle:directiveSets() 67 | 68 | local VaNgxConf = {} 69 | 70 | local ngx_run_conf = buildConf() 71 | 72 | for directive, func in pairs(ngx_directives) do 73 | if type(func) == 'function' then 74 | local func_rs = func(ngx_directive_handle, ngx_run_conf[directive]) 75 | if func_rs ~= false then 76 | VaNgxConf[directive] = func_rs 77 | end 78 | else 79 | VaNgxConf[directive] = ngx_run_conf[directive] 80 | end 81 | end 82 | 83 | return VaNgxConf -------------------------------------------------------------------------------- /vanilla/sys/nginx/directive.lua: -------------------------------------------------------------------------------- 1 | package.path = './application/?.lua;./application/library/?.lua;./application/?/init.lua;' .. package.path 2 | package.cpath = './application/library/?.so;' .. package.cpath 3 | 4 | -- convert true|false to on|off 5 | local function convert_boolean_to_onoff(value) 6 | if value == true then value = 'on' else value = 'off' end 7 | return value 8 | end 9 | 10 | local Directive = {} 11 | 12 | function Directive:new(env) 13 | local run_env = 'production' 14 | if env ~= nil then run_env = env end 15 | local instance = { 16 | run_env = run_env, 17 | directiveSets = self.directiveSets 18 | } 19 | setmetatable(instance, Directive) 20 | return instance 21 | end 22 | 23 | function Directive:luaPackagePath(lua_path) 24 | local path = package.path 25 | if lua_path ~= nil then path = lua_path .. path end 26 | local res = [[lua_package_path "]] .. path .. [[;;";]] 27 | return res 28 | end 29 | 30 | function Directive:luaPackageCpath(lua_cpath) 31 | local path = package.cpath 32 | if lua_cpath ~= nil then path = lua_cpath .. path end 33 | local res = [[lua_package_cpath "]] .. path .. [[;;";]] 34 | return res 35 | end 36 | 37 | function Directive:codeCache(bool_var) 38 | local res = [[lua_code_cache ]] .. convert_boolean_to_onoff(bool_var) .. [[;]] 39 | return res 40 | end 41 | 42 | function Directive:luaSharedDict( lua_lib ) 43 | local ok, sh_dict_conf_or_error = pcall(function() return require(lua_lib) end) 44 | if ok == false then 45 | return false 46 | end 47 | local res = '' 48 | if sh_dict_conf_or_error ~= nil then 49 | for name,size in pairs(sh_dict_conf_or_error) do 50 | res = res .. [[lua_shared_dict ]] .. name .. ' ' .. size .. ';' 51 | end 52 | end 53 | return res 54 | end 55 | 56 | function Directive:initByLua(lua_lib) 57 | if lua_lib == nil then return '' end 58 | local res = [[init_by_lua require(']] .. lua_lib .. [['):run();]] 59 | return res 60 | end 61 | 62 | function Directive:initByLuaFile(lua_file) 63 | if lua_file == nil then return '' end 64 | local res = [[init_by_lua_file ]] .. lua_file .. [[;]] 65 | return res 66 | end 67 | 68 | function Directive:initWorkerByLua(lua_lib) 69 | if lua_lib == nil then return '' end 70 | local res = [[init_worker_by_lua require(']] .. lua_lib .. [['):run();]] 71 | return res 72 | end 73 | 74 | function Directive:initWorkerByLuaFile(lua_file) 75 | if lua_file == nil then return '' end 76 | local res = [[init_worker_by_lua_file ]] .. lua_file .. [[;]] 77 | return res 78 | end 79 | 80 | function Directive:setByLua(lua_lib) 81 | if lua_lib == nil then return '' end 82 | local res = [[set_by_lua require(']] .. lua_lib .. [[');]] 83 | return res 84 | end 85 | 86 | function Directive:setByLuaFile(lua_file) 87 | if lua_file == nil then return '' end 88 | local res = [[set_by_lua_file ]] .. lua_file .. [[;]] 89 | return res 90 | end 91 | 92 | function Directive:rewriteByLua(lua_lib) 93 | if lua_lib == nil then return '' end 94 | local res = [[rewrite_by_lua require(']] .. lua_lib .. [['):run();]] 95 | return res 96 | end 97 | 98 | function Directive:rewriteByLuaFile(lua_file) 99 | if lua_file == nil then return '' end 100 | local res = [[rewrite_by_lua_file ]] .. lua_file .. [[;]] 101 | return res 102 | end 103 | 104 | function Directive:accessByLua(lua_lib) 105 | if lua_lib == nil then return '' end 106 | local res = [[access_by_lua require(']] .. lua_lib .. [['):run();]] 107 | return res 108 | end 109 | 110 | function Directive:accessByLuaFile(lua_file) 111 | if lua_file == nil then return '' end 112 | local res = [[access_by_lua_file ]] .. lua_file .. [[;]] 113 | return res 114 | end 115 | 116 | function Directive:contentByLua(lua_lib) 117 | if lua_lib == nil then return '' end 118 | -- local res = [[content_by_lua require(']] .. lua_lib .. [['):run();]] 119 | local res = [[location / { 120 | content_by_lua require(']] .. lua_lib .. [['):run(); 121 | }]] 122 | return res 123 | end 124 | 125 | function Directive:contentByLuaFile(lua_file) 126 | if lua_file == nil then return '' end 127 | local res = [[location / { 128 | content_by_lua_file ]] .. lua_file .. [[; 129 | }]] 130 | return res 131 | end 132 | 133 | function Directive:headerFilterByLua(lua_lib) 134 | if lua_lib == nil then return '' end 135 | local res = [[header_filter_by_lua require(']] .. lua_lib .. [['):run();]] 136 | return res 137 | end 138 | 139 | function Directive:headerFilterByLuaFile(lua_file) 140 | if lua_file == nil then return '' end 141 | local res = [[header_filter_by_lua_file ]] .. lua_file .. [[;]] 142 | return res 143 | end 144 | 145 | function Directive:bodyFilterByLua(lua_lib) 146 | if lua_lib == nil then return '' end 147 | local res = [[body_filter_by_lua require(']] .. lua_lib .. [['):run();]] 148 | return res 149 | end 150 | 151 | function Directive:bodyFilterByLuaFile(lua_file) 152 | if lua_file == nil then return '' end 153 | local res = [[body_filter_by_lua_file ]] .. lua_file .. [[;]] 154 | return res 155 | end 156 | 157 | function Directive:logByLua(lua_lib) 158 | if lua_lib == nil then return '' end 159 | local res = [[log_by_lua require(']] .. lua_lib .. [['):run();]] 160 | return res 161 | end 162 | 163 | function Directive:logByLuaFile(lua_file) 164 | if lua_file == nil then return '' end 165 | local res = [[log_by_lua_file ]] .. lua_file .. [[;]] 166 | return res 167 | end 168 | 169 | function Directive:directiveSets() 170 | return { 171 | ['VA_ENV'] = self.run_env, 172 | ['PORT'] = 80, 173 | ['NGX_PATH'] = '', 174 | ['LUA_PACKAGE_PATH'] = Directive.luaPackagePath, 175 | ['LUA_PACKAGE_CPATH'] = Directive.luaPackageCpath, 176 | ['LUA_CODE_CACHE'] = Directive.codeCache, 177 | -- lua_shared_dict falcon_share 100m; 178 | ['LUA_SHARED_DICT'] = Directive.luaSharedDict, 179 | ['INIT_BY_LUA'] = Directive.initByLua, 180 | ['INIT_BY_LUA_FILE'] = Directive.initByLuaFile, 181 | ['INIT_WORKER_BY_LUA'] = Directive.initWorkerByLua, 182 | ['INIT_WORKER_BY_LUA_FILE'] = Directive.initWorkerByLuaFile, 183 | ['SET_BY_LUA'] = Directive.setByLua, 184 | ['SET_BY_LUA_FILE'] = Directive.setByLuaFile, 185 | ['REWRITE_BY_LUA'] = Directive.rewriteByLua, 186 | ['REWRITE_BY_LUA_FILE'] = Directive.rewriteByLuaFile, 187 | ['ACCESS_BY_LUA'] = Directive.accessByLua, 188 | ['ACCESS_BY_LUA_FILE'] = Directive.accessByLuaFile, 189 | ['CONTENT_BY_LUA'] = Directive.contentByLua, 190 | ['CONTENT_BY_LUA_FILE'] = Directive.contentByLuaFile, 191 | ['HEADER_FILTER_BY_LUA'] = Directive.headerFilterByLua, 192 | ['HEADER_FILTER_BY_LUA_FILE'] = Directive.headerFilterByLuaFile, 193 | ['BODY_FILTER_BY_LUA'] = Directive.bodyFilterByLua, 194 | ['BODY_FILTER_BY_LUA_FILE'] = Directive.bodyFilterByLuaFile, 195 | ['LOG_BY_LUA'] = Directive.logByLua, 196 | ['LOG_BY_LUA_FILE'] = Directive.logByLuaFile 197 | } 198 | end 199 | 200 | return Directive 201 | 202 | --[[ 203 | 204 | {{LUA_PACKAGE_PATH}} 205 | {{LUA_PACKAGE_CPATH}} 206 | {{LUA_CODE_CACHE}} 207 | {{LUA_SHARED_DICT}} 208 | 209 | 210 | {{INIT_BY_LUA}} 211 | {{INIT_BY_LUA_FILE}} 212 | {{INIT_WORKER_BY_LUA}} 213 | {{INIT_WORKER_BY_LUA_FILE}} 214 | {{REWRITE_BY_LUA}} 215 | {{REWRITE_BY_LUA_FILE}} 216 | {{ACCESS_BY_LUA}} 217 | {{ACCESS_BY_LUA_FILE}} 218 | {{HEADER_FILTER_BY_LUA}} 219 | {{HEADER_FILTER_BY_LUA_FILE}} 220 | {{BODY_FILTER_BY_LUA}} 221 | {{BODY_FILTER_BY_LUA_FILE}} 222 | {{LOG_BY_LUA}} 223 | {{LOG_BY_LUA_FILE}} 224 | {{SET_BY_LUA}} 225 | {{SET_BY_LUA_FILE}} 226 | {{CONTENT_BY_LUA}} 227 | {{CONTENT_BY_LUA_FILE}} 228 | ]] -------------------------------------------------------------------------------- /vanilla/sys/nginx/handle.lua: -------------------------------------------------------------------------------- 1 | local va_conf = LoadV 'vanilla.sys.config' 2 | 3 | local function create_dirs(necessary_dirs) 4 | for _, dir in pairs(necessary_dirs) do 5 | os.execute("mkdir -p " .. dir .. " > /dev/null") 6 | end 7 | end 8 | 9 | local function create_nginx_conf(nginx_conf_file_path, nginx_conf_content) 10 | local fw = io.open(nginx_conf_file_path, "w") 11 | fw:write(nginx_conf_content) 12 | fw:close() 13 | end 14 | 15 | local function remove_nginx_conf(nginx_conf_file_path) 16 | os.remove(nginx_conf_file_path) 17 | end 18 | 19 | local function nginx_command(env, nginx_conf_file_path, nginx_signal) 20 | local devnull_logs = "" 21 | if V_TRACE == false then devnull_logs = " 2>/dev/null" end 22 | 23 | local env_cmd = "" 24 | local nginx = "" 25 | if VANILLA_NGX_PATH ~= nil then 26 | nginx = VANILLA_NGX_PATH .. "/sbin/nginx " 27 | else 28 | nginx = "nginx " 29 | end 30 | if env ~= nil then env_cmd = "-g \"env VA_ENV=" .. env .. ";\"" end 31 | local cmd = nginx .. nginx_signal .. " " .. env_cmd .. " -p `pwd`/ -c " .. nginx_conf_file_path .. devnull_logs 32 | 33 | if V_TRACE == true then 34 | print(cmd) 35 | end 36 | 37 | return os.execute(cmd) 38 | end 39 | 40 | local function start_nginx(env, nginx_conf_file_path) 41 | return nginx_command(env, nginx_conf_file_path, '') 42 | end 43 | 44 | local function stop_nginx(env, nginx_conf_file_path) 45 | return nginx_command(env, nginx_conf_file_path, '-s stop') 46 | end 47 | 48 | local function reload_nginx(env, nginx_conf_file_path) 49 | return nginx_command(env, nginx_conf_file_path, '-s reload') 50 | end 51 | 52 | 53 | local NginxHandle = {} 54 | NginxHandle.__index = NginxHandle 55 | 56 | function NginxHandle.new(nginx_conf_content, nginx_conf_file_path) 57 | local necessary_dirs = va_conf.app_dirs 58 | 59 | local instance = { 60 | nginx_conf_content = nginx_conf_content, 61 | nginx_conf_file_path = nginx_conf_file_path, 62 | necessary_dirs = necessary_dirs 63 | } 64 | setmetatable(instance, NginxHandle) 65 | return instance 66 | end 67 | 68 | function NginxHandle:start(env) 69 | create_dirs(self.necessary_dirs) 70 | create_nginx_conf(self.nginx_conf_file_path, self.nginx_conf_content) 71 | 72 | return start_nginx(env, self.nginx_conf_file_path) 73 | end 74 | 75 | function NginxHandle:stop(env) 76 | result = stop_nginx(env, self.nginx_conf_file_path) 77 | remove_nginx_conf(self.nginx_conf_file_path) 78 | 79 | return result 80 | end 81 | 82 | function NginxHandle:reload(env) 83 | remove_nginx_conf(self.nginx_conf_file_path) 84 | create_dirs(self.necessary_dirs) 85 | create_nginx_conf(self.nginx_conf_file_path, self.nginx_conf_content) 86 | 87 | return reload_nginx(env, self.nginx_conf_file_path) 88 | end 89 | 90 | 91 | return NginxHandle -------------------------------------------------------------------------------- /vanilla/sys/vanilla.lua: -------------------------------------------------------------------------------- 1 | -- dep 2 | local ansicolors = LoadV 'vanilla.v.libs.ansicolors' 3 | 4 | -- perf 5 | local error = error 6 | local sgmatch = string.gmatch --cli didn't have ngx.re API 7 | 8 | -- vanilla 9 | local va_conf = LoadV 'vanilla.sys.config' 10 | local ngx_handle = LoadV 'vanilla.sys.nginx.handle' 11 | local ngx_config = LoadV 'vanilla.sys.nginx.config' 12 | local helpers = LoadV 'vanilla.v.libs.utils' 13 | 14 | -- settings 15 | local nginx_conf_source = 'config/nginx.conf' 16 | 17 | local Vanilla = {} 18 | 19 | function Vanilla.nginx_conf_content() 20 | -- read nginx.conf file 21 | local nginx_conf_template = helpers.read_file(nginx_conf_source) 22 | 23 | -- append notice 24 | nginx_conf_template = [[ 25 | # ===================================================================== # 26 | # THIS FILE IS AUTO GENERATED. DO NOT MODIFY. # 27 | # IF YOU CAN SEE IT, THERE PROBABLY IS A RUNNING SERVER REFERENCING IT. # 28 | # ===================================================================== # 29 | 30 | ]] .. nginx_conf_template 31 | 32 | local match = {} 33 | local tmp = 1 34 | for v in sgmatch(nginx_conf_template , '{{(.-)}}') do 35 | match[tmp] = v 36 | tmp = tmp +1 37 | end 38 | 39 | for _, directive in ipairs(match) do 40 | if ngx_config[directive] ~= nil then 41 | nginx_conf_template = string.gsub(nginx_conf_template, '{{' .. directive .. '}}', ngx_config[directive]) 42 | else 43 | nginx_conf_template = string.gsub(nginx_conf_template, '{{' .. directive .. '}}', '#' .. directive) 44 | end 45 | end 46 | return nginx_conf_template 47 | end 48 | 49 | function base_launcher() 50 | return ngx_handle.new( 51 | Vanilla.nginx_conf_content(), 52 | va_conf.app_dirs.tmp .. "/" .. va_conf.env .. "-nginx.conf" 53 | ) 54 | end 55 | 56 | function Vanilla.start(env) 57 | if env == nil then env = va_conf.env end 58 | -- init base_launcher 59 | local ok, base_launcher = pcall(function() return base_launcher() end) 60 | 61 | if ok == false then 62 | print(ansicolors("%{red}ERROR:%{reset} Cannot initialize launcher: " .. base_launcher)) 63 | return 64 | end 65 | 66 | result = base_launcher:start(env) 67 | 68 | if result == 0 then 69 | if va_conf.env ~= 'test' then 70 | print(ansicolors("Vanilla app in %{green}" .. va_conf.env .. "%{reset} was succesfully started on port " .. ngx_config.PORT .. ".")) 71 | end 72 | else 73 | print(ansicolors("%{red}ERROR:%{reset} Could not start Vanilla app on port " .. ngx_config.PORT .. " (is it running already?).")) 74 | end 75 | end 76 | 77 | function Vanilla.stop(env) 78 | if env == nil then env = va_conf.env end 79 | -- init base_launcher 80 | local base_launcher = base_launcher() 81 | 82 | result = base_launcher:stop(env) 83 | 84 | if va_conf.env ~= 'test' then 85 | if result == 0 then 86 | print(ansicolors("Vanilla app in %{green}" .. va_conf.env .. "%{reset} was succesfully stopped.")) 87 | else 88 | print(ansicolors("%{red}ERROR:%{reset} Could not stop Vanilla app (are you sure it is running?).")) 89 | end 90 | end 91 | end 92 | 93 | function Vanilla.reload(env) 94 | if env == nil then env = va_conf.env end 95 | local base_launcher = base_launcher() 96 | 97 | result = base_launcher:reload(env) 98 | 99 | if va_conf.env ~= 'test' then 100 | if result == 0 then 101 | print(ansicolors("Vanilla app in %{green}" .. va_conf.env .. "%{reset} was succesfully reloaded.")) 102 | else 103 | print(ansicolors("%{red}ERROR:%{reset} Could not reload Vanilla app (are you sure it is running?).")) 104 | end 105 | end 106 | end 107 | 108 | 109 | return Vanilla -------------------------------------------------------------------------------- /vanilla/sys/waf/acc.lua: -------------------------------------------------------------------------------- 1 | local utils = require'vanilla.v.libs.utils' 2 | 3 | local app_waf_conf = utils.lpcall(function() return require('config.waf') end) 4 | local waf_conf = utils.lpcall(function() return LoadV('vanilla.sys.waf.config') end) 5 | if app_waf_conf ~= nil then 6 | for k,v in pairs(app_waf_conf) do 7 | waf_conf[k] = app_waf_conf[k] 8 | end 9 | end 10 | 11 | local match = string.match 12 | local ngxmatch=ngx.re.match 13 | local unescape=ngx.unescape_uri 14 | local get_headers = ngx.req.get_headers 15 | local optionIsOn = function (options) return options == "on" and true or false end 16 | local logpath = waf_conf.logdir 17 | local rulepath = waf_conf.RulePath 18 | local ipWhitelist = waf_conf.ipWhitelist 19 | local ipBlocklist = waf_conf.ipBlocklist 20 | local UrlDeny = optionIsOn(waf_conf.UrlDeny) 21 | local PostCheck = optionIsOn(waf_conf.postMatch) 22 | local CookieCheck = optionIsOn(waf_conf.cookieMatch) 23 | local WhiteCheck = optionIsOn(waf_conf.whiteModule) 24 | local PathInfoFix = optionIsOn(waf_conf.PathInfoFix) 25 | local attacklog = optionIsOn(waf_conf.attacklog) 26 | local CCDeny = optionIsOn(waf_conf.CCDeny) 27 | local Redirect=optionIsOn(waf_conf.Redirect) 28 | 29 | local function getClientIp() 30 | IP = ngx.req.get_headers()["X-Real-IP"] 31 | if IP == nil then 32 | IP = ngx.var.remote_addr 33 | end 34 | if IP == nil then 35 | IP = "unknown" 36 | end 37 | return IP 38 | end 39 | 40 | local function write(logfile,msg) 41 | local fd = io.open(logfile,"ab") 42 | if fd == nil then return end 43 | fd:write(msg) 44 | fd:flush() 45 | fd:close() 46 | end 47 | 48 | local function log(method,url,data,ruletag) 49 | if attacklog then 50 | local realIp = getClientIp() 51 | local ua = ngx.var.http_user_agent 52 | local servername=ngx.var.server_name 53 | local time=ngx.localtime() 54 | if ua then 55 | line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" \""..ua.."\" \""..ruletag.."\"\n" 56 | else 57 | line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" - \""..ruletag.."\"\n" 58 | end 59 | local filename = logpath..'/'..servername.."_"..ngx.today().."_sec.log" 60 | write(filename,line) 61 | end 62 | end 63 | 64 | local function read_rule(var) 65 | file = io.open(rulepath..'/'..var,"r") 66 | if file==nil then 67 | return 68 | end 69 | t = {} 70 | for line in file:lines() do 71 | table.insert(t,line) 72 | end 73 | file:close() 74 | return(t) 75 | end 76 | 77 | local urlrules=read_rule('url') 78 | local argsrules=read_rule('args') 79 | local uarules=read_rule('user-agent') 80 | local wturlrules=read_rule('whiteurl') 81 | local postrules=read_rule('post') 82 | local ckrules=read_rule('cookie') 83 | 84 | local function whiteurl() 85 | if WhiteCheck then 86 | if wturlrules ~=nil then 87 | for _,rule in pairs(wturlrules) do 88 | if ngxmatch(ngx.var.uri,rule,"isjo") then 89 | return true 90 | end 91 | end 92 | end 93 | end 94 | return false 95 | end 96 | 97 | local function fileExtCheck(ext) 98 | local items = Set(black_fileExt) 99 | ext=string.lower(ext) 100 | if ext then 101 | for rule in pairs(items) do 102 | if ngx.re.match(ext,rule,"isjo") then 103 | log('POST',ngx.var.request_uri,"-","file attack with ext "..ext) 104 | say_html() 105 | end 106 | end 107 | end 108 | return false 109 | end 110 | 111 | local function Set (list) 112 | local set = {} 113 | for _, l in ipairs(list) do set[l] = true end 114 | return set 115 | end 116 | 117 | local function say_html() 118 | if Redirect then 119 | ngx.header.content_type = "text/html" 120 | ngx.header.Power_by = "Vanilla-idevz/vanilla" 121 | ngx.status = ngx.HTTP_FORBIDDEN 122 | ngx.say(waf_conf.html) 123 | ngx.eof() 124 | -- ngx.exit(ngx.status) 125 | end 126 | end 127 | 128 | local function args() 129 | for _,rule in pairs(argsrules) do 130 | local args = ngx.req.get_uri_args() 131 | for key, val in pairs(args) do 132 | if type(val)=='table' then 133 | if val ~= false then 134 | data=table.concat(val, " ") 135 | end 136 | else 137 | data=val 138 | end 139 | if data and type(data) ~= "boolean" and rule ~="" and ngxmatch(unescape(data),rule,"isjo") then 140 | log('GET',ngx.var.request_uri,"-",rule) 141 | say_html() 142 | return true 143 | end 144 | end 145 | end 146 | return false 147 | end 148 | 149 | local function url() 150 | if UrlDeny then 151 | for _,rule in pairs(urlrules) do 152 | if rule ~="" and ngxmatch(ngx.var.request_uri,rule,"isjo") then 153 | log('GET',ngx.var.request_uri,"-",rule) 154 | say_html() 155 | return true 156 | end 157 | end 158 | end 159 | return false 160 | end 161 | 162 | local function ua() 163 | local ua = ngx.var.http_user_agent 164 | if ua ~= nil then 165 | for _,rule in pairs(uarules) do 166 | if rule ~="" and ngxmatch(ua,rule,"isjo") then 167 | log('UA',ngx.var.request_uri,"-",rule) 168 | say_html() 169 | return true 170 | end 171 | end 172 | end 173 | return false 174 | end 175 | 176 | local function body(data) 177 | for _,rule in pairs(postrules) do 178 | if rule ~="" and data~="" and ngxmatch(unescape(data),rule,"isjo") then 179 | log('POST',ngx.var.request_uri,data,rule) 180 | say_html() 181 | return true 182 | end 183 | end 184 | return false 185 | end 186 | 187 | local function cookie() 188 | local ck = ngx.var.http_cookie 189 | if CookieCheck and ck then 190 | for _,rule in pairs(ckrules) do 191 | if rule ~="" and ngxmatch(ck,rule,"isjo") then 192 | log('Cookie',ngx.var.request_uri,"-",rule) 193 | say_html() 194 | return true 195 | end 196 | end 197 | end 198 | return false 199 | end 200 | 201 | local function denycc() 202 | if CCDeny then 203 | local uri=ngx.var.uri 204 | CCcount=tonumber(string.match(CCrate,'(.*)/')) 205 | CCseconds=tonumber(string.match(CCrate,'/(.*)')) 206 | local token = getClientIp()..uri 207 | local limit = ngx.shared.limit 208 | local req,_=limit:get(token) 209 | if req then 210 | if req > CCcount then 211 | ngx.exit(503) 212 | return true 213 | else 214 | limit:incr(token,1) 215 | end 216 | else 217 | limit:set(token,1,CCseconds) 218 | end 219 | end 220 | return false 221 | end 222 | 223 | local function get_boundary() 224 | local header = get_headers()["content-type"] 225 | if not header then 226 | return nil 227 | end 228 | 229 | if type(header) == "table" then 230 | header = header[1] 231 | end 232 | 233 | local m = match(header, ";%s*boundary=\"([^\"]+)\"") 234 | if m then 235 | return m 236 | end 237 | 238 | return match(header, ";%s*boundary=([^\",;]+)") 239 | end 240 | 241 | local function whiteip() 242 | if next(ipWhitelist) ~= nil then 243 | for _,ip in pairs(ipWhitelist) do 244 | if getClientIp()==ip then 245 | return true 246 | end 247 | end 248 | end 249 | return false 250 | end 251 | 252 | local function blockip() 253 | if next(ipBlocklist) ~= nil then 254 | for _,ip in pairs(ipBlocklist) do 255 | if getClientIp()==ip then 256 | ngx.exit(403) 257 | return true 258 | end 259 | end 260 | end 261 | return false 262 | end 263 | 264 | local content_length=tonumber(ngx.req.get_headers()['content-length']) 265 | local method=ngx.req.get_method() 266 | local ngxmatch=ngx.re.match 267 | 268 | local Acc = {} 269 | 270 | function Acc:check() 271 | if whiteip() then 272 | elseif blockip() then 273 | elseif denycc() then 274 | elseif ngx.var.http_Acunetix_Aspect then 275 | ngx.exit(444) 276 | elseif ngx.var.http_X_Scan_Memo then 277 | ngx.exit(444) 278 | elseif whiteurl() then 279 | elseif ua() then 280 | elseif url() then 281 | elseif args() then 282 | elseif cookie() then 283 | elseif PostCheck then 284 | if method=="POST" then 285 | local boundary = get_boundary() 286 | if boundary then 287 | local len = string.len 288 | local sock, err = ngx.req.socket() 289 | if not sock then 290 | return 291 | end 292 | ngx.req.init_body(128 * 1024) 293 | sock:settimeout(0) 294 | local content_length = nil 295 | content_length=tonumber(ngx.req.get_headers()['content-length']) 296 | local chunk_size = 4096 297 | if content_length < chunk_size then 298 | chunk_size = content_length 299 | end 300 | local size = 0 301 | while size < content_length do 302 | local data, err, partial = sock:receive(chunk_size) 303 | data = data or partial 304 | if not data then 305 | return 306 | end 307 | ngx.req.append_body(data) 308 | if body(data) then 309 | return true 310 | end 311 | size = size + len(data) 312 | local m = ngxmatch(data,[[Content-Disposition: form-data;(.+)filename="(.+)\\.(.*)"]],'ijo') 313 | if m then 314 | fileExtCheck(m[3]) 315 | filetranslate = true 316 | else 317 | if ngxmatch(data,"Content-Disposition:",'isjo') then 318 | filetranslate = false 319 | end 320 | if filetranslate==false then 321 | if body(data) then 322 | return true 323 | end 324 | end 325 | end 326 | local less = content_length - size 327 | if less < chunk_size then 328 | chunk_size = less 329 | end 330 | end 331 | ngx.req.finish_body() 332 | else 333 | ngx.req.read_body() 334 | local args = ngx.req.get_post_args() 335 | if not args then 336 | return 337 | end 338 | for key, val in pairs(args) do 339 | if type(val) == "table" then 340 | data=table.concat(val, ", ") 341 | else 342 | data=val 343 | end 344 | if data and type(data) ~= "boolean" and body(data) then 345 | return true 346 | end 347 | end 348 | end 349 | end 350 | else 351 | return 352 | end 353 | end 354 | 355 | return Acc -------------------------------------------------------------------------------- /vanilla/sys/waf/config.lua: -------------------------------------------------------------------------------- 1 | local sys_waf_conf = {} 2 | 3 | sys_waf_conf.RulePath = "./config/waf-regs/" 4 | sys_waf_conf.attacklog = "on" 5 | sys_waf_conf.logdir = "./logs/hack/" 6 | sys_waf_conf.UrlDeny="on" 7 | sys_waf_conf.Redirect="on" 8 | sys_waf_conf.CookieMatch="on" 9 | sys_waf_conf.postMatch="on" 10 | sys_waf_conf.whiteModule="on" 11 | sys_waf_conf.black_fileExt={"php","jsp"} 12 | sys_waf_conf.ipWhitelist={"127.0.0.1"} 13 | sys_waf_conf.ipBlocklist={"1.0.0.1"} 14 | sys_waf_conf.CCDeny="off" 15 | sys_waf_conf.CCrate="100/60" 16 | sys_waf_conf.html=[[ 17 | 18 | 19 | 20 |

Welcome To Vanilla's World ...

21 |
=== Vanilla is a Web framework Based On OpenResty ... ====
22 |

---- Sourse Code:https://github.com/idevz/vanilla ... ----

23 | 24 | 25 | ]] 26 | 27 | return sys_waf_conf -------------------------------------------------------------------------------- /vanilla/v/application.lua: -------------------------------------------------------------------------------- 1 | -- perf 2 | local pairs = pairs 3 | local pcall = pcall 4 | local setmetatable = setmetatable 5 | 6 | -- vanilla 7 | local Error = LoadV 'vanilla.v.error' 8 | local Dispatcher = LoadV 'vanilla.v.dispatcher' 9 | -- local Registry = LoadV('vanilla.v.registry'):new('sys') 10 | local Utils = LoadV 'vanilla.v.libs.utils' 11 | local Bootstrap = LoadV 'vanilla.v.bootstrap' 12 | 13 | local function new_dispatcher(self) 14 | return Dispatcher:new(self) 15 | end 16 | 17 | local Application = {} 18 | 19 | function Application:lpcall( ... ) 20 | local ok, rs_or_error = pcall( ... ) 21 | if ok then return rs_or_error else self:raise_syserror(rs_or_error) end 22 | end 23 | 24 | function Application:buildconf(config) 25 | local sys_conf = config 26 | sys_conf['version'] = config['vanilla_version'] or 'idevz-vanilla' 27 | if sys_conf.name == nil or sys_conf.app.root == nil then 28 | self:raise_syserror([[ 29 | Sys Err: Please set app name and app root in config/application.lua like: 30 | 31 | Appconf.name = 'idevz.org' 32 | Appconf.app.root='/data1/VANILLA_ROOT/idevz.org/' 33 | ]]) 34 | end 35 | -- Registry['app_name'] = sys_conf.name 36 | -- Registry['app_root'] = sys_conf.app.root 37 | -- Registry['app_version'] = sys_conf.version 38 | self.config = sys_conf 39 | return true 40 | end 41 | 42 | function Application:new(ngx, config) 43 | self:buildconf(config) 44 | local instance = { dispatcher = self:lpcall(new_dispatcher, self) } 45 | setmetatable(instance, {__index = self}) 46 | return instance 47 | end 48 | 49 | function Application:bootstrap(lboots) 50 | local bootstrap_instance = Bootstrap:new(lboots(self.dispatcher)) 51 | self:lpcall(bootstrap_instance.bootstrap, bootstrap_instance) 52 | return self 53 | end 54 | 55 | function Application:run() 56 | self:lpcall(self.dispatcher.dispatch, self.dispatcher) 57 | end 58 | 59 | function Application:raise_syserror(err) 60 | if type(err) == 'table' then 61 | err = Error:new(err.code, err.msg) 62 | ngx.status = err.status 63 | else 64 | ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR 65 | end 66 | ngx.say('
')
67 |     ngx.say(Utils.sprint_r(err))
68 |     ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
69 | end
70 | 
71 | return Application
72 | 


--------------------------------------------------------------------------------
/vanilla/v/bootstrap.lua:
--------------------------------------------------------------------------------
 1 | -- perf
 2 | local pairs = pairs
 3 | local setmetatable = setmetatable
 4 | -- local lbootstrap = require 'application.bootstrap'
 5 | 
 6 | 
 7 | local Bootstrap = {}
 8 | 
 9 | function Bootstrap:new(lboot_instance)
10 |     local instance = {
11 |     	lboot_instance = lboot_instance
12 |     }
13 |     setmetatable(instance, {__index=self})
14 |     return instance
15 | end
16 | 
17 | function Bootstrap:bootstrap()
18 | 	for k,v in pairs(self.lboot_instance:boot_list()) do
19 | 		v(self.lboot_instance)
20 | 	end
21 | end
22 | 
23 | return Bootstrap


--------------------------------------------------------------------------------
/vanilla/v/cache.lua:
--------------------------------------------------------------------------------
 1 | local Cache = Class('vanilla.v.cache')
 2 | local mc = LoadV('vanilla.v.cache.mc')
 3 | local lru = LoadV('vanilla.v.cache.lru')
 4 | local redis = LoadV('vanilla.v.cache.redis')
 5 | local shdict = LoadV('vanilla.v.cache.shdict')
 6 | 
 7 | local function __construct(self, handle)
 8 | 	local handle = handle or 'shared_dict'
 9 | 	local cache_instance
10 | 	if handle == 'sh' or handle == 'shared_dict' then
11 | 		self.cache_instance = shdict()
12 | 	elseif handle == 'mc' or handle == 'memcached' then
13 | 		self.cache_instance = mc()
14 | 	elseif handle == 'redis' then
15 | 		self.cache_instance = redis()
16 | 	elseif handle == 'lru' or handle == 'lrucache' then
17 | 		self.cache_instance = lru()
18 | 	end
19 | end
20 | Cache.__construct = __construct
21 | 
22 | local function _get_cache_instance(self)
23 | 	return self.cache_instance
24 | end
25 | Cache.getCacheInstance = _get_cache_instance
26 | 
27 | local function _set(self, ...)
28 | 	local cache_instance = self.cache_instance
29 | 	self.cache_instance:set(...)
30 | 	return true
31 | end
32 | Cache.set = _set
33 | 
34 | local function _get(self, ...)
35 | 	local cache_instance = self.cache_instance
36 | 	return cache_instance:get(...)
37 | end
38 | Cache.get = _get
39 | 
40 | local function _del(self, ... )
41 | 	local cache_instance = self.cache_instance
42 | 	return cache_instance:del(...)
43 | end
44 | Cache.del = _del
45 | 
46 | return Cache


--------------------------------------------------------------------------------
/vanilla/v/cache/base.lua:
--------------------------------------------------------------------------------
 1 | local Base = Class('vanilla.v.cache.base')
 2 | local utils = LoadV('vanilla.v.libs.utils')
 3 | local ngx_crc32 = ngx.crc32_short
 4 | local str_sub = string.sub
 5 | 
 6 | local function _gen_cache_key(parent, key)
 7 | 	return Registry['APP_NAME'] .. '_' .. str_sub(ngx.md5(key),1,10)
 8 | end
 9 | Base.cacheKey = _gen_cache_key
10 | 
11 | local function _get_cache_hp(cache_conf, key_str, node)
12 | 	local cache_arrs = utils.explode(" ", utils.trim(cache_conf["instances"]))
13 | 	local cache_arrs_num = #cache_arrs
14 | 	local cache_num = ngx_crc32(key_str)%cache_arrs_num + 1
15 | 	if node ~= nil then
16 | 		if cache_arrs_num >= node then
17 | 			cache_num = node
18 | 		else
19 | 			-- error('Invanidate Node Num')
20 | 		end
21 | 	end
22 | 	local cache_info_arrs = utils.explode(":", cache_arrs[cache_num])
23 | 	return cache_info_arrs[1], cache_info_arrs[2]
24 | end
25 | 
26 | local function _connect_remote_cache(parent, child, key, node)
27 | 	local cache_conf = child.cache_conf
28 | 	local host, port = _get_cache_hp(cache_conf, key, node)
29 | 	local ok, err = child.cache_instance:connect(host, port)
30 | 	if not ok then
31 | 		-- error(handle .. " failed to connect: " .. err)
32 | 	end
33 | end
34 | Base.connect = _connect_remote_cache
35 | 
36 | local function _set_keepalive(parent, child)
37 | 	ngx.log(ngx.ERR, sprint_r(parent))
38 | 	local cache_conf = child.cache_conf
39 | 	local poolsize = cache_conf['poolsize']
40 | 	local idletimeout = cache_conf['idletimeout']
41 | 	local ok, err = child.cache_instance:set_keepalive(idletimeout, poolsize)
42 | 	if not ok then
43 | 	    error("cannot set keepalive: ", err)
44 | 	    return
45 | 	end
46 | end
47 | Base.set_keepalive = _set_keepalive
48 | 
49 | return Base


--------------------------------------------------------------------------------
/vanilla/v/cache/lru.lua:
--------------------------------------------------------------------------------
 1 | local Lru = Class('vanilla.v.cache.lru', LoadV('vanilla.v.cache.base'))
 2 | local resty_lrucache = require 'resty.lrucache'
 3 | local resty_lrucache_ffi = require 'resty.lrucache.pureffi'
 4 | 
 5 | local function __construct(self)
 6 | 	if Registry['lrucache_instance'] then return end
 7 | 	local cache_conf = Registry['sys_conf']['cache']['lrucache']
 8 | 	self.cache_conf = cache_conf
 9 | 	local lrucache, err
10 | 	if cache_conf['useffi'] then
11 | 		lrucache, err = resty_lrucache_ffi.new(cache_conf['items'])
12 | 	else
13 | 		lrucache, err = resty_lrucache.new(cache_conf['items'])
14 | 	end
15 | 	if lrucache == nil then
16 | 		error("failed to instantiate lrucache: " .. err)
17 | 	end
18 | 	Registry['lrucache_instance'] = lrucache
19 | end
20 | 
21 | Lru.__construct = __construct
22 | 
23 | local function _get_cache_instance(self)
24 | 	return Registry['lrucache_instance']
25 | end
26 | Lru.getCacheInstance = _get_cache_instance
27 | 
28 | local function _set(self, key, value, exptime)
29 | 	local key = self.parent:cacheKey(key)
30 | 	local cache_conf = self.cache_conf
31 | 	local cache_instance = Registry['lrucache_instance']
32 | 	local exptime = exptime or cache_conf['exptime']
33 | 	cache_instance:set(key, value, exptime)
34 | 	return true
35 | end
36 | Lru.set = _set
37 | 
38 | local function _get(self, key)
39 | 	local key = self.parent:cacheKey(key)
40 | 	local cache_instance = Registry['lrucache_instance']
41 | 	return cache_instance:get(key)
42 | end
43 | Lru.get = _get
44 | 
45 | local function _del(self, key)
46 | 	local key = self.parent:cacheKey(key)
47 | 	local cache_instance = Registry['lrucache_instance']
48 | 	return cache_instance:delete(key)
49 | end
50 | Lru.del = _del
51 | 
52 | return Lru


--------------------------------------------------------------------------------
/vanilla/v/cache/mc.lua:
--------------------------------------------------------------------------------
 1 | local Mc = Class('vanilla.v.cache.mc', LoadV('vanilla.v.cache.base'))
 2 | local resty_memcached = require 'resty.memcached'
 3 | 
 4 | local function __construct(self)
 5 | 	local cache_conf = Registry['sys_conf']['cache']['memcached']
 6 | 	self.cache_conf = cache_conf
 7 | 	local memc, err = resty_memcached:new()
 8 | 	if not memc then
 9 | 		-- error("failed to instantiate memcached cache_instance: " .. err)
10 | 	end
11 | 	memc:set_timeout(cache_conf['timeout'])
12 | 	self.cache_instance = memc
13 | end
14 | 
15 | Mc.__construct = __construct
16 | 
17 | local function _get_cache_instance(self)
18 | 	return self.cache_instance
19 | end
20 | Mc.getCacheInstance = _get_cache_instance
21 | 
22 | local function _set(self, key, value, exptime)
23 | 	local cache_conf = self.cache_conf
24 | 	local cache_instance = self.cache_instance
25 | 	local key = self.parent:cacheKey(key)
26 | 	self.parent:connect(self, key, node)
27 | 	local exptime = exptime or cache_conf['exptime']
28 | 	local succ, err = cache_instance:set(key, value, exptime)
29 | 	if not succ then error(err) end
30 | 	self.parent:set_keepalive(self)
31 | 	return true
32 | end
33 | Mc.set = _set
34 | 
35 | local function _get(self, key)
36 | 	local cache_conf = self.cache_conf
37 | 	local cache_instance = self.cache_instance
38 | 	local key = self.parent:cacheKey(key)
39 | 	self.parent:connect(self, key, node)
40 | 	local rs, err
41 | 	if type(key) == 'string' then
42 | 		local flags
43 | 		rs, flags, err = cache_instance:get(key)
44 | 	else
45 | 		rs, err = cache_instance:get(key)
46 | 	end
47 | 	if err then
48 | 		-- error(err)
49 | 	end
50 | 	self.parent:set_keepalive(self)
51 | 	return rs
52 | end
53 | Mc.get = _get
54 | 
55 | local function _del(self, key)
56 | 	local cache_conf = self.cache_conf
57 | 	local cache_instance = self.cache_instance
58 | 	local key = self.parent:cacheKey(key)
59 | 	self.parent:connect(self, key, node)
60 | 	local rs, err = cache_instance:delete(key)
61 | 	if err then
62 | 		-- error(err)
63 | 	end
64 | 	self.parent:set_keepalive(self)
65 | 	return rs
66 | end
67 | Mc.del = _del
68 | 
69 | return Mc


--------------------------------------------------------------------------------
/vanilla/v/cache/redis.lua:
--------------------------------------------------------------------------------
 1 | local Redis = Class('vanilla.v.cache.redis', LoadV('vanilla.v.cache.base'))
 2 | local resty_redis = require 'resty.redis'
 3 | 
 4 | local function __construct(self)
 5 | 	local cache_conf = Registry['sys_conf']['cache']['redis']
 6 | 	self.cache_conf = cache_conf
 7 | 	local red, err = resty_redis:new()
 8 | 	if err then
 9 | 		-- error("failed to instantiate redis: " .. err)
10 | 	end
11 | 	red:set_timeout(cache_conf['timeout'])
12 | 	self.cache_instance = red
13 | end
14 | 
15 | Redis.__construct = __construct
16 | 
17 | local function _get_cache_instance(self)
18 | 	return self.cache_instance
19 | end
20 | Redis.getCacheInstance = _get_cache_instance
21 | 
22 | local function _set(self, key, value, exptime)
23 | 	local cache_conf = self.cache_conf
24 | 	local cache_instance = self.cache_instance
25 | 	local key = self.parent:cacheKey(key)
26 | 	-- ngx.log(ngx.ERR, sprint_r(key))
27 | 	self.parent:connect(self, key, node)
28 | 	local exptime = exptime or cache_conf['exptime']
29 | 	local succ, err = cache_instance:set(key, value)
30 | 	cache_instance:expire(key, exptime)
31 | 	if not succ then error(err) end
32 | 	self.parent:set_keepalive(self)
33 | 	return true
34 | end
35 | Redis.set = _set
36 | 
37 | local function _get(self, key)
38 | 	local cache_conf = self.cache_conf
39 | 	local cache_instance = self.cache_instance
40 | 	local key = self.parent:cacheKey(key)
41 | 	self.parent:connect(self, key, node)
42 | 	local rs, err = cache_instance:get(key)
43 | 	if err then
44 | 		error(err)
45 | 	end
46 | 	self.parent:set_keepalive(self)
47 | 	return rs
48 | end
49 | Redis.get = _get
50 | 
51 | local function _del(self, key)
52 | 	local cache_conf = self.cache_conf
53 | 	local cache_instance = self.cache_instance
54 | 	local key = self.parent:cacheKey(key)
55 | 	self.parent:connect(self, key, node)
56 | 	local rs, err = cache_instance:del(key)
57 | 	if err then
58 | 		error(err)
59 | 	end
60 | 	self.parent:set_keepalive(self)
61 | 	return rs
62 | end
63 | Redis.del = _del
64 | 
65 | return Redis


--------------------------------------------------------------------------------
/vanilla/v/cache/shdict.lua:
--------------------------------------------------------------------------------
 1 | local Shdict = Class('vanilla.v.cache.shdict', LoadV('vanilla.v.cache.base'))
 2 | local ngx_shdict = ngx.shared
 3 | local str_sub = string.sub
 4 | 
 5 | local function __construct(self)
 6 | 	local shdict_conf = Registry['sys_conf']['cache']['shared_dict']
 7 | 	self.shdict_conf = shdict_conf
 8 | 	self.cache_instance = ngx_shdict[shdict_conf['dict']]
 9 | end
10 | 
11 | Shdict.__construct = __construct
12 | 
13 | local function _get_cache_instance(self)
14 | 	return self.cache_instance
15 | end
16 | Shdict.getCacheInstance = _get_cache_instance
17 | 
18 | local function _set(self, key, value, exptime)
19 | 	local key = self.parent:cacheKey(key)
20 | 	local cache_instance = self.cache_instance
21 | 	local exptime = exptime or self.shdict_conf['exptime']
22 | 	local succ, err = cache_instance:set(key, value, exptime)
23 | 	if not succ then error(err) end
24 | 	return true
25 | end
26 | Shdict.set = _set
27 | 
28 | local function _get(self, key)
29 | 	local key = self.parent:cacheKey(key)
30 | 	local cache_instance = self.cache_instance
31 | 	return cache_instance:get(key)
32 | end
33 | Shdict.get = _get
34 | 
35 | local function _del(self, key)
36 | 	local key = self.parent:cacheKey(key)
37 | 	local cache_instance = self.cache_instance
38 | 	return cache_instance:delete(key)
39 | end
40 | Shdict.del = _del
41 | 
42 | return Shdict


--------------------------------------------------------------------------------
/vanilla/v/config/handle.lua:
--------------------------------------------------------------------------------
 1 | -- Config Handle
 2 | -- @since 2016-05-17 23:00
 3 | -- @author idevz 
 4 | -- version $Id$
 5 | 
 6 | local Handle = Class('vanilla.v.config')
 7 | local parse = LoadV('vanilla.v.config.parse')
 8 | local save = LoadV('vanilla.v.config.save')
 9 | 
10 | function Handle:__construct(conf_type)
11 | 	self.conf_type = conf_type
12 | end
13 | 
14 | function Handle:get(conf)
15 | 	local lines = function(name) return assert(io.open(name)):lines() end
16 | 	return parse[self.conf_type](lines, Registry['APP_ROOT'] .. '/' .. conf)
17 | end
18 | 
19 | function Handle:save(name, t)
20 | 	local write = function(name, contents) return assert(io.open(name, "w")):write(contents) end
21 | 	save[self.conf_type](write, Registry['APP_ROOT'] .. '/' .. name, t)
22 | 	return true
23 | end
24 | 
25 | return Handle


--------------------------------------------------------------------------------
/vanilla/v/config/parse.lua:
--------------------------------------------------------------------------------
 1 | -- Config Parse moudle
 2 | -- @since 2016-05-8 8:54
 3 | -- @author idevz 
 4 | -- version $Id$
 5 | 
 6 | local Parse = {}
 7 | 
 8 | function Parse.ini(lines, name)
 9 |     local t = {}
10 |     local section
11 |     for line in lines(name) do
12 |         local s = line:match("^%[([^%]]+)%]$")
13 |         if s then
14 |             section = s
15 |             t[section] = t[section] or {}
16 |             goto CONTINUE
17 |         end
18 |         local key, value = line:match("^(%w+)%s-=%s-(.+)$")
19 |         if key and value then
20 |             if tonumber(value) then value = tonumber(value) end
21 |             if value == "true" then value = true end
22 |             if value == "false" then value = false end
23 |             t[section][key] = value
24 |         end
25 |         ::CONTINUE::
26 |     end
27 |     return t
28 | end
29 | 
30 | return Parse
31 | 
32 | 
33 | -- Config Parse moudle
34 | -- @since 2016-05-8 8:54
35 | -- @author idevz 
36 | -- version $Id$
37 | 
38 | -- local Parse = {}
39 | -- local ngx_re_match = ngx.re.match
40 | 
41 | -- function Parse.ini(lines, name)
42 | --     local t = {}
43 | --     local section
44 | --     for line in lines(name) do
45 | --         local s = ngx_re_match(line, [[^\[(.*)\]$]], 'o')
46 | --         if s then
47 | --             section = s[1]
48 | --             t[section] = t[section] or {}
49 | --             goto CONTINUE
50 | --         end
51 | --         local s_conf = ngx_re_match(line, [[^(\w+)\s*=\s*(.*)$]], 'o')
52 | --         local key, value
53 | --         if s_conf then
54 | --             local key, value = s_conf[1], s_conf[2]
55 | --             if key and value then
56 | --                 if tonumber(value) then value = tonumber(value) end
57 | --                 if value == "true" then value = true end
58 | --                 if value == "false" then value = false end
59 | --                 t[section][key] = value
60 | --             end
61 | --         end
62 | --         -- local key, value = ngx_re_match(line, [[^(\w+)\s*=\s*(.*)$]], 'o')
63 | --         ::CONTINUE::
64 | --     end
65 | --     return t
66 | -- end
67 | 
68 | -- return Parse
69 | 


--------------------------------------------------------------------------------
/vanilla/v/config/save.lua:
--------------------------------------------------------------------------------
 1 | -- Config Save moudle
 2 | -- @since 2016-05-8 8:54
 3 | -- @author idevz 
 4 | -- version $Id$
 5 | 
 6 | local Save = {}
 7 | 
 8 | function Save.ini(write, name, t)
 9 |     local contents = ""
10 |     for section, s in pairs(t) do
11 |         contents = contents .. ("[%s]\n"):format(section)
12 |         for key, value in pairs(s) do
13 |             contents = contents .. ("%s=%s\n"):format(key, tostring(value))
14 |         end
15 |         contents = contents .. "\n"
16 |     end
17 |     write(name, contents)
18 | end
19 | 
20 | return Save
21 | 


--------------------------------------------------------------------------------
/vanilla/v/controller.lua:
--------------------------------------------------------------------------------
 1 | -- perf
 2 | local error = error
 3 | local pairs = pairs
 4 | local setmetatable = setmetatable
 5 | 
 6 | local Controller = {}
 7 | 
 8 | function Controller:new(request, response, app_config)
 9 |     local instance = {
10 |         app_config = app_config,
11 |         params = request.params,
12 |         request = request,
13 |         response = response,
14 |         view = {}
15 |     }
16 |     setmetatable(instance, {__index = self})
17 |     return instance
18 | end
19 | 
20 | function Controller:display(view_tpl, values)
21 |     self.view:render(view_tpl, values)
22 | end
23 | 
24 | function Controller:getRequest()
25 |     return self.request
26 | end
27 | 
28 | function Controller:getResponse()
29 |     return self.response
30 | end
31 | 
32 | function Controller:getView()
33 |     return self.view
34 | end
35 | 
36 | function Controller:initView(view_handle, controller_name, action_name)
37 |     local init_controller = ''
38 |     local init_action = ''
39 |     if view_handle ~= nil then self.view = view_handle end
40 |     if controller_name ~= nil then init_controller = controller_name else init_controller = self.request.controller_name end
41 |     if action_name ~= nil then init_action = action_name else init_action = self.request.action_name  end
42 |     self.view:init(init_controller, init_action)
43 | end
44 | 
45 | function Controller:redirect(url)
46 |     local togo = url
47 |     if not ngx.re.match(togo, "http") then
48 |         togo = "http://" .. togo
49 |     end
50 |     ngx.redirect(togo)
51 | end
52 | 
53 | function Controller:raise_error(code, custom_attrs)
54 |     error({ code = code, custom_attrs = custom_attrs })
55 | end
56 | 
57 | function Controller:accepted_params(param_filters, params)
58 |     local accepted_params = {}
59 |     for _, param in pairs(param_filters) do
60 |         accepted_params[param] = params[param]
61 |     end
62 |     return accepted_params
63 | end
64 | 
65 | return Controller


--------------------------------------------------------------------------------
/vanilla/v/dispatcher.lua:
--------------------------------------------------------------------------------
  1 | -- vanilla
  2 | local Controller = LoadV 'vanilla.v.controller'
  3 | local Request = LoadV 'vanilla.v.request'
  4 | local Router = LoadV 'vanilla.v.router'
  5 | local Response = LoadV 'vanilla.v.response'
  6 | local View = LoadV 'vanilla.v.views.rtpl'
  7 | local Error = LoadV 'vanilla.v.error'
  8 | 
  9 | -- perf
 10 | local error = error
 11 | local pairs = pairs
 12 | local pcall = pcall
 13 | local ngx = ngx
 14 | local require = require
 15 | local setmetatable = setmetatable
 16 | local function tappend(t, v) t[#t+1] = v end
 17 | 
 18 | local function new_view(view_conf)
 19 |     return View:new(view_conf)
 20 | end
 21 | 
 22 | local function run_route(router_instance)
 23 |     return router_instance:route()
 24 | end
 25 | 
 26 | local Dispatcher = {}
 27 | local mt = {__index = Dispatcher}
 28 | 
 29 | function Dispatcher:new(application)
 30 |     local request = Request:new()
 31 |     local response = Response:new()
 32 |     local router = Router:new(request)
 33 |     Registry['CONTROLLER_PREFIX'] = 'controllers.'
 34 |     local instance = {
 35 |         application = application,
 36 |         request = request,
 37 |         response = response,
 38 |         router = router,
 39 |         plugins = {},
 40 |         -- controller_prefix = 'controllers.',
 41 |         error_controller = 'error',
 42 |         error_action = 'error'
 43 |     }
 44 |     return setmetatable(instance, mt)
 45 | end
 46 | 
 47 | function Dispatcher:getRequest()
 48 |     return self.request
 49 | end
 50 | 
 51 | function Dispatcher:setRequest(request)
 52 |     self.request = request
 53 | end
 54 | 
 55 | function Dispatcher:getResponse()
 56 |     return self.response
 57 | end
 58 | 
 59 | function Dispatcher:registerPlugin(plugin)
 60 |     if plugin ~= nil then tappend(self.plugins, plugin) end
 61 | end
 62 | 
 63 | function Dispatcher:_runPlugins(hook)
 64 |     for _, plugin in ipairs(self.plugins) do
 65 |         if plugin[hook] ~= nil then
 66 |             plugin[hook](plugin, self.request, self.response)
 67 |         end
 68 |     end
 69 | end
 70 | 
 71 | function Dispatcher:getRouter()
 72 |     return self.router
 73 | end
 74 | 
 75 | function Dispatcher:_route()
 76 |     local ok, controller_name_or_error, action= pcall(run_route, self.router)
 77 |     if ok and controller_name_or_error then
 78 |         self.request.controller_name = controller_name_or_error
 79 |         self.request.action_name = action
 80 |         return true
 81 |     else
 82 |         self:errResponse(controller_name_or_error)
 83 |     end
 84 | end
 85 | 
 86 | local function require_controller(controller_prefix, controller_name)
 87 |     return LoadApplication(controller_prefix .. controller_name)
 88 | end
 89 | 
 90 | local function call_controller(Dispatcher, matched_controller, controller_name, action_name)
 91 |     if matched_controller[action_name] == nil then
 92 |         Dispatcher:errResponse({ code = 102, msg = {NoAction = action_name}})
 93 |     end
 94 |     Dispatcher:initView()
 95 |     local body = matched_controller[action_name](matched_controller)
 96 |     if body ~= nil then return body
 97 |     else
 98 |         Dispatcher:errResponse({ code = 104, msg = {Exec_Err = controller_name .. '/' .. action_name}})
 99 |     end
100 | end
101 | 
102 | function Dispatcher:dispatch()
103 |     self:_runPlugins('routerStartup')
104 |     self:_route()
105 |     self:_runPlugins('routerShutdown')
106 |     self.controller = Controller:new(self.request, self.response, self.application.config)
107 |     self.view = self.view or self.application:lpcall(new_view, self.application.config.view)
108 |     self:_runPlugins('dispatchLoopStartup')
109 |     local cls_call = {}
110 |     local matched_controller = self:lpcall(require_controller, Registry['CONTROLLER_PREFIX'], self.request.controller_name)
111 |     self:_runPlugins('preDispatch')
112 |     if matched_controller.parent ~= nil and type(matched_controller.parent) == 'table' then
113 |         setmetatable(matched_controller.parent, {__index = self.controller})
114 |         cls_call = matched_controller()
115 |     elseif matched_controller.__cname ~= nil then
116 |         local mt = getmetatable(matched_controller)
117 |         mt.__index = self.controller
118 |         cls_call = matched_controller()
119 |         setmetatable(cls_call.class, mt)
120 |     else
121 |         cls_call = setmetatable(matched_controller, { __index = self.controller })
122 |     end
123 |     local c_rs = self:lpcall(call_controller, self, cls_call, self.request.controller_name, self.request.action_name)
124 |     self.response.body = c_rs
125 |     self:_runPlugins('postDispatch')
126 |     self.response:response()
127 |     self:_runPlugins('dispatchLoopShutdown')
128 | end
129 | 
130 | function Dispatcher:initView(view, controller_name, action_name)
131 |     if view ~= nil then self.view = view end
132 |     self.controller:initView(self.view, controller_name, action_name)
133 | end
134 | 
135 | function Dispatcher:lpcall( ... )
136 |     local ok, rs_or_error = pcall( ... )
137 |     if ok then
138 |         return rs_or_error
139 |     else
140 |         self:errResponse(rs_or_error)
141 |     end
142 | end
143 | 
144 | function Dispatcher:errResponse(err)
145 |     self.response.body = self:raise_error(err)
146 |     self.response:response()
147 |     ngx.eof()
148 | end
149 | 
150 | function Dispatcher:raise_error(err)
151 |     if self.controller == nil then self.controller = Controller:new(self.request, self.response, self.application.config) end
152 |     if self.view == nil then self.view = self.application:lpcall(new_view, self.application.config.view) end
153 |     local error_controller = LoadApplication(Registry['CONTROLLER_PREFIX'] .. self.error_controller)
154 |     setmetatable(error_controller, { __index = self.controller })
155 |     self:initView(self.view, self.error_controller, self.error_action)
156 |     local error_instance = Error:new(err.code, err.msg)
157 |     if error_instance ~= false then
158 |         error_controller.err = error_instance
159 |     else
160 |         error_controller.err = Error:new(100, {msg = err})
161 |     end
162 |     self.response:setStatus(error_controller.err.status)
163 |     return error_controller[self.error_action](error_controller)
164 | end
165 | 
166 | function Dispatcher:getApplication()
167 |     return self.application
168 | end
169 | 
170 | function Dispatcher:setView(view)
171 |     self.view = view
172 | end
173 | 
174 | function Dispatcher:returnResponse()
175 |     return self.response
176 | end
177 | 
178 | function Dispatcher:setDefaultAction(default_action)
179 |     if default_action ~= nil then self.request.action_name = default_action end
180 | end
181 | 
182 | function Dispatcher:setDefaultController(default_controller)
183 |     if default_controller ~= nil then self.request.controller_name = default_controller end
184 | end
185 | 
186 | function Dispatcher:setErrorHandler(err_handler)
187 |     if type(err_handler) == 'table' then
188 |         if err_handler['controller'] ~= nil then self.error_controller = err_handler['controller'] end
189 |         if err_handler['action'] ~= nil then self.error_action = err_handler['action'] end
190 |         return true
191 |     end
192 |     return false
193 | end
194 | 
195 | return Dispatcher
196 | 


--------------------------------------------------------------------------------
/vanilla/v/error.lua:
--------------------------------------------------------------------------------
 1 | -- vanilla
 2 | local helpers = LoadV 'vanilla.v.libs.utils'
 3 | 
 4 | -- perf
 5 | local error = error
 6 | local pairs = pairs
 7 | local setmetatable = setmetatable
 8 | 
 9 | -- define error
10 | Error = {}
11 | Error.__index = Error
12 | 
13 | local function init_errors()
14 |     -- get app errors
15 |     local errors = helpers.try_require('config.errors', {})
16 |     -- add system errors
17 |     errors[100] = { status = 500, message = "Vanilla Inner Lpcall Err." }
18 |     errors[101] = { status = 500, message = "DisPatcher Err: Request init Error." }
19 |     errors[102] = { status = 404, message = "DisPatcher Err: Action didn't defined." }
20 |     errors[103] = { status = 500, message = "Controller Err." }
21 |     errors[104] = { status = 500, message = "Action Err.: Action return Nil." }
22 |     errors[105] = { status = 500, message = "Response Err." }
23 |     errors[201] = { status = 500, message = "Routing Err." }
24 |     errors[203] = { status = 500, message = "Plugins Err." }
25 | 
26 |     return errors
27 | end
28 | 
29 | Error.list = init_errors()
30 | 
31 | function Error:new(code, custom_attrs)
32 |     local err = Error.list[code]
33 |     if err == nil then return false end
34 | 
35 |     local body = {
36 |         code = code,
37 |         message = err.message
38 |     }
39 | 
40 |     if custom_attrs ~= nil then
41 |         for k,v in pairs(custom_attrs) do body[k] = v end
42 |     end
43 | 
44 |     local instance = {
45 |         status = err.status,
46 |         body = body
47 |     }
48 |     setmetatable(instance, Error)
49 |     return instance
50 | end
51 | 
52 | return Error
53 | 


--------------------------------------------------------------------------------
/vanilla/v/libs/ansicolors.lua:
--------------------------------------------------------------------------------
 1 | -- perf
 2 | local setmetatable = setmetatable
 3 | local error = error
 4 | local schar = string.char
 5 | local sgsub = string.gsub
 6 | local sformat = string.format
 7 | local tinsert = table.insert
 8 | local tconcat = table.concat
 9 | 
10 | local colors_map = {
11 | 	-- reset
12 | 	reset =      0,
13 | 
14 | 	-- misc
15 | 	bright     = 1,
16 | 	dim        = 2,
17 | 	underline  = 4,
18 | 	blink      = 5,
19 | 	reverse    = 7,
20 | 	hidden     = 8,
21 | 
22 | 	-- foreground colors
23 | 	black     = 30,
24 | 	red       = 31,
25 | 	green     = 32,
26 | 	yellow    = 33,
27 | 	blue      = 34,
28 | 	magenta   = 35,
29 | 	cyan      = 36,
30 | 	white     = 37,
31 | 
32 | 	-- background colors
33 | 	blackbg   = 40,
34 | 	redbg     = 41,
35 | 	greenbg   = 42,
36 | 	yellowbg  = 43,
37 | 	bluebg    = 44,
38 | 	magentabg = 45,
39 | 	cyanbg    = 46,
40 | 	whitebg   = 47
41 | }
42 | 
43 | local function escapeKeys(str)
44 | 	local buffer = {}
45 | 	local number
46 | 	for word in str:gmatch("%w+") do
47 | 		number = colors_map[word]
48 | 		assert(number, "Unknown colors: " .. word)
49 | 		tinsert(buffer, sformat(schar(27) .. '[%dm', number))
50 | 	end
51 | 	return tconcat(buffer)
52 | end
53 | 
54 | local function replaceCodes(str)
55 | 	str = sgsub(str,"(%%{(.-)})", function(_, str) return escapeKeys(str) end )
56 | 	return str
57 | end
58 | 
59 | local function ansicolors( str )
60 | 	str = tostring(str or '')
61 | 	return replaceCodes('%{reset}' .. str .. '%{reset}')
62 | end
63 | 
64 | return setmetatable({noReset = replaceCodes}, {__call = function (_, str) return ansicolors (str) end})


--------------------------------------------------------------------------------
/vanilla/v/libs/cache.lua:
--------------------------------------------------------------------------------
  1 | local Cache = Class('vanilla.v.libs.cache')
  2 | local resty_memcached = require 'resty.memcached'
  3 | local resty_redis = require 'resty.redis'
  4 | local resty_lrucache = require 'resty.lrucache'
  5 | local resty_lrucache_ffi = require 'resty.lrucache.pureffi'
  6 | local utils = LoadV('vanilla.v.libs.utils')
  7 | local str_sub = string.sub
  8 | 
  9 | local ngx_crc32 = ngx.crc32_short
 10 | local ngx_shdict = ngx.shared
 11 | 
 12 | local function __construct(self, handle)
 13 | 	local handle = handle or 'shared_dict'
 14 | 	local cache_conf = Registry['sys_conf']['cache']
 15 | 
 16 | 	self.cache_conf = cache_conf
 17 | 	self.handle = handle
 18 | 
 19 | 	local cache_instance
 20 | 	if handle == 'sh' or handle == 'shared_dict' then
 21 | 		self.cache_instance = ngx_shdict[cache_conf['shared_dict']['content']]
 22 | 	elseif handle == 'mc' or handle == 'memcached' then
 23 | 		local memc, err = resty_memcached:new()
 24 | 		if not memc then
 25 | 			-- error("failed to instantiate memcached cache_instance: " .. err)
 26 | 		end
 27 | 		memc:set_timeout(cache_conf['memcached']['timeout'])
 28 | 		self.cache_instance = memc
 29 | 	elseif handle == 'redis' then
 30 | 		local red, err = resty_redis:new()
 31 | 		if err then
 32 | 			-- error("failed to instantiate redis: " .. err)
 33 | 		end
 34 | 		red:set_timeout(cache_conf['redis']['timeout'])
 35 | 		self.cache_instance = red
 36 | 	elseif handle == 'lrucache' then
 37 | 		local lrucache, err = resty_lrucache.new(cache_conf['lrucache']['content'])
 38 | 		if lrucache == nil then
 39 | 			-- error("failed to instantiate lrucache: " .. err)
 40 | 		end
 41 | 		self.cache_instance = lrucache
 42 | 	end
 43 | end
 44 | Cache.__construct = __construct
 45 | 
 46 | local function _get_cache_hp(cache_type, cache_conf, key_str, node)
 47 | 	local cache_arrs = utils.explode(" ", utils.trim(cache_conf[cache_type]["conf"]))
 48 | 	local cache_arrs_num = #cache_arrs
 49 | 	local cache_num = ngx_crc32(key_str)%cache_arrs_num + 1
 50 | 	if node ~= nil then
 51 | 		if cache_arrs_num >= node then
 52 | 			cache_num = node
 53 | 		else
 54 | 			-- error('Invanidate Node Num')
 55 | 		end
 56 | 	end
 57 | 	local cache_info_arrs = utils.explode(":", cache_arrs[cache_num])
 58 | 	return cache_info_arrs[1], cache_info_arrs[2]
 59 | end
 60 | 
 61 | local function _get_cache_instance()
 62 | 	return self.cache_instance
 63 | end
 64 | Cache.getCacheInstance = _get_cache_instance
 65 | 
 66 | local function _connect_remote_cache(self, cache_type, key, node)
 67 | 	local handle = self.handle
 68 | 	local cache_conf = self.cache_conf
 69 | 	local host, port = _get_cache_hp(cache_type, cache_conf, key, node)
 70 | 	local ok, err = self.cache_instance:connect(host, port)
 71 | 	print_r(host)
 72 | 	if not ok then
 73 | 		-- error(handle .. " failed to connect: " .. err)
 74 | 	end
 75 | end
 76 | 
 77 | local function _useMc(self, key, node)
 78 | 	_connect_remote_cache(self, 'memcached', key, node)
 79 | 	return self
 80 | end
 81 | Cache.useMc = _useMc
 82 | 
 83 | local function _useRedis(self, key, node)
 84 | 	_connect_remote_cache(self, 'redis', key, node)
 85 | 	return self
 86 | end
 87 | Cache.useRedis = _useRedis
 88 | 
 89 | local function _useLruCache()
 90 | 	return self
 91 | end
 92 | Cache.useLruCache = _useLruCache
 93 | 
 94 | local function _useSharedDict()
 95 | 	return self
 96 | end
 97 | Cache.useSharedDict = _useSharedDict
 98 | 
 99 | local function _gen_cache_key(key)
100 | 	return Registry['APP_NAME'] .. '_' .. str_sub(ngx.md5(key),1,10)
101 | end
102 | Cache.cacheKey = _gen_cache_key
103 | 
104 | local function _get(self, key)
105 | 	local handle = self.handle
106 | 	local cache_instance = self.cache_instance
107 | 	local res, flags, get_err = cache_instance:get(_gen_cache_key(key))
108 | 	print_r(res)
109 | 	if get_err then
110 | 		print_r(get_err)
111 | 		-- error(handle .. " failed to get : " .. get_err)
112 | 		return false, get_err
113 | 	end
114 | 
115 | 	if not res then
116 | 		-- error(handle .. " not found " .. _gen_cache_key(key))
117 | 		return false
118 | 	end
119 | 	return res
120 | end
121 | Cache.get = _get
122 | 
123 | local function _set(self, key, value, expiretime)
124 | 	local handle = self.handle
125 | 	local cache_instance = self.cache_instance
126 | 	local expiretime = expiretime or 1000
127 | 	local set_ok, set_err
128 | 	if handle == 'redis' then
129 | 		local redis_key = _gen_cache_key(key)
130 | 		set_ok, set_err = cache_instance:set(redis_key, value)
131 | 		print_r(cache_instance)
132 | 		print_r(self)
133 | 		print_r(set_ok)
134 | 		cache_instance:expire(redis_key, expiretime)
135 | 	else
136 | 		set_ok, set_err = cache_instance:set(_gen_cache_key(key), value, expiretime)
137 | 	end
138 | 	if not set_ok and handle ~= 'lrucache' then
139 | 		-- error(handle .. "failed to set: " .. set_err)
140 | 		return false, set_err
141 | 	end
142 | 	return true
143 | end
144 | Cache.set = _set
145 | 
146 | return Cache


--------------------------------------------------------------------------------
/vanilla/v/libs/cookie.lua:
--------------------------------------------------------------------------------
 1 | -- https://github.com/cloudflare/lua-resty-cookie
 2 | local resty_cookie = require 'resty.cookie'
 3 | 
 4 | local Cookie = Class('vanilla.v.libs.cookie')
 5 | 
 6 | local function __construct(self)
 7 | 	local ck, err = resty_cookie:new()
 8 |     if not ck then
 9 |         ngx.log(ngx.ERR, err)
10 |         return
11 |     end
12 |     self.ck = ck
13 | end
14 | Cookie.__construct = __construct
15 | 
16 | local function _set(self, key, value, opts)
17 | 	local ck = self.ck
18 | 	local key = key
19 | 	local value = value
20 | 	local opts = opts or {}
21 | 
22 | 	local expires = opts['expires'] or 3600*24
23 | 	local path = opts['path'] or '/'
24 | 	local domain = opts['domain'] or Registry['APP_HOST']
25 | 	local secure = opts['secure'] or false
26 | 	local httponly = opts['httponly'] or true
27 | 	local samesite = opts['samesite'] or 'Lax' --Strict
28 | 	local extension = opts['extension'] or nil
29 | 
30 | 	local ck_opts = {
31 | 		key = key,
32 | 		value = value,
33 | 		path = path,
34 | 		domain = domain,
35 | 		max_age = expires,
36 | 		secure = secure,
37 | 		httponly = httponly,
38 | 		samesite = samesite,
39 | 		extension = extension
40 | 		}
41 | 
42 | 	local ok, err = ck:set(ck_opts)
43 |     if not ok then
44 |         ngx.log(ngx.ERR, err)
45 |         return false, err
46 |     end
47 |     return true
48 | end
49 | Cookie.set = _set
50 | 
51 | local function _get(self, key)
52 | 	local ck = self.ck
53 | 	local key = key
54 | 	local ok, err = ck:get(key)
55 | 	if not ok then
56 | 		ngx.log(ngx.ERR, err)
57 | 		return false, err
58 | 	end
59 | 	return ok
60 | end
61 | Cookie.get = _get
62 | 
63 | local function _get_all(self)
64 | 	local ck = self.ck
65 | 	local ok, err = ck:get_all()
66 | 	if not ok then
67 | 		ngx.log(ngx.ERR, err)
68 | 		return false, err
69 | 	end
70 | 	return ok
71 | end
72 | Cookie.getAll = _get_all
73 | 
74 | return Cookie


--------------------------------------------------------------------------------
/vanilla/v/libs/http.lua:
--------------------------------------------------------------------------------
 1 | -- dep:https://github.com/pintsized/lua-resty-http
 2 | local resty_http = require 'resty.http'
 3 | 
 4 | local str_upper = string.upper
 5 | local ngx_encode_args = ngx.encode_args
 6 | 
 7 | local Http = Class('vanilla.v.libs.http')
 8 | 
 9 | local function __construct(self)
10 | 	local http_handle = resty_http.new()
11 | 	self.http_handle = http_handle
12 | end
13 | Http.__construct = __construct
14 | 
15 | local function _request(self, method, url, body, headers, timeout)
16 | 	local http_handle = self.http_handle
17 | 	local method = method or 'GET'
18 | 	local timeout = timeout or 500
19 | 	local headers = headers or {}
20 | 	local body = body or nil
21 | 
22 | 	if type(body) == 'table' then
23 | 		body = ngx_encode_args(body)
24 | 	end
25 | 
26 | 	headers["User-Agent"] = 'Vanilla-OpenResty-' .. Registry['VANILLA_VERSION']
27 | 	if str_upper(method) == 'POST' then
28 | 		headers["Content-Type"] = "application/x-www-form-urlencoded"
29 | 	end
30 | 
31 | 	http_handle:set_timeout(timeout)
32 | 
33 | 	local res, err = http_handle:request_uri(url, {
34 | 		method = method,
35 | 		headers = headers,
36 | 		body = body
37 | 		})
38 | 	if res ~= nil then
39 | 		return res
40 | 	else
41 | 		return false, err
42 | 	end
43 | end
44 | 
45 | local function get(self, ... )
46 | 	return _request(self, 'GET', ... )
47 | end
48 | Http.get = get
49 | 
50 | local function post(self, ... )
51 | 	return _request(self, 'POST', ... )
52 | end
53 | Http.post = post
54 | 
55 | return Http
56 | 


--------------------------------------------------------------------------------
/vanilla/v/libs/logs.lua:
--------------------------------------------------------------------------------
 1 | -- dep
 2 | -- https://github.com/cloudflare/lua-resty-logger-socket
 3 | local http_handle = require('resty.logger.socket')
 4 | 
 5 | -- perf
 6 | local setmetatable = setmetatable
 7 | 
 8 | local Logs = {}
 9 | 
10 | function Logs:new()
11 | 	local instance = {
12 | 	}
13 | 	setmetatable(instance, Logs)
14 | 	return instance
15 | end
16 | 
17 | return Logs


--------------------------------------------------------------------------------
/vanilla/v/libs/reqargs.lua:
--------------------------------------------------------------------------------
  1 | -- parse request body to args, this lib come from bungle
  2 | -- @since 2016-03-12 6:45
  3 | -- @author idevz 
  4 | -- @see https://github.com/bungle/lua-resty-reqargs
  5 | -- version $Id$
  6 | 
  7 | -- perf
  8 | local upload               = require "resty.upload"
  9 | local json_decode          = require "cjson.safe".decode
 10 | local os_tmpname           = os.tmpname
 11 | local tconcat              = table.concat
 12 | local type                 = type
 13 | local s_find               = string.find
 14 | local io_open              = io.open
 15 | local s_sub                = string.sub
 16 | local ngx                  = ngx
 17 | local ngx_req              = ngx.req
 18 | local ngx_var              = ngx.var
 19 | local req_read_body        = ngx_req.read_body
 20 | local req_get_body_data    = ngx_req.get_body_data
 21 | local req_get_post_args    = ngx_req.get_post_args
 22 | local req_get_uri_args     = ngx_req.get_uri_args
 23 | 
 24 | local function rightmost(s, sep)
 25 |     local p = 1
 26 |     local i = s_find(s, sep, 1, true)
 27 |     while i do
 28 |         p = i + 1
 29 |         i = s_find(s, sep, p, true)
 30 |     end
 31 |     if p > 1 then
 32 |         s = s_sub(s, p)
 33 |     end
 34 |     return s
 35 | end
 36 | 
 37 | local function basename(s)
 38 |     return rightmost(rightmost(s, "\\"), "/")
 39 | end
 40 | 
 41 | local function kv(r, s)
 42 |     if s == "formdata" then return end
 43 |     local e = s_find(s, "=", 1, true)
 44 |     if e then
 45 |         r[s_sub(s, 2, e - 1)] = s_sub(s, e + 2, #s - 1)
 46 |     else
 47 |         r[#r+1] = s
 48 |     end
 49 | end
 50 | 
 51 | local function parse(s)
 52 |     if not s then return nil end
 53 |     local r = {}
 54 |     local i = 1
 55 |     local b = s_find(s, ";", 1, true)
 56 |     while b do
 57 |         local p = s_sub(s, i, b - 1)
 58 |         kv(r, p)
 59 |         i = b + 1
 60 |         b = s_find(s, ";", i, true)
 61 |     end
 62 |     local p = s_sub(s, i)
 63 |     if p ~= "" then kv(r, p) end
 64 |     return r
 65 | end
 66 | 
 67 | local ReqArgs = {}
 68 | 
 69 | function ReqArgs:getRequestData(options)
 70 |     local GET = req_get_uri_args()
 71 |     local POST = {}
 72 |     local FILE = {}
 73 |     local content_type = ngx_var.content_type
 74 |     if content_type == nil then return GET, POST, FILE end
 75 |     if s_sub(content_type, 1, 19) == "multipart/form-data" then
 76 |         local chunk_size   = options.chunk_size or 8192
 77 |         local form, err = upload:new(chunk_size)
 78 |         if not form then return nil, err end
 79 |         local header, post_data, file_info, out_put_file
 80 |         form:set_timeout(options.timeout or 1000)
 81 |         while true do
 82 |             local res_type, res, err = form:read()
 83 |             if not res_type then return nil, err end
 84 |             if res_type == "header" then
 85 |                 if not header then header = {} end
 86 |                 if type(res) == "table" then
 87 |                     local k, v = res[1], parse(res[2])
 88 |                     if v then header[k] = v end
 89 |                 end
 90 |             elseif res_type == "body" then
 91 |                 if header then
 92 |                     local header_data = header["Content-Disposition"]
 93 |                     if header_data then
 94 |                         if header_data.filename then
 95 |                             file_info = {
 96 |                                 name = header_data.name,
 97 |                                 type = header["Content-Type"] and header["Content-Type"][1],
 98 |                                 file = basename(header_data.filename),
 99 |                                 temp = os_tmpname()
100 |                             }
101 |                             out_put_file, err = io_open(file_info.temp, "w+")
102 |                             if not out_put_file then return nil, err end
103 |                             out_put_file:setvbuf("full", chunk)
104 |                         else
105 |                             post_data = { name = header_data.name, data = { n = 1 } }
106 |                         end
107 |                     end
108 |                     h = nil
109 |                 end
110 |                 if out_put_file then
111 |                     local ok, err = out_put_file:write(res)
112 |                     if not ok then return nil, err end
113 |                 elseif post_data then
114 |                     local n = post_data.data.n
115 |                     post_data.data[n] = res
116 |                     post_data.data.n = n + 1
117 |                 end
118 |             elseif res_type == "part_end" then
119 |                 if out_put_file then
120 |                     file_info.size = out_put_file:seek()
121 |                     out_put_file:close()
122 |                     out_put_file = nil
123 |                 end
124 |                 local c, d
125 |                 if file_info then
126 |                     c, d, file_info = FILE, file_info, nil
127 |                 elseif post_data then
128 |                     c, d, post_data = POST, post_data, nil
129 |                 end
130 |                 if c then
131 |                     local n = d.name
132 |                     local s = d.data and tconcat(d.data) or d
133 |                     if n then
134 |                         local z = c[n]
135 |                         if z then
136 |                             if z.n then
137 |                                 z.n = z.n + 1
138 |                                 z[z.n] = s
139 |                             else
140 |                                 z = { z, s }
141 |                                 z.n = 2
142 |                             end
143 |                         else
144 |                             c[n] = s
145 |                         end
146 |                     else
147 |                         c[c.n+1] = s
148 |                         c.n = c.n + 1
149 |                     end
150 |                 end
151 |             elseif res_type == "eof" then
152 |                 break
153 |             end
154 |         end
155 |         local t, r, e = form:read()
156 |         if not t then return nil, e end
157 |         FILE[1] = true
158 |     elseif s_sub(content_type, 1, 16) == "application/json" then
159 |         req_read_body()
160 |         POST = json_decode(req_get_body_data()) or {}
161 |     else
162 |         req_read_body()
163 |         POST = req_get_post_args()
164 |     end
165 |     return GET, POST, FILE
166 | end
167 | 
168 | return ReqArgs
169 | 


--------------------------------------------------------------------------------
/vanilla/v/libs/session.lua:
--------------------------------------------------------------------------------
 1 | -- dep
 2 | -- https://github.com/bungle/lua-resty-session
 3 | local http_handle = require('resty.session').new()
 4 | 
 5 | -- perf
 6 | local setmetatable = setmetatable
 7 | 
 8 | local Session = {}
 9 | 
10 | function Session:new()
11 | 	local instance = {
12 | 	}
13 | 	setmetatable(instance, Session)
14 | 	return instance
15 | end
16 | 
17 | return Session


--------------------------------------------------------------------------------
/vanilla/v/libs/shcache.lua:
--------------------------------------------------------------------------------
 1 | -- dep
 2 | -- https://github.com/cloudflare/lua-resty-shcache
 3 | local http_handle = require('resty.shcache')
 4 | 
 5 | -- perf
 6 | local setmetatable = setmetatable
 7 | 
 8 | local Shcache = {}
 9 | 
10 | function Shcache:new()
11 | 	local instance = {
12 | 	}
13 | 	setmetatable(instance, Shcache)
14 | 	return instance
15 | end
16 | 
17 | return Shcache


--------------------------------------------------------------------------------
/vanilla/v/libs/utils.lua:
--------------------------------------------------------------------------------
  1 | -- perf
  2 | local assert = assert
  3 | local iopen = io.open
  4 | local pairs = pairs
  5 | local pcall = pcall
  6 | local require = require
  7 | local sfind = string.find
  8 | local sgsub = string.gsub
  9 | local smatch = string.match
 10 | local ssub = string.sub
 11 | local type = type
 12 | local append = table.insert
 13 | local concat = table.concat
 14 | local function tappend(t, v) t[#t+1] = v end
 15 | 
 16 | local Utils = {}
 17 | 
 18 | function Utils.trim (s) 
 19 |   return (string.gsub(s, "^%s*(.-)%s*$", "%1")) 
 20 | end
 21 | 
 22 | function Utils.explode(d,p)
 23 |     local t, ll
 24 |     t={}
 25 |     ll=0
 26 |     if(#p == 1) then return {p} end
 27 |     while true do
 28 |         l=string.find(p,d,ll,true) -- find the next d in the string
 29 |         if l~=nil then -- if "not not" found then..
 30 |             table.insert(t, string.sub(p,ll,l-1)) -- Save it in our array.
 31 |             ll=l+1 -- save just after where we found it for searching next time.
 32 |         else
 33 |             table.insert(t, string.sub(p,ll)) -- Save what's left in our array.
 34 |             break -- Break at end, as it should be, according to the lua manual.
 35 |         end
 36 |     end
 37 |     return t
 38 | end
 39 | 
 40 | function Utils.lpcall( ... )
 41 |     local ok, rs_or_error = pcall( ... )
 42 |     if ok then
 43 |         return rs_or_error
 44 |     else
 45 |         Utils.raise_syserror(rs_or_error)
 46 |     end
 47 | end
 48 | 
 49 | function Utils.raise_syserror(err)
 50 |     ngx.say('
')
 51 |     local s = Utils.sprint_r(err)
 52 |     ngx.say(s)
 53 |     ngx.eof()
 54 | end
 55 | 
 56 | local function require_module(module_name)
 57 |     return require(module_name)
 58 | end
 59 | 
 60 | -- try to require
 61 | function Utils.try_require(module_name, default)
 62 |     local ok, module_or_err = pcall(require_module, module_name)
 63 | 
 64 |     if ok == true then return module_or_err end
 65 | 
 66 |     if ok == false and smatch(module_or_err, "'" .. module_name .. "' not found") then
 67 |         return default
 68 |     else
 69 |         error(module_or_err)
 70 |     end
 71 | end
 72 | 
 73 | -- read file
 74 | function Utils.read_file(file_path)
 75 |     local f = iopen(file_path, "rb")
 76 |     local content = f:read("*all")
 77 |     f:close()
 78 |     return content
 79 | end
 80 | 
 81 | -- split function
 82 | function Utils.split(str, pat)
 83 |     local t = {}
 84 |     local fpat = "(.-)" .. pat
 85 |     local last_end = 1
 86 |     local s, e, cap = sfind(str, fpat, 1)
 87 | 
 88 |     while s do
 89 |         if s ~= 1 or cap ~= "" then
 90 |             tappend(t,cap)
 91 |         end
 92 |         last_end = e+1
 93 |         s, e, cap = sfind(str, fpat, last_end)
 94 |     end
 95 | 
 96 |     if last_end <= #str then
 97 |         cap = ssub(str, last_end)
 98 |         tappend(t, cap)
 99 |     end
100 | 
101 |     return t
102 | end
103 | 
104 | -- split a path in individual parts
105 | function Utils.split_path(str)
106 |    return Utils.split(str, '[\\/]+')
107 | end
108 | 
109 | -- value in table?
110 | function Utils.included_in_table(t, value)
111 |     for i = 1, #t do
112 |         if t[i] == value then return true end
113 |     end
114 |     return false
115 | end
116 | 
117 | -- reverse table
118 | function Utils.reverse_table(t)
119 |     local size = #t + 1
120 |     local reversed = {}
121 |     for i = 1, #t  do
122 |         reversed[size - i] = t[i]
123 |     end
124 |     return reversed
125 | end
126 | 
127 | --- get the Lua keywords as a set-like table.
128 | -- So `res["and"]` etc would be `true`.
129 | -- @return a table
130 | function Utils.get_keywords ()
131 |     if not lua_keyword then
132 |         lua_keyword = {
133 |             ["and"] = true, ["break"] = true,  ["do"] = true,
134 |             ["else"] = true, ["elseif"] = true, ["end"] = true,
135 |             ["false"] = true, ["for"] = true, ["function"] = true,
136 |             ["if"] = true, ["in"] = true,  ["local"] = true, ["nil"] = true,
137 |             ["not"] = true, ["or"] = true, ["repeat"] = true,
138 |             ["return"] = true, ["then"] = true, ["true"] = true,
139 |             ["until"] = true,  ["while"] = true
140 |         }
141 |     end
142 |     return lua_keyword
143 | end
144 | 
145 | --- Utility function that finds any patterns that match a long string's an open or close.
146 | -- Note that having this function use the least number of equal signs that is possible is a harder algorithm to come up with.
147 | -- Right now, it simply returns the greatest number of them found.
148 | -- @param s The string
149 | -- @return 'nil' if not found. If found, the maximum number of equal signs found within all matches.
150 | local function has_lquote(s)
151 |     local lstring_pat = '([%[%]])(=*)%1'
152 |     local start, finish, bracket, equals, next_equals = nil, 0, nil, nil, nil
153 |     -- print("checking lquote for", s)
154 |     repeat
155 |         start, finish, bracket, next_equals =  s:find(lstring_pat, finish + 1)
156 |         if start then
157 |             -- print("found start", start, finish, bracket, next_equals)
158 |             --length of captured =. Ex: [==[ is 2, ]] is 0.
159 |             next_equals = #next_equals 
160 |             equals = next_equals >= (equals or 0) and next_equals or equals
161 |         end
162 |     until not start
163 |     --next_equals will be nil if there was no match.
164 |     return   equals 
165 | end
166 | 
167 | --- Quote the given string and preserve any control or escape characters, such that reloading the string in Lua returns the same result.
168 | -- @param s The string to be quoted.
169 | -- @return The quoted string.
170 | function Utils.quote_string(s)
171 |     --find out if there are any embedded long-quote
172 |     --sequences that may cause issues.
173 |     --This is important when strings are embedded within strings, like when serializing.
174 |     local equal_signs = has_lquote(s) 
175 |     if  s:find("\n") or equal_signs then 
176 |         -- print("going with long string:", s)
177 |         equal_signs =  ("="):rep((equal_signs or -1) + 1)
178 |         --long strings strip out leading \n. We want to retain that, when quoting.
179 |         if s:find("^\n") then s = "\n" .. s end
180 |         --if there is an embedded sequence that matches a long quote, then
181 |         --find the one with the maximum number of = signs and add one to that number
182 |         local lbracket, rbracket =  
183 |             "[" .. equal_signs .. "[",  
184 |             "]" .. equal_signs .. "]"
185 |         s = lbracket .. s .. rbracket
186 |     else
187 |         --Escape funny stuff.
188 |         s = ("%q"):format(s)
189 |     end
190 |     return s
191 | end
192 | 
193 | local function quote (s)
194 |     if type(s) == 'table' then
195 |         return Utils.write(s,'')
196 |     else
197 |         --AAS
198 |         return Utils.quote_string(s)-- ('%q'):format(tostring(s))
199 |     end
200 | end
201 | 
202 | local function quote_if_necessary (v)
203 |     if not v then return ''
204 |     else
205 |         --AAS
206 |         if v:find ' ' then v = Utils.quote_string(v) end
207 |     end
208 |     return v
209 | end
210 | 
211 | local function index (numkey,key)
212 |     --AAS
213 |     if not numkey then 
214 |         key = quote(key) 
215 |          key = key:find("^%[") and (" " .. key .. " ") or key
216 |     end
217 |     return '['..key..']'
218 | end
219 | 
220 | local function is_identifier (s)
221 |     return type(s) == 'string' and s:find('^[%a_][%w_]*$') and not keywords[s]
222 | end
223 | 
224 | --- Create a string representation of a Lua table.
225 | --  This function never fails, but may complain by returning an
226 | --  extra value. Normally puts out one item per line, using
227 | --  the provided indent; set the second parameter to '' if
228 | --  you want output on one line.
229 | --  @tab tbl Table to serialize to a string.
230 | --  @string space (optional) The indent to use.
231 | --  Defaults to two spaces; make it the empty string for no indentation
232 | --  @bool not_clever (optional) Use for plain output, e.g {['key']=1}.
233 | --  Defaults to false.
234 | --  @return a string
235 | --  @return a possible error message
236 | function Utils.write (tbl,space,not_clever)
237 |     if type(tbl) ~= 'table' then
238 |         local res = tostring(tbl)
239 |         if type(tbl) == 'string' then return quote(tbl) end
240 |         return res, 'not a table'
241 |     end
242 |     if not keywords then
243 |         keywords = Utils.get_keywords()
244 |     end
245 |     local set = ' = '
246 |     if space == '' then set = '=' end
247 |     space = space or '  '
248 |     local lines = {}
249 |     local line = ''
250 |     local tables = {}
251 | 
252 | 
253 |     local function put(s)
254 |         if #s > 0 then
255 |             line = line..s
256 |         end
257 |     end
258 | 
259 |     local function putln (s)
260 |         if #line > 0 then
261 |             line = line..s
262 |             append(lines,line)
263 |             line = ''
264 |         else
265 |             append(lines,s)
266 |         end
267 |     end
268 | 
269 |     local function eat_last_comma ()
270 |         local n,lastch = #lines
271 |         local lastch = lines[n]:sub(-1,-1)
272 |         if lastch == ',' then
273 |             lines[n] = lines[n]:sub(1,-2)
274 |         end
275 |     end
276 | 
277 |     local writeit
278 |     writeit = function (t,oldindent,indent)
279 |         local tp = type(t)
280 |         if tp ~= 'string' and  tp ~= 'table' then
281 |             putln(quote_if_necessary(tostring(t))..',')
282 |         elseif tp == 'string' then
283 |             -- if t:find('\n') then
284 |             --     putln('[[\n'..t..']],')
285 |             -- else
286 |             --     putln(quote(t)..',')
287 |             -- end
288 |             --AAS
289 |             putln(Utils.quote_string(t) ..",")
290 |         elseif tp == 'table' then
291 |             if tables[t] then
292 |                 putln(',')
293 |                 return
294 |             end
295 |             tables[t] = true
296 |             local newindent = indent..space
297 |             putln('{')
298 |             local used = {}
299 |             if not not_clever then
300 |                 for i,val in ipairs(t) do
301 |                     put(indent)
302 |                     writeit(val,indent,newindent)
303 |                     used[i] = true
304 |                 end
305 |             end
306 |             for key,val in pairs(t) do
307 |                 local numkey = type(key) == 'number'
308 |                 if not_clever then
309 |                     key = tostring(key)
310 |                     put(indent..index(numkey,key)..set)
311 |                     writeit(val,indent,newindent)
312 |                 else
313 |                     if not numkey or not used[key] then -- non-array indices
314 |                         if numkey or not is_identifier(key) then
315 |                             key = index(numkey,key)
316 |                         end
317 |                         put(indent..key..set)
318 |                         writeit(val,indent,newindent)
319 |                     end
320 |                 end
321 |             end
322 |             tables[t] = nil
323 |             eat_last_comma()
324 |             putln(oldindent..'},')
325 |         else
326 |             putln(tostring(t)..',')
327 |         end
328 |     end
329 |     writeit(tbl,'',space)
330 |     eat_last_comma()
331 |     return concat(lines,#space > 0 and '\n' or '')
332 | end
333 | 
334 | function Utils.sprint_r(o)
335 |     return Utils.write(o)
336 | end
337 | 
338 | -- get the lua module name
339 | function Utils.get_lua_module_name(file_path)
340 |     return smatch(file_path, "(.*)%.lua")
341 | end
342 | 
343 | -- shallow copy of a table
344 | function Utils.shallowcopy(orig)
345 |     local orig_type = type(orig)
346 |     local copy
347 |     if orig_type == 'table' then
348 |         copy = {}
349 |         for orig_key, orig_value in pairs(orig) do
350 |             copy[orig_key] = orig_value
351 |         end
352 |     else -- number, string, boolean, etc
353 |         copy = orig
354 |     end
355 |     return copy
356 | end
357 | 
358 | function Utils.basename(str)
359 |     local name = sgsub(str, "(.*/)(.*)", "%2")
360 |     return name
361 | end
362 | 
363 | function Utils.dirname(str)
364 |     if str:match(".-/.-") then
365 |         local name = sgsub(str, "(.*/)(.*)", "%1")
366 |         return name
367 |     else
368 |         return ''
369 |     end
370 | end
371 | 
372 | return Utils
373 | 


--------------------------------------------------------------------------------
/vanilla/v/plugin.lua:
--------------------------------------------------------------------------------
 1 | -- perf
 2 | local setmetatable = setmetatable
 3 | 
 4 | local Plugin = {}
 5 | 
 6 | function Plugin:routerStartup(request, response)
 7 | end
 8 | 
 9 | function Plugin:routerShutdown(request, response)
10 | end
11 | 
12 | function Plugin:dispatchLoopStartup(request, response)
13 | end
14 | 
15 | function Plugin:preDispatch(request, response)
16 | end
17 | 
18 | function Plugin:postDispatch(request, response)
19 | end
20 | 
21 | function Plugin:dispatchLoopShutdown(request, response)
22 | end
23 | 
24 | function Plugin:new()
25 |     local instance = {
26 |     }
27 |     setmetatable(instance, {__index = self})
28 |     return instance
29 | end
30 | 
31 | return Plugin


--------------------------------------------------------------------------------
/vanilla/v/registry.lua:
--------------------------------------------------------------------------------
 1 | -- perf
 2 | local setmetatable = setmetatable
 3 | 
 4 | local vanilla_userdata = {}
 5 | 
 6 | local Registry = {}
 7 | 
 8 | function Registry:del(key)
 9 |     vanilla_userdata[self.namespace][key] = nil
10 | end
11 | 
12 | function Registry:get(key)
13 |     if vanilla_userdata[self.namespace][key] ~= nil then
14 |         return vanilla_userdata[self.namespace][key]
15 |     else
16 |         return false
17 |     end
18 | end
19 | 
20 | function Registry:has(key)
21 |     if vanilla_userdata[self.namespace][key] ~= nil then
22 |         return true 
23 |     else
24 |         return false
25 |     end
26 | end
27 | 
28 | function Registry:set(key, value)
29 |     vanilla_userdata[self.namespace][key] = value
30 |     return true
31 | end
32 | 
33 | function Registry:dump(namespace)
34 |     local rs = {}
35 |     if namespace ~= nil then
36 |         rs = vanilla_userdata[namespace]
37 |     else
38 |         rs = vanilla_userdata
39 |     end
40 |     return rs
41 | end
42 | 
43 | function Registry:new(namespace)
44 |     if namespace == nil then namespace = 'default' end
45 |     if vanilla_userdata[namespace] == nil then vanilla_userdata[namespace] = {} end
46 |     local instance = {
47 |         namespace = namespace,
48 |         del = self.del,
49 |         get = self.get,
50 |         has = self.has,
51 |         dump = self.dump,
52 |         set = self.set
53 |     }
54 |     setmetatable(instance, Registry)
55 |     return instance
56 | end
57 | 
58 | function Registry:__newindex(index, value)
59 |     if index ~=nil and value ~= nil then
60 |         vanilla_userdata[self.namespace][index]=value
61 |     end
62 | end
63 | 
64 | function Registry:__index(index)
65 |     local out = rawget(vanilla_userdata[self.namespace], index)
66 |     if out then return out else return false end
67 | end
68 | 
69 | return Registry


--------------------------------------------------------------------------------
/vanilla/v/request.lua:
--------------------------------------------------------------------------------
  1 | -- Request moudle
  2 | -- @since 2015-08-17 10:54
  3 | -- @author idevz 
  4 | -- version $Id$
  5 | 
  6 | -- perf
  7 | local error = error
  8 | local pairs = pairs
  9 | local pcall = pcall
 10 | local setmetatable = setmetatable
 11 | local Reqargs = LoadV 'vanilla.v.libs.reqargs'
 12 | 
 13 | local Request = {}
 14 | 
 15 | function Request:new()
 16 |     -- local headers = ngx.req.get_headers()
 17 | 
 18 |     -- url:http://zj.com:9210/di0000/111?aa=xx
 19 |     local instance = {
 20 |         uri = ngx.var.uri,                  -- /di0000/111
 21 |         -- req_uri = ngx.var.request_uri,      -- /di0000/111?aa=xx
 22 |         -- req_args = ngx.var.args,            -- aa=xx
 23 |         -- params = params,
 24 |         -- uri_args = ngx.req.get_uri_args(),  -- { aa = "xx" }
 25 |         -- method = ngx.req.get_method(),
 26 |         -- headers = headers,
 27 |         -- body_raw = ngx.req.get_body_data()
 28 |     }
 29 |     setmetatable(instance, {__index = self})
 30 |     return instance
 31 | end
 32 | 
 33 | -- function Request:getControllerName()
 34 | --     return self.controller_name
 35 | -- end
 36 | 
 37 | -- function Request:getActionName()
 38 | --     return self.action_name
 39 | -- end
 40 | 
 41 | function Request:getHeaders()
 42 |     if self.headers == nil then self.headers = ngx.req.get_headers() end
 43 |     return self.headers
 44 | end
 45 | 
 46 | function Request:getHeader(key)
 47 |     return self:getHeaders()[key]
 48 | end
 49 | 
 50 | function Request:buildParams()
 51 |     local GET, POST, FILE = Reqargs:getRequestData({})
 52 |     local params = {}
 53 |     params['VA_GET'] = GET
 54 |     params['VA_POST'] = POST
 55 |     if #FILE >= 1 then params['VA_FILE']=FILE end
 56 |     for k,v in pairs(GET) do params[k] = v end
 57 |     for k,v in pairs(POST) do params[k] = v end
 58 |     self.params = params
 59 |     return self.params
 60 | end
 61 | 
 62 | function Request:GET()
 63 |     if self.params ~= nil then return self.params.VA_GET end
 64 |     return self:buildParams()['VA_GET']
 65 | end
 66 | 
 67 | function Request:POST()
 68 |     if self.params ~= nil then return self.params.VA_POST end
 69 |     return self:buildParams()['VA_POST']
 70 | end
 71 | 
 72 | function Request:FILE()
 73 |     if self.params ~= nil then return self.params.VA_FILE end
 74 |     return self:buildParams()['VA_FILE']
 75 | end
 76 | 
 77 | function Request:getMethod()
 78 |     if self.method == nil then self.method = ngx.req.get_method() end
 79 |     return self.method
 80 | end
 81 | 
 82 | function Request:getParams()
 83 |     return self.params or self:buildParams()
 84 | end
 85 | 
 86 | function Request:getParam(key)
 87 |     if self.params ~= nil then return self.params[key] end
 88 |     return self:buildParams()[key]
 89 | end
 90 | 
 91 | function Request:setParam(key, value)
 92 |     if self.params == nil then self:buildParams() end
 93 |     self.params[key] = value
 94 | end
 95 | 
 96 | function Request:isGet()
 97 |     if self:getMethod() == 'GET' then return true else return false end
 98 | end
 99 | 
100 | return Request


--------------------------------------------------------------------------------
/vanilla/v/response.lua:
--------------------------------------------------------------------------------
 1 | -- perf
 2 | local setmetatable = setmetatable
 3 | local cache = LoadV('vanilla.v.cache')
 4 | 
 5 | local Response = {}
 6 | Response.__index = Response
 7 | 
 8 | function Response:new()
 9 |     local instance = {
10 |         headers = {},
11 |         append_body = '',
12 |         body = '',
13 |         prepend_body = '',
14 |         page_cache_timeout = 1000,
15 |     }
16 |     setmetatable(instance, Response)
17 |     return instance
18 | end
19 | 
20 | function Response:appendBody(append_body)
21 |     if append_body ~= nil and type(append_body) == 'string' then
22 |         self.append_body = append_body
23 |     else
24 |         error({ code = 105, msg = {AppendBodyErr = 'append_body must be a not empty string.'}})
25 |     end
26 | end
27 | 
28 | function Response:clearBody()
29 |     self.body = nil
30 | end
31 | 
32 | function Response:clearHeaders()
33 |     for k,_ in pairs(ngx.header) do
34 |         ngx.header[k] = nil
35 |     end
36 | end
37 | 
38 | function Response:getBody()
39 |     return self.body
40 | end
41 | 
42 | function Response:getHeader()
43 |     return self.headers
44 | end
45 | 
46 | function Response:prependBody(prepend_body)
47 |     if prepend_body ~= nil and type(prepend_body) == 'string' then
48 |         self.prepend_body = prepend_body
49 |     else
50 |         error({ code = 105, msg = {PrependBodyErr = 'prepend_body must be a not empty string.'}})
51 |     end
52 | end
53 | 
54 | function Response:response()
55 |     local REQ_Registry = ngx.ctx.REQ_Registry
56 |     local vanilla_version = Registry['VANILLA_VERSION']
57 |     ngx.header['Power_By'] = 'Vanilla-' .. vanilla_version
58 |     ngx.header['Content_type'] = ngx.header['Content_type'] or 'text/html'
59 |     local body = {[1]=self.append_body, [2]=self.body, [3]=self.prepend_body}
60 |     
61 |     ngx.print(body)
62 |     if REQ_Registry['USE_PAGE_CACHE'] then
63 |         local cache_lib = Registry['VANILLA_CACHE_LIB']
64 |         local page_cache = cache_lib(Registry['page_cache_handle'])
65 |         local rs = table.concat( body, "")
66 |         page_cache:set(REQ_Registry['APP_PAGE_CACHE_KEY'], rs, self.page_cache_timeout)
67 |     end
68 |     return true
69 | end
70 | 
71 | function Response:setPageCacheTimeOut(timeout)
72 |     local timeout = timeout or 1000
73 |     self.page_cache_timeout = timeout
74 | end
75 | 
76 | function Response:setBody(body)
77 |     if body ~= nil then self.body = body end
78 | end
79 | 
80 | function Response:setStatus(status)
81 |     if status ~= nil then ngx.status = status end
82 | end
83 | 
84 | function Response:setHeaders(headers)
85 |     if headers ~=nil then
86 |         for header,value in pairs(headers) do
87 |             ngx.header[header] = value
88 |         end
89 |     end
90 | end
91 | 
92 | function Response:setHeader(key, value)
93 |     ngx.header[key] = value
94 | end
95 | 
96 | return Response
97 | 


--------------------------------------------------------------------------------
/vanilla/v/router.lua:
--------------------------------------------------------------------------------
 1 | -- perf
 2 | local error = error
 3 | local tconcat = table.concat
 4 | local function tappend(t, v) t[#t+1] = v end
 5 | local simple_route = LoadV 'vanilla.v.routes.simple'
 6 | 
 7 | -- init Router and set routes
 8 | local Router = {}
 9 | 
10 | function Router:new(request)
11 |     local instance = { routes = {simple_route:new(request)} }
12 | 
13 |     setmetatable(instance, {__index = self})
14 |     return instance
15 | end
16 | 
17 | function Router:addRoute(route, only_one)
18 |     if route ~= nil then
19 |         if only_one then self.routes = {} end
20 |         tappend(self.routes, route)
21 |     end
22 | end
23 | 
24 | function Router:removeRoute(route_name)
25 |     for i,route in ipairs(self.routes) do
26 |         if (tostring(route) == route_name) then self.routes[i] = false end
27 |     end
28 | end
29 | 
30 | function Router:getRoutes()
31 |     return self.routes
32 | end
33 | 
34 | function Router:getCurrentRoute()
35 |     return self.current_route
36 | end
37 | 
38 | function Router:getCurrentRouteName()
39 |     return tostring(self.current_route)
40 | end
41 | 
42 | local function route_match(route)
43 |     return route:match()
44 | end
45 | 
46 | function Router:route()
47 |     if #self.routes >= 1 then
48 |         local alive_route_num = 0
49 |         local route_err = {}
50 |         for k,route in ipairs(self.routes) do
51 |             if route then
52 |                 alive_route_num = alive_route_num + 1
53 |                 local ok, controller_name_or_error, action = pcall(route_match, route)
54 |                 if ok and controller_name_or_error ~= nil and package.searchpath(Registry['APP_ROOT'] .. '/application/' 
55 |                     .. Registry['CONTROLLER_PREFIX']
56 |                     .. controller_name_or_error, '/?.lua;/?/init.lua') ~= nil
57 |                     -- and type(LoadApplication(Registry['CONTROLLER_PREFIX'] .. controller_name_or_error)[action]) == 'function' 
58 |                     then
59 |                 -- if ok and controller_name_or_error then
60 |                     self.current_route = route
61 |                     return controller_name_or_error, action
62 |                 else
63 |                     route_err[k] = controller_name_or_error
64 |                 end
65 |             end
66 |         end
67 |         error({ code = 201, msg = {
68 |             Routes_No_Match = alive_route_num .. " Routes All Didn't Match. Errs Like: " .. tconcat( route_err, ", ")}})
69 |     end
70 |     error({ code = 201, msg = {Empty_Routes = 'Null routes added.'}})
71 | end
72 | 
73 | return Router


--------------------------------------------------------------------------------
/vanilla/v/routes/restful.lua:
--------------------------------------------------------------------------------
 1 | -- perf
 2 | local error = error
 3 | local ngxgsub = ngx.re.gsub
 4 | local ngxmatch = ngx.re.match
 5 | local accept_header_pattern = "^application/vnd." .. Registry['APP_NAME'] .. ".v(\\d+)(.*)+json$"
 6 | local function tappend(t, v) t[#t+1] = v end
 7 | 
 8 | local http_methods = {
 9 |     GET = true,
10 |     POST = true,
11 |     HEAD = true,
12 |     OPTIONS = true,
13 |     PUT = true,
14 |     PATCH = true,
15 |     DELETE = true,
16 |     TRACE = true,
17 |     CONNECT = true
18 | }
19 | 
20 | local function rule_pattern(pattern)
21 |     local params = {}
22 |     local n_p = ngxgsub(pattern, "/:([A-Za-z0-9_]+)", function(m) tappend(params, m[1]); return "/([A-Za-z0-9_]+)" end, "io")
23 |     return n_p, params
24 | end
25 | 
26 | local function get_rules(request)
27 |     local rules_conf = LoadApp 'config.restful'
28 |     local header_accept = request:getHeader('accept')
29 |     local req_method = request:getMethod()
30 |     local version = ''
31 |     local rules = {}
32 |     if not http_methods[req_method] then error({ code = 201, msg = {Req_Method = 'Request Method Not Allowed...'}}) end
33 |     local v
34 |     if header_accept then v = ngxmatch(header_accept, accept_header_pattern) end
35 |     if v then version = v[1] end
36 |     if rules_conf['v' .. version] ~= nil and rules_conf['v' .. version][req_method] ~= nil then
37 |         for k,info in pairs(rules_conf['v' .. version][req_method]) do
38 |             local pattern, params = rule_pattern(info['pattern'])
39 |             local pattern_reg = "^" .. pattern .. "$"
40 |             rules[k] = info
41 |             rules[k]['pattern_reg'] = pattern_reg
42 |             rules[k]['params'] = params
43 |         end
44 |     -- else
45 |     --     error({ code = 201, msg = {Empty_Rules = 'Null routes rules for this Version Or Method Like:' 
46 |     --         .. 'v' .. version .. '.' .. req_method}})
47 |     end
48 |     return rules
49 | end
50 | 
51 | local RestFul = {}
52 | 
53 | function RestFul:new(request)
54 |     local instance = {
55 |         route_name = 'vanilla.v.routes.restful',
56 |         request = request,
57 |         rules = get_rules(request)
58 |     }
59 | 
60 |     setmetatable(instance, {
61 |         __index = self,
62 |         __tostring = function(self) return self.route_name end
63 |         })
64 |     return instance
65 | end
66 | 
67 | function RestFul:match()
68 |     local uri = self.request.uri
69 |     local match_rs = nil
70 |     for k,info in pairs(self.rules) do
71 |         match_rs = ngxmatch(uri, info['pattern_reg'], "io")
72 |         if match_rs then
73 |             for index, p in pairs(info['params']) do
74 |                 self.request:setParam(p, match_rs[index])
75 |             end
76 |             return info['controller'], info['action']
77 |         end
78 |     end
79 |     if uri == '/' then
80 |         return 'index', 'index'
81 |     end
82 | end
83 | 
84 | return RestFul
85 | 


--------------------------------------------------------------------------------
/vanilla/v/routes/simple.lua:
--------------------------------------------------------------------------------
 1 | -- perf
 2 | local error = error
 3 | local strlower = string.lower
 4 | local ngxmatch=ngx.re.gmatch
 5 | 
 6 | -- init Simple and set routes
 7 | local Simple = {}
 8 | 
 9 | function Simple:new(request)
10 |     local instance = {
11 |         route_name = 'vanilla.v.routes.simple',
12 |     	request = request
13 |     }
14 | 
15 |     setmetatable(instance, {
16 |         __index = self,
17 |         __tostring = function(self) return self.route_name end
18 |         })
19 |     return instance
20 | end
21 | 
22 | function Simple:match()
23 |     local uri = self.request.uri
24 |     local match = {}
25 |     local tmp = 1
26 |     if uri == '/' then
27 |         return 'index', 'index'
28 |     end
29 |     for v in ngxmatch(uri , '/([A-Za-z0-9_]+)', "o") do
30 |         match[tmp] = v[1]
31 |         tmp = tmp +1
32 |     end
33 |     if #match == 1 then
34 |         return match[1], 'index'
35 |     else
36 |         return table.concat(match, '.', 1, #match - 1), strlower(match[#match])
37 |     end
38 | end
39 | 
40 | return Simple


--------------------------------------------------------------------------------
/vanilla/v/view.lua:
--------------------------------------------------------------------------------
 1 | -- perf
 2 | local error = error
 3 | local setmetatable = setmetatable
 4 | 
 5 | 
 6 | local View = {}
 7 | View.__index = View
 8 | 
 9 | function View:new(controller_name, action, view_config)
10 | end
11 | 
12 | function View:init(controller_name, action)
13 | end
14 | 
15 | function View:assign()
16 | end
17 | 
18 | function View:caching()
19 | end
20 | 
21 | function View:display()
22 | end
23 | 
24 | function View:getScriptPath()
25 | end
26 | 
27 | function View:render()
28 | end
29 | 
30 | function View:setScriptPath()
31 | end
32 | 
33 | 
34 | return View


--------------------------------------------------------------------------------
/vanilla/v/views/lemplate.lua:
--------------------------------------------------------------------------------
 1 | local Lemplate = {}
 2 | local templates = LoadApplication("views.templates")
 3 | function Lemplate:new(view_config)
 4 |     local instance = {
 5 |         view_config = view_config
 6 |     }
 7 |     setmetatable(instance, {__index = self})
 8 |     return instance
 9 | end
10 | 
11 | function Lemplate:init(controller_name, action)
12 |     self.controller_name = controller_name
13 |     self.action = action
14 | end
15 | 
16 | function Lemplate:process(key, stash)
17 |     return table.concat(templates.process(key, stash))
18 | end
19 | 
20 | function Lemplate:assign(params)
21 | 	return self:process(self.controller_name .. '-' .. self.action .. self.view_config.suffix, params)
22 | end
23 | 
24 | return Lemplate


--------------------------------------------------------------------------------
/vanilla/v/views/rtpl.lua:
--------------------------------------------------------------------------------
 1 | -- dep
 2 | -- https://github.com/bungle/lua-resty-template
 3 | local template = require "resty.template"
 4 | 
 5 | -- perf
 6 | local error = error
 7 | local pairs = pairs
 8 | local setmetatable = setmetatable
 9 | local app_root = Registry['APP_NAME']
10 | 
11 | local View = {}
12 | 
13 | function View:new(view_config)
14 |     ngx.var.template_root = view_config.path or app_root .. 'application/views/'
15 |     local instance = {
16 |         view_config = view_config,
17 |         init = self.init
18 |     }
19 |     setmetatable(instance, {__index = self})
20 |     return instance
21 | end
22 | 
23 | function View:init(controller_name, action)
24 |     self.view_handle = template.new(controller_name .. '-' .. action .. self.view_config.suffix)
25 |     self.controller_name = controller_name
26 |     self.action = action
27 | end
28 | 
29 | function View:assign(key, value)
30 |     if type(key) == 'string' then
31 |         self.view_handle[key] = value
32 |     elseif type(key) == 'table' and value == nil then
33 |         for k,v in pairs(key) do
34 |             self.view_handle[k] = v
35 |         end
36 |     end
37 | end
38 | 
39 | function View:caching(cache)
40 |     local cache = cache or true
41 |     template.caching(cache)
42 | end
43 | 
44 | function View:display()
45 |     return tostring(self.view_handle)
46 | end
47 | 
48 | function View:getScriptPath()
49 |     return ngx.var.template_root
50 | end
51 | 
52 | local function view_handle_params(view_handle, params)
53 |     return view_handle(params)
54 | end
55 | 
56 | function View:render(view_tpl, params)
57 |     local view_handle = template.compile(view_tpl)
58 |     local ok, body_or_error = pcall(view_handle_params, view_handle, params)
59 |     if ok then
60 |         return body_or_error
61 |     else
62 |         error(body_or_error)
63 |     end
64 | end
65 | 
66 | function View:setScriptPath(scriptpath)
67 |     if scriptpath ~= nil then ngx.var.template_root = scriptpath end
68 | end
69 | 
70 | return View


--------------------------------------------------------------------------------