I have heard about Luvit for a long time, but I never get deep into it until recently. Luvit is a nodejs style lua libray with callback hell Asynchronous feature by Tim Caswell :) , it works well in most of the platforms, it's small and fast. It's really an interesting pramgraming language, and it's very easy to learn.
sample code of luvit:
local http = require('http')
http.createServer(function (req, res)
res:writeHead(200, {['Content-Type'] = 'text/plain'})
res:finish('Hello World\n')
end):listen(1337, '127.0.0.1')
print('Server running at http://127.0.0.1:1337/')
looks right like nodejs, right?
So I write a http framework library base on http module, it's luvit-mooncake. I'm trying to make it looks like connect
or express
framework of nodejs as possible as I can. and below is the demo usage of luvit-mooncake:
Intro:
Firstly, you can install luvit-mooncake
with npm(yes, it's npm).
npm install mooncake
Then you can use mooncake in your lua file:
local MoonCake = require("./node_modules/mooncake")
local server = MoonCake()
-- route your application
server:get("/", function(req, res)
local content = "<p>Hello world from MoonCake</p>"
res:send(content, 200)
end)
server:start(8080)
Router:
you can route your application by calling server:get
, server:post
, server:put
, server:delete
directly like the sample code above, or you can add your route in this way:
server:route({
["get"] = {
["/users/:id"] = function(q, s)
s:send("List User in Databases => " .. q.params.id)
end
}
})
avaialble method for route: "get", "post", "put", "delete" and "all", all
means any method will be routed.
server:all("/hello", function(q, s)
s:send("HELLO!")
end)
server:get("/admin", function(q, s)
-- if user not login then
s:redirect("/login")
end)
Response:
extra method for response res
:
- res:send
res:send("Hello world!")
- res:redirect
res:redirect("/login")
- res:render
res:render('./view/index.html')
see renderer below
- res:status
res:status(404):render("/view/404.html")
Request
You can get post data via req.body, get query data(such as "/users?page=1") via req.query.page
req.body
server:post("/posts/new", function(req,res)
if req.body.title and req.body.content then
print("new post")
-- Save to DB:
-- DB.save("post", {title = req.body.title, content = req.body.content})
res:redirect("/posts")
end
end)
req.params
server:get("/posts/:id", function(req, res)
post = DB.find("post", {id = req.params.id})
res:render("./view/post.html", {post = post})
end)
req.query
-- [GET] 'http://example.com/posts?page=4'
server:get("/posts", function(req, res)
local page = req.query.page
local skip = (page-1) * 10 --(10 post per page)
res:render("./view/post-list.html", {
post = DB.find("post", {
skip = skip,
limit = 10
})
})
end)
renderer
create a html file with content like this:
{(header.html)} <!--import layout-->
<h1>Post List</h1>
<ul class='posts'>
<!--loop in content with lua syntax style. -->
{% for _, post in ipairs(posts) do %}
<li>
<h2>{{post.title}}</h2>
<p>{{post.content}}</p>
</li>
{% end %}
</ul>
{(footer.html)}
Template renderer powered by https://github.com/bungle/lua-resty-template/ , you can use it simply with res:render(TEMPLATEPATH, CONTEXT)
:
You can get more about render template syntax at: https://github.com/bungle/lua-resty-template/ .
server:get("/posts", function(req,res)
-- get post list, render template.
res:render("./view/post-list.html", {posts = DB.find("posts")})
end)
Static files:
One more thing, static server for static files!
root
option means mount path,
for example: "/static/" means url path will be "http://example.com/static/file.ext"
server:static("./public/", {
root = "/static/",
maxAge = 31536000 -- one year
})
Start Server:
Start your server: (server:start
must be called lastly.)
server:start(8080)
Now you can open your browser with url: http://localhost:8080, here we go!
If you are interested in this project, please don't hesitate to let me know. All stars, comments, suggestions, contributions and Pull Requests are welcome :)
Fork me at github!