Property definitions

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