Notice: This repository is no longer maintained. Kemal does pretty much what Moonshine does and it has better documentation.
Moonshine is a minimal sinatra like web framework for the Crystal language.
Add this to your application's shard.yml
:
dependencies:
moonshine:
github: dhruvrajvanshi/Moonshine
Code speaks louder than words, so here's an example.
require "moonshine"
include Moonshine
include Moonshine::Utils::Shortcuts
include Moonshine
app = App.new
# respond to all HTTP verbs
app.route "/", do |request|
ok("Hello Moonshine!")
end
# or particular HTTP verbs
app.get "/get", do |request|
ok("This is a get response")
end
# you can set response headers
app.get "/api", do |request|
res = ok("{\"name\": \"moonshine\"}")
res.headers["Content-type"] = "text/json"
res
end
app.run(8000)
Moonshine automatically parses POST and GET parameters for you. The get
and post
properties are hashes of these params.
app.get "/putparams", do |request|
ok("<h1>POST<h1><p>#{request.post}</p><h2>GET<h2><p>#{request.get}</p>")
end
Controllers are objects which can respond to multiple routes. Set the @rotuer instance variable of a controller to specify routing within controller. Add the controller to the app using app.controller method. @router maps between a route and an action. Action can be any object with a call method (usually a Proc).
# Inherit from Moonshine::Controller to define a controller
class HomeController < Moonshine::Controller
def initialize()
@viewcount = 0
@router = {
"GET /" => ->get(Request),
}
end
def get(req)
@viewcount += 1
ok("This page has been visited #{@viewcount} times.")
end
end
# Bind controller to the app object
app.controller "/", HomeController.new
An action can also be a string containing the method name provided that the method is defined in the controller, and the controller name symbol has been passed to the actions macro in the controller definition.
class PostController < Moonshine::Controller
actions :get_all_posts, :get_post
def initialize()
@posts = [
Post.new("Post1"),
Post.new("Post2")
] of Post
@router = {
"GET /posts" =>"get_all_posts",
"GET /posts/:id" => "get_post"
}
end
def get_post(req)
...
end
def get_all_posts(req)
...
end
end
app.controller(PostController.new)
String and proc actions can also be mixed in a single router.
You can either create middleware classes or individual methods that process request or response
You can add middleware classes to your application by inheriting from Moonshine::Middleware. Your class can override process_request and process_response methods to globally alter request and response objects.
class Hello < Moonshine::Middleware
def process_request(req)
req.headers["User"] = "Annonymous"
end
def process_response(req, res)
req.body += "\nFooter"
end
end
app.middleware_object Hello.new
# add request middleware
app.request_middleware do |req|
unless req.get.has_key? "user"
Moonshine::Http::Response.new(200, "Not allowed")
else
nil
end
end
To add a request middleware, call app.request_middleware with a block that returns a response or nil. If the method returns nil, the response chain continues, otherwise, the response is sent back.
# add response middleware
app.response_middleware do |req, res|
res.body = "Modified"
res
end
Response middleware methods take request and response arguments and return a response. This is used to globally alter the response of the application. Response middleware are processed in order.
0.3.0 : Renamed base module to core.
Aliased Moonshine::App = Moonshine::Core::App (Previously Moonshine::Base::App)
Aliased Moonshine::Controller = Moonshine::Core::Controller
Moved Moonshine::Middleware::Base => Moonshine::Core::Middleware
Aliased Moonshine::Middleware = Moonshine::Core::Middleware
Added Moonshine::Utils::StaticDirs middleware class. It can serve multiple directories