aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/guff/api-handler.cr122
-rw-r--r--src/guff/handler.cr3
-rw-r--r--src/guff/handlers.cr62
-rw-r--r--src/guff/model.cr1
-rw-r--r--src/guff/run.cr2
-rw-r--r--src/guff/server.cr31
-rw-r--r--src/guff/test-handler.cr14
7 files changed, 211 insertions, 24 deletions
diff --git a/src/guff/api-handler.cr b/src/guff/api-handler.cr
new file mode 100644
index 0000000..7928d3c
--- /dev/null
+++ b/src/guff/api-handler.cr
@@ -0,0 +1,122 @@
+require "./handler"
+
+module Guff
+ record APIContext,
+ context : HTTP::Server::Context,
+ model : Model
+
+ API = {
+ "posts": {
+ "get_posts": {
+ text: "Get posts matching query.",
+
+ args: {
+ "q": {
+ text: "Search string.",
+ type: :text,
+ required: false,
+ default: "",
+ },
+
+ "page": {
+ text: "Page number",
+ type: :int,
+ required: false,
+ default: "1",
+ },
+
+ "tags": {
+ text: "Comma-separated list of tags (union)",
+ type: :tags,
+ required: false,
+ default: "1",
+ },
+
+ "sort": {
+ text: "Sort order of results",
+ type: :sort,
+ required: false,
+ default: "date,desc",
+ },
+ },
+
+ method: ->(c : APIContext) {
+ "get_posts"
+ }
+ },
+ },
+ }
+
+ API_PATH_RE = %r{
+ ^/api
+
+ (?:
+ # method call
+ (?:
+ /
+ (?<namespace>[a-z0-9_-]+)
+ /
+ (?<method>[a-z0-9]+)
+ )
+
+ |
+
+ # index.html
+ /(?:index(?:\.html|)|)
+
+ |
+
+ # implicit index (no trailing slash)
+ )
+
+ $
+ }mx
+
+ class APIHandler < Handler
+ def call(context : HTTP::Server::Context)
+ if md = (context.request.path || "").match(API_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
+ )
+ # method call
+#
+# fn = API[namespace][method][:method] as Proc(APIContext, String)
+# context.response.puts fn.call(APIContext.new(context, @model))
+#
+ page = HTMLPageView.new(
+ "TODO: API Call",
+ "<p>API Call: namespace = %s, call = %s</p>" % [
+ namespace,
+ method
+ ]
+ )
+
+ context.response.content_type = page.content_type
+ context.response.puts page
+ end
+
+ private def do_docs(context : HTTP::Server::Context)
+ page = HTMLPageView.new(
+ "API Documentation",
+ "<p>API Documentation</p>"
+ )
+
+ context.response.content_type = page.content_type
+ context.response.puts page
+ end
+ end
+end
diff --git a/src/guff/handler.cr b/src/guff/handler.cr
index e665585..125e7e7 100644
--- a/src/guff/handler.cr
+++ b/src/guff/handler.cr
@@ -3,9 +3,8 @@ require "http/server"
module Guff
class Handler < ::HTTP::Handler
getter :model
- getter :config
- def initialize(@model : Model, @config : Config)
+ def initialize(@model : Model)
end
def call(context : HTTP::Server::Context)
diff --git a/src/guff/handlers.cr b/src/guff/handlers.cr
new file mode 100644
index 0000000..4ebeae7
--- /dev/null
+++ b/src/guff/handlers.cr
@@ -0,0 +1,62 @@
+require "http/server"
+require "./config"
+require "./model"
+require "./blog-handler"
+
+module Guff
+ module Handlers
+ HANDLERS = [{
+ # TODO: add production error handler
+ env: %w{development},
+ init: ->(model : Model) {
+ HTTP::ErrorHandler.new as HTTP::Handler
+ },
+ }, {
+ init: ->(model : Model) {
+ HTTP::LogHandler.new as HTTP::Handler
+ },
+ }, {
+ init: ->(model : Model) {
+ HTTP::DeflateHandler.new as HTTP::Handler
+ },
+ }, {
+ env: %w{development},
+ init: ->(model : Model) {
+ TestHandler.new(model) as HTTP::Handler
+ },
+ }, {
+ init: ->(model : Model) {
+ APIHandler.new(model) as HTTP::Handler
+ },
+ }, {
+ init: ->(model : Model) {
+ BlogHandler.new(model) as HTTP::Handler
+ },
+ }, {
+ init: ->(model : Model) {
+ SlugHandler.new(model) as HTTP::Handler
+ },
+ }, {
+ init: ->(model : Model) {
+ HTTP::StaticFileHandler.new(model.config["public"]) as HTTP::Handler
+ },
+ }, {
+ init: ->(model : Model) {
+ NotFoundHandler.new(model) as HTTP::Handler
+ },
+ }]
+
+ def self.get(model : Model) : Array(HTTP::Handler)
+ HANDLERS.select { |h|
+ if h.has_key?(:env)
+ (h[:env] as Array(String)).includes?(model.config["environment"])
+ else
+ true
+ end
+ }.map { |h|
+ init = (h[:init] as Proc(Model, HTTP::Handler))
+ init.call(model)
+ }
+ end
+ end
+end
diff --git a/src/guff/model.cr b/src/guff/model.cr
index 370229c..0bc0e78 100644
--- a/src/guff/model.cr
+++ b/src/guff/model.cr
@@ -1,5 +1,6 @@
module Guff
class Model
+ getter :config
getter :db
def initialize(@config : Config)
diff --git a/src/guff/run.cr b/src/guff/run.cr
index 2b7e966..90afbae 100644
--- a/src/guff/run.cr
+++ b/src/guff/run.cr
@@ -11,6 +11,6 @@ module Guff
model = Model.new(config)
# create and run server
- Server.run(model, config)
+ Server.run(model)
end
end
diff --git a/src/guff/server.cr b/src/guff/server.cr
index bc4494c..1d87db7 100644
--- a/src/guff/server.cr
+++ b/src/guff/server.cr
@@ -1,41 +1,30 @@
require "http/server"
require "./config"
require "./model"
-require "./blog-handler"
+require "./handlers"
module Guff
class Server
- def self.run(model : Model, config : Config)
- new(model, config).run
+ def self.run(model : Model)
+ new(model).run
end
- def initialize(@model : Model, @config : Config)
+ def initialize(@model : Model)
# create server
@server = HTTP::Server.new(
- config["host"],
- config["port"].to_i,
- get_handlers(model, config)
+ @model.config["host"],
+ @model.config["port"].to_i,
+ get_handlers(@model)
)
end
def run
- puts "listening on %s:%s" % %w{host port}.map { |k| @config[k] }
+ puts "listening on %s:%s" % %w{host port}.map { |k| @model.config[k] }
@server.listen
end
- private def get_handlers(
- model : Model,
- config : Config
- ) : Array(HTTP::Handler)
- @handlers ||= [
- HTTP::ErrorHandler.new,
- HTTP::LogHandler.new,
- HTTP::DeflateHandler.new,
- BlogHandler.new(model, config),
- SlugHandler.new(model, config),
- HTTP::StaticFileHandler.new(config["public"]),
- NotFoundHandler.new(model, config),
- ]
+ private def get_handlers(model : Model) : Array(HTTP::Handler)
+ @handlers ||= Handlers.get(model)
end
end
end
diff --git a/src/guff/test-handler.cr b/src/guff/test-handler.cr
new file mode 100644
index 0000000..3856400
--- /dev/null
+++ b/src/guff/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