From a8beeed0e3df3463b467476f27bdf2f110e2b0f6 Mon Sep 17 00:00:00 2001 From: ricksterhd123 Date: Wed, 31 Jan 2024 04:02:54 +0000 Subject: [PATCH] Update README.md + add screenshot --- README.md | 39 ++++++++++++++++++--------------------- image.png | Bin 0 -> 26373 bytes 2 files changed, 18 insertions(+), 21 deletions(-) create mode 100644 image.png diff --git a/README.md b/README.md index 9ac7e50..2d16bdb 100755 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # mruv -mruv = mruby + libuv +**mruv = mruby + libuv** + +> mruv is a proof-of-concept for a scriptable web server using mruby. It's designed as single binary toolkit for creating (hopefully fast and secure) dynamic web applications. ## System Requirements - git @@ -16,26 +18,21 @@ TBC... ## TODO - [x] statically linked mruby + libuv (single binary) - [x] proof of concept ruby dsl scripting for callbacks to events, similar to ruby rack config.ru +- [x] libuv TCP socket handling +- [x] http request parsing & response generation +- [x] proof of concept testing in postman +- [] improve c handling + research valgrind / ASAT and other dynamic memory testing tools +- [] unit testing +- [] JSON handling library +- [] MIME handling +- [] chunked content + streaming + +## Examples +![Return the request body reversed](image.png) + +`config.rb` ```rb -## -# mruv socket handler function fizzbuzz example -# -def handler(env) - n = env.chomp.to_i - if n > 0 and n < 100 then - if n % 15 == 0 then - "fizzbuzz" - elsif n % 3 == 0 then - "fizz" - elsif n % 5 == 0 then - "buzz" - else - env - end - else - "Must be number between 1 and 99" - end +def handler(body) + body.reverse end - ``` -- [ ] support libuv TCP/IP and maybe some file stuff diff --git a/image.png b/image.png new file mode 100644 index 0000000000000000000000000000000000000000..4436a1df7a47a03b19d3f0248fd1eb0a0c6393c2 GIT binary patch literal 26373 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 literal 0 HcmV?d00001