diff options
Diffstat (limited to 'src/guff/handlers/api.cr')
-rw-r--r-- | src/guff/handlers/api.cr | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/src/guff/handlers/api.cr b/src/guff/handlers/api.cr new file mode 100644 index 0000000..77606ae --- /dev/null +++ b/src/guff/handlers/api.cr @@ -0,0 +1,148 @@ +require "json" +require "../handler" +require "../api/*" +require "../views/html/api-docs" + +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 + +class Guff::Handlers::APIHandler < Guff::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) + Guff::APIDocsHTMLView.run(context) + end +end |