{"id":23712009,"url":"https://github.com/godexsoft/krabby","last_synced_at":"2026-04-29T08:33:49.461Z","repository":{"id":143861216,"uuid":"260517053","full_name":"godexsoft/krabby","owner":"godexsoft","description":"Krabby is a Lua scriptable HTTP/WS server powered by C++","archived":false,"fork":false,"pushed_at":"2020-06-15T10:17:37.000Z","size":139,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-30T08:49:17.827Z","etag":null,"topics":["cpp17","crablib","http","inja","lua","moderncpp","scriptable","sol2","templates","webserver","websockets"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/godexsoft.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-05-01T17:22:49.000Z","updated_at":"2023-02-16T19:32:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"0a23272b-f423-49ce-a5b0-54ed28d4044b","html_url":"https://github.com/godexsoft/krabby","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/godexsoft/krabby","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/godexsoft%2Fkrabby","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/godexsoft%2Fkrabby/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/godexsoft%2Fkrabby/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/godexsoft%2Fkrabby/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/godexsoft","download_url":"https://codeload.github.com/godexsoft/krabby/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/godexsoft%2Fkrabby/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32417815,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T06:29:02.080Z","status":"ssl_error","status_checked_at":"2026-04-29T06:29:00.631Z","response_time":110,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp17","crablib","http","inja","lua","moderncpp","scriptable","sol2","templates","webserver","websockets"],"created_at":"2024-12-30T19:56:19.022Z","updated_at":"2026-04-29T08:33:49.456Z","avatar_url":"https://github.com/godexsoft.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Krabby\nA simple HTTP/WebSocket Lua scriptable webserver written in modern C++.\n\n### Dependencies\nMost of the dependencies are in git submodules under the `lib` directory.\nTo fetch Krabby with all its dependencies do this:\n```\n$ git clone https://github.com/godexsoft/krabby.git --recurse-submodules\n```\n\nYou will also need `SQLite3` development package and `Lua5.1` or newer with its development package installed on your system. Krabby will use whatever `Lua` you have available (through `sol3`).\n\nFor example, on Ubuntu:\n```\n$ sudo apt-get install lua5.1-dev\n$ sudo apt-get install libsqlite3-dev\n```\n\n`CMake` is used for generation of your preferred build files. By default it will generate a `Makefile`.\nYou will need `CMake 3.15` or newer in order to succesfully configure Krabby.\n\n### Compile\n```\n$ mkdir build\n$ cd build\n$ cmake -DENABLE_LOG=ON -DCRAB_TLS=ON ..\n$ make\n```\n\n*NOTE:*: CRAB_TLS option is only needed if you wish to include SSL support for the client request. For it to work you need to have OpenSSL installed.\n\n*NOTE:*: You can specify the root of your OpenSSL installation (for MacOSX with brew for example): -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl\n\n### Usage:\nSee `examples/scripts` directory for Lua code.\n\nKrabby accepts a data root directory as first (optional) argument. It will load all the `.lua` scripts it can find recursively.\n\n```\n$ krabby -h\n$ krabby path/to/data/root\n```\n\n*NOTE:* Krabby will use current directory as data root if no path is specified.\n\n### Docker\n\nDocker image is available at https://hub.docker.com/r/godexsoft/krabby\n\n```\n$ docker run -d --rm -v /path/to/data/root:/data:rw -p 8080:8080 --name krabby godexsoft/krabby:0.0.4\n```\n\n### API\n\n#### JSON\nJSON manipulation is supported via the `json` type:\n```\nlocal data = json.new()      \nlocal other = json.parse(\"{'some':'thing'}\")\n\ndata:str(\"strParam\", \"some string\")\ndata:int(\"intParam\", 420)\ndata:dbl(\"doubleParam\", 42.0)\ndata:bool(\"boolParam\", true)\ndata:obj(\"objOrArray\", other)\n\n-- note: same goes for str, int, dbl and bool\nlocal otherCopy = data:obj(\"objOrArray\")\n```\n\n#### Templates\nOutput produced by Krabby can be generated using `Inja` templates by passing a filepath and a JSON object with data:\n```\nlocal output = template:render_file(\"templates/index.j2\", data)    \nprint(output)\n```\n\n#### Timers\nTimers can be set to fire like so:\n```\nlocal t = timer.new(\n    function()\n        print(\"timer fired\")\n    end)\n\nt:once(1.23)\n```\n\n#### Key-Value Storage\nKrabby creates and maintains an sqlite3 database which can be used as a high-efficient key-value storage.\nIt operates on `strings`, `arrays of strings` (string_vector) or `JSON objects`.\n\nExample using `JSON` directly:\n```\n-- loads a JSON array with fallback to empty array\nlocal records = storage:load(\"your_key\", json.array())\n\nlocal data = json.new()\ndata:str(\"name\", \"Krabby\")\ndata:int(\"age\", 420)\n\n-- add a new record and save it back to storage\nrecords:push_back(data)\nstorage:save(\"your_key\", records)\n```\n\nExample using `string_vector`:\n```\nlocal data = storage:load(\"your key\", string_vector.new())\nlocal new_user = json.new()\nnew_user:str(\"name\", name)\n\nlocal new_key = generate_key(16)        \nstorage:save(new_key, new_user) -- save JSON object under key\n        \ndata:push_back(new_key)\nstorage:save(\"list key\", data)\n```\n\nRemoving data:\n```\n-- `user_key` is a string key for an existing user\nstorage:remove(user_key) -- remove the JSON object itself\nstorage:remove(\"user list key\", user_key) -- remove it from a string_vector list of users\n```\n\n#### Live Reload/Recompile\nKrabby is maintaining two contexts, one `master` and one `staging` context. You can reload the staging context at any time by using `Reload()` anywhere in your Lua code. This will rediscover and recompile all lua scripts under `data root path` and if everything compiles fine it will swap the current `master` context with the newly created `staging`:\n\n```\nlocal output = Reload()\nif #output \u003e 0 then\n    print(\"compilation errors\", output)\nend\n```\n\n#### Basic HTTP\n##### Writing Responses\nOnce you will learn about routes below you will know how to apply these functions, but for now here is what is available for writing data back to clients:\n```\nrespond(who, 200, \"text/html\", \"\u003chtml\u003e\u003cbody\u003eplain html data\u003c/body\u003e\u003c/html\u003e\")\nrespond_html(who, 404, \"\u003cp\u003ewrapped html 404 page\u003c/p\u003e\")\nrespond_text(who, 401, \"not authorized text here\")\nrespond_msg(who, \"arbitrary text data for websocket\")\n```\n\n##### Mountpoints\nMountpoints are used to expose static content at a given location on the filesystem. The paths are relative to `data root` specified at startup.\n\nTo expose `data/root/path/public` at `/public/*` on your server you can do this:\n```\nMount( \"/public\", \"public\" )\n```\n\n##### Routes\nRoutes can be used to setup dynamic endpoints. For example to make a RESTful API.\nSupported routes are \n* Get\n* Post\n* Delete \n* Put \n* Patch\n\nThe following example sets up a route at `/krabby/[3-16 characters long string without spaces]` that will be expecting `par1` and `par2` to be passed in the query string (i.e. `localhost:8080/krabby/hello?par1=first\u0026par2=second`). If the parameters are not passed Krabby will automatically return an error page. All the parameters passed to this route will end up in `params` regardless of them being required or not.\nThe `matches` table will contain all the matches for the route path regular expression.\n```\nGet( \"/krabby/(\\\\w{3,16})\", {\"par1\", \"par2\"},\n    function(who, req, matches, params)\n        -- if this was called via 'localhost:8080/krabby/hello?par1=first\u0026par2=second'\n        -- matches[1] == \"/krabby/hello\"\n        -- matches[2] == \"hello\"\n        -- params[\"par1\"] == \"first\"\n        -- params[\"par2\"] == \"second\"\n    end )\n```\n\n*Note:* the route path does not have to be a `regular expression`\n\n*Note:* if you don't require any parameters just pass `{}` for the list.\n\n#### WebSockets\nWebSocket communication is possible in Krabby. The `upgrade` function upgrades a HTTP socket to WebSocket. It accepts two functions as its arguments: a onMessage callback and a onDisconnect callback.\nHere is an example of the server script for a WebSocket API:\n```\nGet( \"/api\", {},\n    function(who, req, matches, params)\n    who:upgrade(\n        function(msg)\n            respond_msg(who, \"hello\") -- send a message                \n            return true -- you need to return true to keep the connection alive                \n        end,\n        function()\n            print(\"web socket closed\")\n        end )\n    end )\n```\n\n*Note:* Proper documentation will be written eventually.\n\n##### Handling Disconnect\nWhen a connection is established via a route it's expected that your code does one of the following:\n- write a response with one of the functions listed in the corresponding section\n- call `upgrade` to initiate WebSocket communication\n- call `postpone_response` if you need more time to generate a response (e.g. via timer or a client request)\n\n*NOTE:* If none of the above was done the client will automatically receive a `Not found` response.\n\nThe function that was setup with `postpone_response` on its respective `who` will be called on disconnect:\n```\nwho:postpone_response(\n    function()\n        -- code to handle disconnect of who\n    end )\n```\n\n#### Client Requests\nYou can also fetch data from a remote server using `ClientGet`. This works for both `http` and `https`:\n\n```\nhandle = ClientGet(\"https://yourhost.com/api.json\", \n    function(resp) -- called on response                \n        local data = json.parse(resp.body)        \n        local output = template:render_file(\"templates/mytemplate.j2\", data)\n        respond(who, 200, \"text/html\", output)\n    end, \n    function(err) -- called on error\n        respond_html(who, 500, \"Could not query api: \"..err)        \n    end )\n\n-- to cancel the request:\nhandle:cancel()\n```\n\n*Note:* The request will automatically get destroyed with no callbacks if it is not saved in a variable/table.\n\n*Note:* See `examples/scripts/http_request.lua` for a more detailed example.\n\n#### Utils\nThere are a few utils included with Krabby\n* generate_key(size) - generates a `size` long random alphanumeric key \n* hash_sha1(str) - computes sha1 for a string (raw bytes)\n* hmac_sha1(str, secret) - computes hmac-sha1 for a string with a shared secret\n* string_to_hex(bytes) - computes a hex string for input bytes\n* escape_html(html) - escapes html string\n\n*Note:* See `examples/scripts/utils.lua` for usage examples.\n\n### Powered by:\n* C++17\n* https://github.com/hrissan/crablib\n* https://github.com/GVNG/SQLCPPBridgeFramework\n* https://github.com/ThePhD/sol2\n* https://github.com/lua/lua (thru sol2)\n* https://github.com/pantor/inja.git\n* https://github.com/nlohmann/json (thru inja)\n* https://github.com/jarro2783/cxxopts.git\n* https://github.com/fmtlib/fmt  \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgodexsoft%2Fkrabby","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgodexsoft%2Fkrabby","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgodexsoft%2Fkrabby/lists"}