diff --git a/spec/kemal_handler_spec.cr b/spec/kemal_handler_spec.cr index e288809..b338e8e 100644 --- a/spec/kemal_handler_spec.cr +++ b/spec/kemal_handler_spec.cr @@ -50,17 +50,4 @@ describe "Kemal::Handler" do response = kemal.call(request) response.headers["Content-Type"].should eq("application/json") end - - it "parses POST body" do - kemal = Kemal::Handler.new - kemal.add_route "POST", "/" do |env| - name = env.params["name"] - age = env.params["age"] - hasan = env.params["hasan"] - "Hello #{name} #{hasan} #{age}" - end - request = HTTP::Request.new("POST", "/?hasan=cemal", body: "name=kemal&age=99") - response = kemal.call(request) - response.body.should eq("Hello kemal cemal 99") - end end diff --git a/spec/logger_spec.cr b/spec/logger_spec.cr index 421a4f7..f5d0075 100644 --- a/spec/logger_spec.cr +++ b/spec/logger_spec.cr @@ -1,13 +1,11 @@ require "./spec_helper" describe "Logger" do - it "logs stuff" do - IO.pipe do |r,w| + IO.pipe do |r, w| logger = Kemal::Logger.new(w) logger.info "Info from logger" r.gets.should match(/Info from logger/) end end - end diff --git a/spec/param_parser_spec.cr b/spec/param_parser_spec.cr new file mode 100644 index 0000000..9f544f3 --- /dev/null +++ b/spec/param_parser_spec.cr @@ -0,0 +1,16 @@ +require "./spec_helper" + +describe "ParamParser" do + it "parses params" do + kemal = Kemal::Handler.new + kemal.add_route "POST", "/" do |env| + name = env.params["name"] + age = env.params["age"] + hasan = env.params["hasan"] + "Hello #{name} #{hasan} #{age}" + end + request = HTTP::Request.new("POST", "/?hasan=cemal", body: "name=kemal&age=99") + response = kemal.call(request) + response.body.should eq("Hello kemal cemal 99") + end +end diff --git a/spec/route_spec.cr b/spec/route_spec.cr index 3842654..e2b8e5b 100644 --- a/spec/route_spec.cr +++ b/spec/route_spec.cr @@ -4,18 +4,21 @@ describe "Route" do describe "match" do it "doesn't match because of route" do route = Route.new("GET", "/foo/bar") { "" } - route.match("GET", "/foo/baz".split("/")).should be_nil + request = HTTP::Request.new("GET", "/world?message=coco") + route.match?(request).should be_nil end it "doesn't match because of method" do route = Route.new("GET", "/foo/bar") { "" } - route.match("POST", "/foo/bar".split("/")).should be_nil + request = HTTP::Request.new("POST", "/foo/bar") + route.match?(request).should be_nil end it "matches" do route = Route.new("GET", "/foo/:one/path/:two") { "" } - params = route.match("GET", "/foo/uno/path/dos".split("/")) - params.should eq({"one" => "uno", "two" => "dos"}) + request = HTTP::Request.new("GET", "/foo/uno/path/dos") + match = route.match?(request) + match.should eq true end end end diff --git a/src/kemal/handler.cr b/src/kemal/handler.cr index 1db1586..527514f 100644 --- a/src/kemal/handler.cr +++ b/src/kemal/handler.cr @@ -20,21 +20,10 @@ class Kemal::Handler < HTTP::Handler def exec_request(request) components = request.path.not_nil!.split "/" @routes.each do |route| - params = route.match(request.method, components) - if params - if query = request.query - HTTP::Params.parse(query) do |key, value| - params[key] ||= value - end - end - - if body = request.body - HTTP::Params.parse(request.body.not_nil!) do |key, value| - params[key] ||= value - end - end - - context = Context.new(request, params) + match = route.match?(request) + if match + params = Kemal::Params.new(route, request).parse + context = Context.new(request, params.not_nil!) begin body = route.handler.call(context).to_s content_type = context.response?.try(&.content_type) || "text/plain" diff --git a/src/kemal/logger.cr b/src/kemal/logger.cr index 9650c19..4d3e065 100644 --- a/src/kemal/logger.cr +++ b/src/kemal/logger.cr @@ -1,5 +1,6 @@ class Kemal::Logger LOG_LEVELS = %w(info debug error warn) + def initialize(@stream) end @@ -10,6 +11,6 @@ class Kemal::Logger {% end %} def exception(e) - error "#{e.message}:\n\t#{e.backtrace.join("\n\t")}" + error "#{e.message}:\n\t#{e.backtrace.join("\n\t")}" end end diff --git a/src/kemal/param_parser.cr b/src/kemal/param_parser.cr new file mode 100644 index 0000000..01526ed --- /dev/null +++ b/src/kemal/param_parser.cr @@ -0,0 +1,37 @@ +class Kemal::Params + def initialize(@route, @request) + @route_components = route.components + @request_components = request.path.not_nil!.split "/" + @params = {} of String => String + end + + def parse + parse_components + parse_request + end + + def parse_request + if query = @request.query + HTTP::Params.parse(query) do |key, value| + @params[key] ||= value + end + end + + if body = @request.body + HTTP::Params.parse(body.not_nil!) do |key, value| + @params[key] ||= value + end + end + @params + end + + def parse_components + @route_components.zip(@request_components) do |route_component, req_component| + if route_component.starts_with? ':' + @params[route_component[1..-1]] = req_component + else + return nil unless route_component == req_component + end + end + end +end diff --git a/src/kemal/route.cr b/src/kemal/route.cr index e63f658..ee3b8fc 100644 --- a/src/kemal/route.cr +++ b/src/kemal/route.cr @@ -1,26 +1,15 @@ class Kemal::Route getter handler + getter components def initialize(@method, path, &@handler : Kemal::Context -> _) @components = path.split "/" end - def match(method, components) - return nil unless method == @method + def match?(request) + components = request.path.not_nil!.split "/" + return nil unless request.method == @method return nil unless components.size == @components.size - - 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 - params + true end end