module pop_handlers
import pop_routes
-import json
+import csv
# Class handler for a route.
#
# 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
# 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.
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)
# Write data in body response and send it.
fun send(raw_data: nullable Writable, status: nullable Int) do
if raw_data != null then
- body += raw_data.write_to_string
+ body = raw_data
end
if status != null then
status_code = status
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