commit 2eaf44195e8286e42f8839eb42792a2198ffa01f Author: Juan Wajnerman Date: Wed Jun 11 20:41:02 2014 -0300 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d1f2bed --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.crystal diff --git a/samples/hello_world.cr b/samples/hello_world.cr new file mode 100644 index 0000000..be1ac36 --- /dev/null +++ b/samples/hello_world.cr @@ -0,0 +1,5 @@ +require "../src/frank" + +get "/" do + "Hello World!" +end diff --git a/spec/route_spec.cr b/spec/route_spec.cr new file mode 100644 index 0000000..eeb2a4f --- /dev/null +++ b/spec/route_spec.cr @@ -0,0 +1,16 @@ +require "spec_helper" + +describe "Route" do + describe "match" do + it "doesn't match" do + route = Route.new("/foo/bar", nil) + route.match(nil, "/foo/baz".split("/")).should be_nil + end + + it "matches" do + route = Route.new("/foo/:one/path/:two", nil) + request = route.match(nil, "/foo/uno/path/dos".split("/")) + request.not_nil!.params.should eq({"one" => "uno", "two" => "dos"}) + end + end +end diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr new file mode 100644 index 0000000..f84647b --- /dev/null +++ b/spec/spec_helper.cr @@ -0,0 +1,4 @@ +require "spec" +require "../src/frank/*" + +include Frank diff --git a/src/frank.cr b/src/frank.cr new file mode 100644 index 0000000..31e8fb2 --- /dev/null +++ b/src/frank.cr @@ -0,0 +1,21 @@ +require "option_parser" +require "./frank/*" + +$frank_handler = Frank::Handler.new +port = 3000 + +OptionParser.parse! do |opts| + opts.on("-p ", "--port ", "port") do |opt_port| + port = opt_port.to_i + end +end + +at_exit do + handlers = [] of HTTP::Handler + handlers << HTTP::LogHandler.new + handlers << $frank_handler + server = HTTP::Server.new(port, HTTP::Server.build_middleware handlers) + + puts "Listening on http://0.0.0.0:#{port}" + server.listen +end diff --git a/src/frank/dsl.cr b/src/frank/dsl.cr new file mode 100644 index 0000000..c10da40 --- /dev/null +++ b/src/frank/dsl.cr @@ -0,0 +1,3 @@ +def get(path, &block : Frank::Request -> String) + $frank_handler.add_route(path, block) +end diff --git a/src/frank/handler.cr b/src/frank/handler.cr new file mode 100644 index 0000000..b8edd26 --- /dev/null +++ b/src/frank/handler.cr @@ -0,0 +1,34 @@ +require "net/http" + +class Frank::Handler < HTTP::Handler + def initialize + @routes = [] of Route + end + + def call(request) + if body = exec_request(request) + begin + HTTP::Response.new("HTTP/1.1", 200, "OK", {"Content-Type" => "text/plain"}, body) + rescue ex + HTTP::Response.new("HTTP/1.1", 500, "Internal Server Error", {"Content-Type" => "text/plain"}, ex.to_s) + end + else + HTTP::Response.new("HTTP/1.1", 404, "Not Found", {"Content-Type" => "text/plain"}, "Not Found") + end + end + + def add_route(path, handler) + @routes << Route.new(path, handler) + end + + def exec_request(request) + components = request.path.split "/" + @routes.each do |route| + frank_request = route.match(request, components) + if frank_request + return route.handler.call(frank_request) + end + end + nil + end +end diff --git a/src/frank/request.cr b/src/frank/request.cr new file mode 100644 index 0000000..0150e69 --- /dev/null +++ b/src/frank/request.cr @@ -0,0 +1,6 @@ +class Frank::Request + getter params + + def initialize(@params) + end +end diff --git a/src/frank/route.cr b/src/frank/route.cr new file mode 100644 index 0000000..ad0e4bc --- /dev/null +++ b/src/frank/route.cr @@ -0,0 +1,25 @@ +class Frank::Route + getter handler + + def initialize(path, @handler) + @components = path.split "/" + end + + def match(request, components) + return nil unless components.length == @components.length + + params = nil + + @components.zip(components) do |route_component, req_component| + if route_component.starts_with? ':' + params ||= {} of String => String + params[route_component[1 .. -1]] = req_component + else + return nil unless route_component == req_component + end + end + + params ||= {} of String => String + Request.new(params) + end +end