X-Git-Url: http://nitlanguage.org diff --git a/lib/popcorn/pop_handlers.nit b/lib/popcorn/pop_handlers.nit index 2ce4755..e657d68 100644 --- a/lib/popcorn/pop_handlers.nit +++ b/lib/popcorn/pop_handlers.nit @@ -18,7 +18,7 @@ module pop_handlers import pop_routes -import json +import csv # Class handler for a route. # @@ -235,10 +235,16 @@ class StaticHandler # Static files directory to serve. var static_dir: String + # Default file to serve if nothing matches the request. + # + # `null` for no default file. + var default_file: nullable String + # Internal file server used to lookup and render files. var file_server: FileServer is lazy do var srv = new FileServer(static_dir) srv.show_directory_listing = false + srv.default_file = default_file return srv end @@ -307,6 +313,12 @@ class Router # 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. @@ -315,14 +327,48 @@ class Router 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) @@ -402,23 +448,26 @@ redef class HttpResponse send(html, status) end - # Write data as JSON and set the right content type header. - fun json(json: nullable Jsonable, status: nullable Int) do - header["Content-Type"] = media_types["json"].as(not null) - if json == null then + # Write data as CSV and set the right content type header. + fun csv(csv: nullable CsvDocument, status: nullable Int) do + header["Content-Type"] = media_types["csv"].as(not null) + if csv == null then send(null, status) else - send(json.to_json, status) + send(csv.write_to_string, status) end end # Redirect response to `location` + # + # Use by default 303 See Other as it is the RFC + # way to redirect web applications to a new URI. fun redirect(location: String, status: nullable Int) do header["Location"] = location if status != null then status_code = status else - status_code = 302 + status_code = 303 end check_sent sent = true