189 lines
5.0 KiB
Lua
189 lines
5.0 KiB
Lua
-- Example HTTP server with string-based routing, parameters, and wildcards
|
|
|
|
print("Starting Moonshark HTTP server with string routing...")
|
|
|
|
-- Start HTTP server
|
|
http.listen(3000)
|
|
|
|
-- Home page
|
|
http.route("GET", "/", function(req)
|
|
local visits = session.get("visits") or 0
|
|
visits = visits + 1
|
|
session.set("visits", visits)
|
|
|
|
return http.html([[
|
|
<h1>Welcome to Moonshark!</h1>
|
|
<p>You've visited this page ]] .. visits .. [[ times.</p>
|
|
<p><a href="/login">Login</a> | <a href="/users/123">User Profile</a></p>
|
|
<p><a href="/api/test">API Test</a> | <a href="/files/docs/readme.txt">File Access</a></p>
|
|
]])
|
|
end)
|
|
|
|
-- User profile with dynamic parameter
|
|
http.route("GET", "/users/:id", function(req)
|
|
local userId = req.params.id
|
|
return http.html([[
|
|
<h2>User Profile</h2>
|
|
<p>User ID: ]] .. userId .. [[</p>
|
|
<p><a href="/users/]] .. userId .. [[/posts">View Posts</a></p>
|
|
<p><a href="/">Home</a></p>
|
|
]])
|
|
end)
|
|
|
|
-- User posts with multiple parameters
|
|
http.route("GET", "/users/:id/posts", function(req)
|
|
local userId = req.params.id
|
|
return http.json({
|
|
user_id = userId,
|
|
posts = {
|
|
{id = 1, title = "First Post", content = "Hello world!"},
|
|
{id = 2, title = "Second Post", content = "Learning Lua routing!"}
|
|
}
|
|
})
|
|
end)
|
|
|
|
-- Blog post with slug parameter
|
|
http.route("GET", "/blog/:slug", function(req)
|
|
local slug = req.params.slug
|
|
return http.html([[
|
|
<h1>Blog Post: ]] .. slug .. [[</h1>
|
|
<p>This is the content for blog post "]] .. slug .. [["</p>
|
|
<p><a href="/blog/]] .. slug .. [[/comments">View Comments</a></p>
|
|
<p><a href="/">Home</a></p>
|
|
]])
|
|
end)
|
|
|
|
-- Blog comments
|
|
http.route("GET", "/blog/:slug/comments", function(req)
|
|
local slug = req.params.slug
|
|
return http.json({
|
|
blog_slug = slug,
|
|
comments = {
|
|
{author = "Alice", comment = "Great post!"},
|
|
{author = "Bob", comment = "Very informative."}
|
|
}
|
|
})
|
|
end)
|
|
|
|
-- Wildcard route for file serving
|
|
http.route("GET", "/files/*path", function(req)
|
|
local filePath = req.params.path
|
|
return http.html([[
|
|
<h2>File Access</h2>
|
|
<p>Requested file: ]] .. filePath .. [[</p>
|
|
<p>In a real application, this would serve the file content.</p>
|
|
<p><a href="/">Home</a></p>
|
|
]])
|
|
end)
|
|
|
|
-- API endpoints with parameters
|
|
http.route("GET", "/api/users/:id", function(req)
|
|
local userId = req.params.id
|
|
return http.json({
|
|
id = tonumber(userId),
|
|
name = "User " .. userId,
|
|
email = "user" .. userId .. "@example.com",
|
|
active = true
|
|
})
|
|
end)
|
|
|
|
http.route("PUT", "/api/users/:id", function(req)
|
|
local userId = req.params.id
|
|
local userData = req.form
|
|
|
|
return http.json({
|
|
success = true,
|
|
message = "User " .. userId .. " updated",
|
|
data = userData
|
|
})
|
|
end)
|
|
|
|
http.route("DELETE", "/api/users/:id", function(req)
|
|
local userId = req.params.id
|
|
return http.json({
|
|
success = true,
|
|
message = "User " .. userId .. " deleted"
|
|
})
|
|
end)
|
|
|
|
-- Login form with CSRF protection
|
|
http.route("GET", "/login", function(req)
|
|
return http.html([[
|
|
<h2>Login</h2>
|
|
<form method="POST" action="/login">
|
|
]] .. csrf.field() .. [[
|
|
<input type="text" name="username" placeholder="Username" required><br>
|
|
<input type="password" name="password" placeholder="Password" required><br>
|
|
<button type="submit">Login</button>
|
|
</form>
|
|
<p><a href="/">Home</a></p>
|
|
]])
|
|
end)
|
|
|
|
-- Handle login POST
|
|
http.route("POST", "/login", function(req)
|
|
if not csrf.validate() then
|
|
http.status(403)
|
|
return "CSRF token invalid"
|
|
end
|
|
|
|
local username = req.form.username
|
|
local password = req.form.password
|
|
|
|
if username == "admin" and password == "secret" then
|
|
session.set("user", username)
|
|
session.flash("success", "Login successful!")
|
|
return http.redirect("/dashboard")
|
|
else
|
|
session.flash("error", "Invalid credentials")
|
|
return http.redirect("/login")
|
|
end
|
|
end)
|
|
|
|
-- Dashboard (requires login)
|
|
http.route("GET", "/dashboard", function(req)
|
|
local user = session.get("user")
|
|
if not user then
|
|
return http.redirect("/login")
|
|
end
|
|
|
|
local success = session.get_flash("success")
|
|
local error = session.get_flash("error")
|
|
|
|
return http.html([[
|
|
<h2>Dashboard</h2>
|
|
]] .. (success and ("<p style='color:green'>" .. success .. "</p>") or "") .. [[
|
|
]] .. (error and ("<p style='color:red'>" .. error .. "</p>") or "") .. [[
|
|
<p>Welcome, ]] .. user .. [[!</p>
|
|
<p><a href="/logout">Logout</a></p>
|
|
<p><a href="/">Home</a></p>
|
|
]])
|
|
end)
|
|
|
|
-- Logout
|
|
http.route("GET", "/logout", function(req)
|
|
session.set("user", nil)
|
|
session.flash("info", "You have been logged out")
|
|
return http.redirect("/")
|
|
end)
|
|
|
|
-- Catch-all route for 404s (must be last)
|
|
http.route("GET", "*path", function(req)
|
|
http.status(404)
|
|
return http.html([[
|
|
<h1>404 - Page Not Found</h1>
|
|
<p>The requested path "]] .. req.params.path .. [[" was not found.</p>
|
|
<p><a href="/">Go Home</a></p>
|
|
]])
|
|
end)
|
|
|
|
print("Server configured with string routing. Listening on http://localhost:3000")
|
|
print("Try these routes:")
|
|
print(" GET /")
|
|
print(" GET /users/123")
|
|
print(" GET /users/456/posts")
|
|
print(" GET /blog/my-first-post")
|
|
print(" GET /blog/lua-tutorial/comments")
|
|
print(" GET /files/docs/readme.txt")
|
|
print(" GET /api/users/789")
|
|
print(" GET /nonexistent (404 handler)") |