├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── README.md ├── config.lua ├── curldemo.sh ├── json_example.html ├── receiveJson.html └── turbowebdis.lua /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "resp"] 2 | path = resp 3 | url = https://github.com/soveran/resp 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Markus Bergholz 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 all 13 | 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 THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | LUAROCKS= luarocks-5.1 2 | 3 | arch: ## Install system dependencies on arch linux 4 | @echo "Installing system requirements using pacman" 5 | @sudo pacman -Sy redis luajit luarocks5.1 base-devel 6 | @make install 7 | 8 | ubuntu: ## Install system dependencies on ubuntu 9 | @echo "Installing system requirements using apt-get" 10 | @sudo apt-get install redis-server redis-tools luajit luarocks gcc libssl-dev 11 | @make install LUAROCKS=luarocks 12 | 13 | install: ## Install turbowebdis dependencies locally 14 | @echo "Installing lsocket" 15 | @$(LUAROCKS) install lsocket --local 16 | @echo "Installing turbo" 17 | @PREFIX=$$HOME/.luarocks/ $(LUAROCKS) install turbo --local 18 | @echo "setup environment path" 19 | @$(LUAROCKS) path >> $$HOME/.bashrc 20 | @echo "copy resp" 21 | @cp resp/resp.lua ./ 22 | 23 | start: ## Start turbowebdis 24 | @echo "Starting turbowebdis" 25 | @source $$HOME/.bashrc 26 | @echo $$(date) > turbo.log 27 | @./turbowebdis.lua >> turbo.log 2>&1 & echo "$$!" > /tmp/turbowebdis.pid 28 | 29 | stop: /tmp/turbowebdis.pid ## Stop turbowebdis 30 | @echo "Stopping turbowebdis" 31 | @kill `cat $<` && rm $< 32 | 33 | uninstall: ## Uninstall turbo dependencies 34 | @echo "removing lsocket" 35 | @$(LUAROCKS) remove lsocket --local 36 | @echo "removing turbo" 37 | @$(LUAROCKS) remove turbo --local 38 | 39 | tabularasa: ## Tabula rasa 40 | @echo "reset git repository" 41 | @git reset --hard 42 | @echo "remove local luarocks path" 43 | @rm -rf $$HOME/.luarocks/ 44 | @echo "flush redis db" 45 | @echo "flushdb"| redis-cli 46 | 47 | 48 | .PHONY: help 49 | 50 | help: 51 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 52 | 53 | .DEFAULT_GOAL := help 54 | 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tinywebdis 2 | 3 | Webdis replacement using TurboLua. 4 | 5 | ## requirements 6 | 7 | * luajit 8 | * luarocks 5.1 9 | * redis 10 | * gcc (to build TurboLua) 11 | 12 | ... install both with you package manager (when you're using linux). 13 | 14 | ## install 15 | 16 | E.g. if you're on a fresh Ubuntu 17 | 18 | 1. just install `git` and `make` 19 | 2. `git clone --recursive https://github.com/markuman/tinywebdis` 20 | 3. `make ubuntu` 21 | 4. `make start` 22 | 23 | 24 | $ make 25 | arch Install system dependencies on arch linux 26 | install Install turbowebdis dependencies locally 27 | start Start turbowebdis 28 | stop Stop turbowebdis 29 | tabularasa Tabula rasa 30 | ubuntu Install system dependencies on ubuntu 31 | uninstall Uninstall turbo dependencies 32 | 33 | 34 | #### curl examples 35 | 36 | 37 | 38 | $ curl -w '\n' http://127.0.0.1:1234/get/foo 39 | {"get": 42 } 40 | 41 | $ curl -w '\n' http://127.0.0.1:1234/set/foo/gnupower 42 | {"set": "OK" } 43 | 44 | $ curl -w '\n' http://127.0.0.1:1234/get/foo 45 | {"get": "gnupower" } 46 | 47 | $ curl -w '\n' http://127.0.0.1:1234/type/foo 48 | {"type": "string" } 49 | 50 | $ curl -w '\n' http://127.0.0.1:1234/type/mylist 51 | {"type": "list" } 52 | 53 | $ curl -w '\n' http://127.0.0.1:1234/llen/mylist 54 | {"llen": 4 } 55 | 56 | $ curl -w '\n' http://127.0.0.1:1234/lrange/mylist/0/-1 57 | { "lrange":[ "hello", "oi", "oi", "a"] } 58 | 59 | $ curl -w '\n' http://127.0.0.1:1234/keys/* 60 | { "keys":[ "mylist", "a:c", "foo", "a:b", "string"] } 61 | 62 | $ curl -w '\n' http://127.0.0.1:8000/rpush/tinywebdis/redis 63 | {"rpush": 3 } 64 | 65 | curl -w '\n' http://127.0.0.1:8000/llen/tinywebdis 66 | {"llen": 3 } 67 | 68 | curl -w '\n' http://127.0.0.1:8000/lrange/tinywebdis/0/-1 69 | { "lrange":[ "lua", "dyad", "redis"] } 70 | 71 | ##### jsonp support 72 | 73 | curl -w '\n' http://127.0.0.1:8888/get/foo?callback=myfunc 74 | myfunc({"get":"gnupower"}) 75 | 76 | 77 | 78 | #### HTML JQUERY CORS example 79 | 80 | You can send a json object to turbowebdis like this. 81 | 82 | { 83 | "auth": "foobar", 84 | "db": "0", 85 | "command": [ 86 | "SET", 87 | "SOME", 88 | "VALUE" 89 | ] 90 | } 91 | 92 | 93 | The key/value pairs `auth` and/or `db` are not a must have. When they are missed, the default values from `config.lua` file are taken. 94 | `db` should be a string. But you can pass it as a number too. Turbowebdis will take care of it. 95 | See `json_example.html` as a standalone example (open the file directly in your webbrowser). 96 | 97 | 98 | ## TurboWebdis, TinyWebdis & CherryWebdis 99 | 100 | Go here for detailed install instructions: [Installation](https://github.com/markuman/tinywebdis/wiki/Installation) 101 | 102 | 103 | * TurboWebdis is currently the main version (and the fastest). 104 | * TinyWebdis is currently not maintained but stable (and the tiniest installation). 105 | * CherryWebdis is maybe the easiest to install version (but incomplete!) 106 | 107 | 108 | #### Alternatively 109 | 110 | * Rust-Webdis by [badboy](https://github.com/badboy/webdis-rs) 111 | * Origin Webdis by [nicolasff](https://github.com/nicolasff/webdis) 112 | 113 | -------------------------------------------------------------------------------- /config.lua: -------------------------------------------------------------------------------- 1 | -- TurboWebdis config 2 | 3 | return { 4 | ["turbo"] = { ["port"] = 8888, ["logging"] = false, ["CORS"] = false, ["JSONP"] = true }, 5 | ["redis"] = { ["host"] = "127.0.0.1", ["port"] = 6379, ["auth"] = "", ["db"] = "0"} 6 | } 7 | -------------------------------------------------------------------------------- /curldemo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ### !! this could inundate your redis db 4 | 5 | # curl demo 6 | # set and get 7 | curl -w '\n' http://127.0.0.1:8888/get/noexisting 8 | curl -w '\n' http://127.0.0.1:8888/set/noexisting/42 9 | curl -w '\n' http://127.0.0.1:8888/get/noexisting 10 | curl -w '\n' http://127.0.0.1:8888/set/a:a/42 11 | curl -w '\n' http://127.0.0.1:8888/set/a:b/gnupower! 12 | curl -w '\n' http://127.0.0.1:8888/get/a:b 13 | 14 | # scan 15 | curl -w '\n' http://127.0.0.1:8888/scan/0/match/a:* 16 | 17 | # rpush, llen and lrange 18 | curl -w '\n' http://127.0.0.1:8888/rpush/tinywebdis/lua 19 | curl -w '\n' http://127.0.0.1:8888/rpush/tinywebdis/dyad 20 | curl -w '\n' http://127.0.0.1:8888/rpush/tinywebdis/redis 21 | curl -w '\n' http://127.0.0.1:8888/llen/tinywebdis 22 | curl -w '\n' http://127.0.0.1:8888/lrange/tinywebdis/0/-1 23 | 24 | # jsonp 25 | curl -w '\n' http://127.0.0.1:8888/get/a:b?callback=myfunc 26 | -------------------------------------------------------------------------------- /json_example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | turbowebdis 5 | 6 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /receiveJson.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TinyTurboWebdis 5 | 6 | 7 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /turbowebdis.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/luajit 2 | -- tinywebdis 1.3 powered by turbo.lua 3 | 4 | local config = require("config") 5 | local turbo = require("turbo") 6 | local escape = require("turbo.escape") 7 | 8 | turbo.log.categories.success = config.turbo.logging 9 | 10 | local function splitIntoArgs(path) 11 | local args = {} 12 | for arg in string.gmatch(path, "[^/]+") do 13 | -- table.insert(args, arg) 14 | -- faster way (less function calls) 15 | args[#args+1] = arg 16 | end 17 | return args 18 | end -- function splitIntoArgs 19 | 20 | 21 | local function callRedis(string) 22 | -- make redis connection using https://github.com/soveran/resp 23 | local resp = require("resp") 24 | -- enter redis connection details here 25 | local client = resp.new(config.redis.host, config.redis.port) 26 | local args = splitIntoArgs(string) 27 | local key = args[1] 28 | 29 | -- execute command 30 | local unpack = unpack or table.unpack 31 | if #config.redis.auth > 0 then client:call("AUTH", config.redis.auth) end 32 | if config.redis.db ~= "0" then client:call("SELECT", config.redis.db) end 33 | local value = client:call(unpack(args)) 34 | 35 | local ret = {} 36 | ret[key] = value 37 | return ret 38 | 39 | end -- function callRedis 40 | 41 | 42 | local IndexHandler = class("IndexHandler", turbo.web.RequestHandler) 43 | 44 | -- Method POST 45 | -- Sending json like this JSON.stringify({"auth": "", "db": 1, "command": ["GET", "SOME", "VALUE"]}) 46 | function IndexHandler:post() 47 | self:add_header('Access-Control-Allow-Origin','*') 48 | local json = self:get_json(true) 49 | 50 | auth = json['auth'] or auth 51 | db = tostring(json['db'] or db) -- make sure that the db number is a string 52 | local cmd = json['command'] 53 | 54 | self:write(callRedis(table.concat(cmd,'/'))) 55 | end -- POST 56 | 57 | -- Method GET 58 | function IndexHandler:get(input) 59 | -- add cors header 60 | self:add_header('Access-Control-Allow-Origin','*') 61 | self:add_header('Content-Type', 'application/json') 62 | 63 | -- count arguments 64 | input,argCount = string.gsub(input, "/", "%1") 65 | if ((argCount <= 1) and (#input <= 1)) then 66 | self:write({usage="command/key/option[1]/option[2]/..."}) 67 | else 68 | -- get/a?callback=mycallback 69 | -- jsonp return 70 | 71 | local callback = self:get_argument("callback", -1) 72 | if ((config.turbo.JSONP) and (type (callback) == "string")) then 73 | local retval = callRedis (input) 74 | self:write (callback .. "(" .. escape.json_encode (retval) .. ")") 75 | else 76 | self:write (callRedis (input)) 77 | end 78 | end -- if 79 | end -- GET 80 | 81 | -- CORS preflight request 82 | -- necessary for POST method 83 | function IndexHandler:options() 84 | if (config.turbo.CORS) then 85 | self:add_header('Access-Control-Allow-Methods', 'POST') 86 | self:add_header('Access-Control-Allow-Headers', 'content-type') 87 | self:add_header('Access-Control-Allow-Origin', '*') 88 | end 89 | end -- CORS preflight 90 | 91 | 92 | local app = turbo.web.Application:new({ 93 | -- parse arguments 94 | {"/(.*)$", IndexHandler}, 95 | }) 96 | 97 | app:listen(config.turbo.port) 98 | turbo.ioloop.instance():start() 99 | --------------------------------------------------------------------------------