aboutsummaryrefslogtreecommitdiff
path: root/src/guff/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'src/guff/handlers')
-rw-r--r--src/guff/handlers/api-handler.cr149
-rw-r--r--src/guff/handlers/blog-handler.cr106
-rw-r--r--src/guff/handlers/not-found-handler.cr10
-rw-r--r--src/guff/handlers/test-handler.cr14
4 files changed, 279 insertions, 0 deletions
diff --git a/src/guff/handlers/api-handler.cr b/src/guff/handlers/api-handler.cr
new file mode 100644
index 0000000..274e137
--- /dev/null
+++ b/src/guff/handlers/api-handler.cr
@@ -0,0 +1,149 @@
+require "json"
+require "./handler"
+require "./api/*"
+
+private macro define_method_calls(hash)
+ case namespace
+ {% for namespace, methods in hash %}
+ when "{{ namespace.id }}"
+ case method
+ {% for method in methods %}
+ when "{{ method }}"
+ do_{{ namespace.id }}_{{ method }}(context, get_method_args(
+ context.request.query_params,
+ "{{ namespace.id }}",
+ "{{ method.id }}"
+ )).to_json
+ {% end %}
+ else
+ raise "unknown method"
+ end
+ {% end %}
+ else
+ raise "unknown namespace"
+ end
+end
+
+module Guff
+ class APIHandler < Handler
+ include API::Methods
+ include API::ContentType
+ include API::Util
+ include API::PostAPI
+ include API::DirAPI
+ include API::FileAPI
+ include API::TagAPI
+ include API::SiteAPI
+ include API::TestAPI
+
+ PATH_RE = %r{
+ ^/api
+
+ (?:
+ # method call
+ (?:
+ /
+ (?<namespace>[a-z0-9_-]+)
+ /
+ (?<method>[a-z0-9_]+)
+ )
+
+ |
+
+ # index.html
+ /(?:index(?:\.html|)|)
+
+ |
+
+ # implicit index (no trailing slash)
+ )
+
+ $
+ }mx
+
+ def call(context : HTTP::Server::Context)
+ if md = (context.request.path || "").match(PATH_RE)
+ if md["namespace"]?
+ # method call
+ do_call(context, md["namespace"], md["method"])
+ else
+ # api index
+ do_docs(context)
+ end
+ else
+ call_next(context)
+ end
+ end
+
+ private def do_call(
+ context : HTTP::Server::Context,
+ namespace : String,
+ method : String
+ )
+ # set response type
+ context.response.content_type = get_content_type
+
+ # method call
+ json = begin
+ #
+ # macro expands to equivalent of the following for each
+ # namespace and method:
+ #
+ # args = get_method_args(context, namespace, method)
+ # send("do_#{namespace}_#{method}".intern, context, args)
+ #
+ define_method_calls({
+ post: [
+ get_posts,
+ add_post,
+ update_post,
+ remove_posts,
+ set_tags,
+ ],
+
+ dir: [
+ add,
+ remove,
+ ],
+
+ file: [
+ add,
+ remove,
+ ],
+
+ tag: [
+ get_tags,
+ remove_tags,
+ ],
+
+ site: [
+ add_site,
+ remove_sites,
+ set_default,
+ set_domains,
+ ],
+
+ test: [
+ version,
+ get_posts,
+ error,
+ ],
+ })
+ rescue e
+ # log backtrace
+ # FIXME
+ puts e.inspect_with_backtrace
+
+ # return error to user
+ { "error": e.to_s }.to_json
+ end
+
+ # send body
+ context.response.puts json
+ end
+
+ private def do_docs(context : HTTP::Server::Context)
+ APIDocsHTMLView.run(context)
+ end
+ end
+end
diff --git a/src/guff/handlers/blog-handler.cr b/src/guff/handlers/blog-handler.cr
new file mode 100644
index 0000000..988eab5
--- /dev/null
+++ b/src/guff/handlers/blog-handler.cr
@@ -0,0 +1,106 @@
+require "./handler"
+
+module Guff
+ class BlogHandler < Handler
+ ROUTES = [{
+ list: false,
+ blog: true,
+ re: %r{
+ ^/
+
+ # match YYYY/MM/DD/SLUG.html
+ (?<year>\d{4})
+ /
+ (?<month>\d{2})
+ /
+ (?<day>\d{2})
+ /
+ (?<slug>[a-z0-9._-]+)
+ \.html
+
+ $
+ }x,
+ }, {
+ list: true,
+ blog: true,
+ re: %r{
+ ^/
+
+ # match YYYY/MM/DD
+ (?<year>\d{4})
+ /
+ (?<month>\d{2})
+ /
+ (?<day>\d{2})
+ /?
+
+ $
+ }x,
+ }, {
+ list: true,
+ blog: true,
+ re: %r{
+ ^/
+
+ # match YYYY/MM
+ (?<year>\d{4})
+ /
+ (?<month>\d{2})
+ /?
+
+ $
+ }x,
+ }, {
+ list: true,
+ blog: true,
+ re: %r{
+ ^/
+
+ # match YYYY
+ (?<year>\d{4})
+ /?
+
+ $
+ }x,
+ }, {
+ list: false,
+ blog: false,
+ re: %r{
+ ^/
+
+ # match slug
+ (?<slug>[a-z0-9._-]+)
+ \.html
+
+ $
+ }x,
+ }, {
+ list: true,
+ blog: true,
+ re: %r{
+ # match index
+ ^/$
+ }x,
+ }]
+
+ def call(context : HTTP::Server::Context)
+ path = context.request.path || ""
+
+ call_next(context) unless ROUTES.reduce(false) do |matched, route|
+ unless matched
+ if md = (route[:re] as Regex).match(path)
+ # matched route
+ matched = true
+
+ context.response.puts "blog: route = %s, md = %s" % [
+ route.to_s,
+ md.to_s
+ ]
+ end
+ end
+
+ matched
+ end
+ end
+ end
+end
diff --git a/src/guff/handlers/not-found-handler.cr b/src/guff/handlers/not-found-handler.cr
new file mode 100644
index 0000000..b15b1dc
--- /dev/null
+++ b/src/guff/handlers/not-found-handler.cr
@@ -0,0 +1,10 @@
+require "./handler"
+
+module Guff
+ class NotFoundHandler < Handler
+ def call(context : HTTP::Server::Context)
+ context.response.status_code = 404
+ context.response.puts "not found"
+ end
+ end
+end
diff --git a/src/guff/handlers/test-handler.cr b/src/guff/handlers/test-handler.cr
new file mode 100644
index 0000000..3856400
--- /dev/null
+++ b/src/guff/handlers/test-handler.cr
@@ -0,0 +1,14 @@
+require "./handler"
+
+module Guff
+ class TestHandler < Handler
+ def call(context : HTTP::Server::Context)
+ if ((context.request.path || "").match(/^\/test\//))
+ context.response.content_type = "text/html"
+ context.response.puts "test"
+ else
+ call_next(context)
+ end
+ end
+ end
+end