Web framework for Crystal language [DEPRECATED in favour of kemal]
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
getand
postproperties are hashes of these params.
app.get "/putparams", do |request| ok("POST
#{request.post}
GET
#{request.get}
") 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). ```crystal
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
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. ```crystal class PostController < Moonshine::Controller actions :getallposts, :getpost def initialize() @posts = [ Post.new("Post1"), Post.new("Post2") ] of Post @router = { "GET /posts" =>"getallposts", "GET /posts/:id" => "getpost" } end
def get_post(req) ... end
def getallposts(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 processrequest and processresponse methods to globally alter request and response objects. ```crystal class Hello < Moonshine::Middleware def process_request(req) req.headers["User"] = "Annonymous" end
def processresponse(req, res) req.body += "\nFooter" end end app.middlewareobject 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