popcorn :: Router :: defaultinit
# Mountable routers
#
# Use the `Router` class to create modular, mountable route handlers.
# A Router instance is a complete middleware and routing system; for this reason,
# it is often referred to as a “mini-app”.
#
# The following example creates a router as a module, loads a middleware handler in it,
# defines some routes, and mounts the router module on a path in the main app.
#
# ~~~
# class AppHome
# super Handler
#
# redef fun get(req, res) do res.send "Site Home"
# end
#
# class UserLogger
# super Handler
#
# redef fun all(req, res) do print "User logged"
# end
#
# class UserHome
# super Handler
#
# redef fun get(req, res) do res.send "User Home"
# end
#
# class UserProfile
# super Handler
#
# redef fun get(req, res) do res.send "User Profile"
# end
#
# var user_router = new Router
# user_router.use("/*", new UserLogger)
# user_router.use("/", new UserHome)
# user_router.use("/profile", new UserProfile)
#
# var app = new App
# app.use("/", new AppHome)
# app.use("/user", user_router)
# ~~~
#
# The app will now be able to handle requests to /user and /user/profile, as well
# as call the `Time` middleware handler that is specific to the route.
class Router
super Handler
# List of handlers to match with requests.
private var handlers = new Map[AppRoute, Handler]
# List of handlers to match before every other.
private var pre_handlers = new Map[AppRoute, Handler]
# List of handlers to match after every other.
private var post_handlers = new Map[AppRoute, Handler]
# Register a `handler` for a route `path`.
#
# Route paths are matched in registration order.
fun use(path: String, handler: Handler) do
var route = build_route(handler, path)
handlers[route] = handler
end
# Register a pre-handler for a route `path`.
#
# Prehandlers are matched before every other handlers in registrastion order.
fun use_before(path: String, handler: Handler) do
var route = build_route(handler, path)
pre_handlers[route] = handler
end
# Register a post-handler for a route `path`.
#
# Posthandlers are matched after every other handlers in registrastion order.
fun use_after(path: String, handler: Handler) do
var route = build_route(handler, path)
post_handlers[route] = handler
end
redef fun handle(route, uri, req, res) do
if not route.match(uri) then return
handle_pre(route, uri, req, res)
handle_in(route, uri, req, res)
handle_post(route, uri, req, res)
end
private fun handle_pre(route: AppRoute, uri: String, req: HttpRequest, res: HttpResponse) do
for hroute, handler in pre_handlers do
handler.handle(hroute, route.uri_root(uri), req, res)
end
end
private fun handle_in(route: AppRoute, uri: String, req: HttpRequest, res: HttpResponse) do
for hroute, handler in handlers do
handler.handle(hroute, route.uri_root(uri), req, res)
if res.sent then break
end
end
private fun handle_post(route: AppRoute, uri: String, req: HttpRequest, res: HttpResponse) do
for hroute, handler in post_handlers do
handler.handle(hroute, route.uri_root(uri), req, res)
end
end
private fun build_route(handler: Handler, path: String): AppRoute do
if handler isa Router or handler isa StaticHandler then
return new AppGlobRoute(path)
else if path.has_suffix("*") then
return new AppGlobRoute(path)
else
return new AppParamRoute(path)
end
end
end
lib/popcorn/pop_handlers.nit:264,1--381,3