diff --git a/spec/param_parser_spec.cr b/spec/param_parser_spec.cr index 4c1992f..1ee5b2c 100644 --- a/spec/param_parser_spec.cr +++ b/spec/param_parser_spec.cr @@ -2,101 +2,98 @@ require "./spec_helper" describe "ParamParser" do it "parses query params" do - route = Route.new "POST", "/" do |env| - hasan = env.params.query["hasan"] - "Hello #{hasan}" - end request = HTTP::Request.new("POST", "/?hasan=cemal") query_params = Kemal::ParamParser.new(request).query query_params["hasan"].should eq "cemal" end - it "parses multiple values for query params" do - route = Route.new "POST", "/" do |env| - hasan = env.params.query["hasan"] - "Hello #{hasan}" - end - request = HTTP::Request.new("POST", "/?hasan=cemal&hasan=lamec") - query_params = Kemal::ParamParser.new(request).query - query_params.fetch_all("hasan").should eq ["cemal", "lamec"] - end - - it "parses url params" do - kemal = Kemal::RouteHandler::INSTANCE - kemal.add_route "POST", "/hello/:hasan" do |env| - "hello #{env.params.url["hasan"]}" - end - request = HTTP::Request.new("POST", "/hello/cemal") - # Radix tree MUST be run to parse url params. - io_with_context = create_request_and_return_io(kemal, request) - url_params = Kemal::ParamParser.new(request).url - url_params["hasan"].should eq "cemal" - end - - it "decodes url params" do - kemal = Kemal::RouteHandler::INSTANCE - kemal.add_route "POST", "/hello/:email/:money/:spanish" do |env| - email = env.params.url["email"] - money = env.params.url["money"] - spanish = env.params.url["spanish"] - "Hello, #{email}. You have #{money}. The spanish word of the day is #{spanish}." - end - request = HTTP::Request.new("POST", "/hello/sam%2Bspec%40gmail.com/%2419.99/a%C3%B1o") - # Radix tree MUST be run to parse url params. - io_with_context = create_request_and_return_io(kemal, request) - url_params = Kemal::ParamParser.new(request).url - url_params["email"].should eq "sam+spec@gmail.com" - url_params["money"].should eq "$19.99" - url_params["spanish"].should eq "año" - end - - it "parses request body" do - route = Route.new "POST", "/" do |env| - name = env.params.query["name"] - age = env.params.query["age"] - hasan = env.params.body["hasan"] - "Hello #{name} #{hasan} #{age}" - end - - request = HTTP::Request.new( - "POST", - "/?hasan=cemal", - body: "name=serdar&age=99", - headers: HTTP::Headers{"Content-Type" => "application/x-www-form-urlencoded"}, - ) - - query_params = Kemal::ParamParser.new(request).query - {"hasan" => "cemal"}.each do |k, v| - query_params[k].should eq(v) - end - - body_params = Kemal::ParamParser.new(request).body - {"name" => "serdar", "age" => "99"}.each do |k, v| - body_params[k].should eq(v) + context "#query" do + it "parses multiple values for query params" do + request = HTTP::Request.new("POST", "/?hasan=cemal&hasan=lamec") + query_params = Kemal::ParamParser.new(request).query + query_params["hasan"].should eq ["cemal", "lamec"] end end - it "parses multiple values in request body" do - route = Route.new "POST", "/" do |env| - hasan = env.params.body["hasan"] - "Hello #{hasan}" + context "#url" do + it "parses url params" do + kemal = Kemal::RouteHandler::INSTANCE + kemal.add_route "POST", "/hello/:hasan" do |env| + "hello #{env.params.url["hasan"]}" + end + request = HTTP::Request.new("POST", "/hello/cemal") + # Radix tree MUST be run to parse url params. + io_with_context = create_request_and_return_io(kemal, request) + url_params = Kemal::ParamParser.new(request).url + url_params["hasan"].should eq "cemal" end - request = HTTP::Request.new( - "POST", - "/", - body: "hasan=cemal&hasan=lamec", - headers: HTTP::Headers{"Content-Type" => "application/x-www-form-urlencoded"}, - ) - - body_params = Kemal::ParamParser.new(request).body - body_params.fetch_all("hasan").should eq(["cemal", "lamec"]) + it "decodes url params" do + kemal = Kemal::RouteHandler::INSTANCE + kemal.add_route "POST", "/hello/:email/:money/:spanish" do |env| + email = env.params.url["email"] + money = env.params.url["money"] + spanish = env.params.url["spanish"] + "Hello, #{email}. You have #{money}. The spanish word of the day is #{spanish}." + end + request = HTTP::Request.new("POST", "/hello/sam%2Bspec%40gmail.com/%2419.99/a%C3%B1o") + # Radix tree MUST be run to parse url params. + io_with_context = create_request_and_return_io(kemal, request) + url_params = Kemal::ParamParser.new(request).url + url_params["email"].should eq "sam+spec@gmail.com" + url_params["money"].should eq "$19.99" + url_params["spanish"].should eq "año" + end end - context "when content type is application/json" do + context "#body" do it "parses request body" do - route = Route.new "POST", "/" { } + request = HTTP::Request.new( + "POST", + "/?hasan=cemal", + body: "name=serdar&age=99", + headers: HTTP::Headers{"Content-Type" => "application/x-www-form-urlencoded"}, + ) + query_params = Kemal::ParamParser.new(request).query + {"hasan" => "cemal"}.each do |k, v| + query_params[k].should eq(v) + end + + body_params = Kemal::ParamParser.new(request).body + {"name" => "serdar", "age" => "99"}.each do |k, v| + body_params[k].should eq(v) + end + end + + it "parses multiple values in request body" do + request = HTTP::Request.new( + "POST", + "/", + body: "hasan=cemal&hasan=lamec", + headers: HTTP::Headers{"Content-Type" => "application/x-www-form-urlencoded"}, + ) + + body_params = Kemal::ParamParser.new(request).body + body_params["hasan"].should eq(["cemal", "lamec"]) + end + + it "parses array values in request body" do + request = HTTP::Request.new( + "POST", + "/", + body: "framework=kemal&feats[]=fast&feats[]=effective&feats[]=simple", + headers: HTTP::Headers{"Content-Type" => "application/x-www-form-urlencoded"}, + ) + + body_params = Kemal::ParamParser.new(request).body + body_params["framework"].should eq("kemal") + body_params["feats[]"].should eq(["fast", "effective", "simple"]) + end + end + + context "#json" do + it "parses request body" do request = HTTP::Request.new( "POST", "/", @@ -109,8 +106,6 @@ describe "ParamParser" do end it "parses request body when passed charset" do - route = Route.new "POST", "/" { } - request = HTTP::Request.new( "POST", "/", @@ -123,8 +118,6 @@ describe "ParamParser" do end it "parses request body for array" do - route = Route.new "POST", "/" { } - request = HTTP::Request.new( "POST", "/", @@ -137,8 +130,6 @@ describe "ParamParser" do end it "parses request body and query params" do - route = Route.new "POST", "/" { } - request = HTTP::Request.new( "POST", "/?foo=bar", @@ -156,8 +147,6 @@ describe "ParamParser" do end it "handles no request body" do - route = Route.new "GET", "/" { } - request = HTTP::Request.new( "GET", "/", @@ -180,13 +169,6 @@ describe "ParamParser" do context "when content type is incorrect" do it "does not parse request body" do - route = Route.new "POST", "/" do |env| - name = env.params.body["name"] - age = env.params.body["age"] - hasan = env.params.query["hasan"] - "Hello #{name} #{hasan} #{age}" - end - request = HTTP::Request.new( "POST", "/?hasan=cemal", diff --git a/src/kemal/ext/params.cr b/src/kemal/ext/params.cr new file mode 100644 index 0000000..5451842 --- /dev/null +++ b/src/kemal/ext/params.cr @@ -0,0 +1,8 @@ +module HTTP + struct Params + def [](name) + params = raw_params[name] + params.size == 1 ? params.first : params + end + end +end diff --git a/src/kemal/ext/request.cr b/src/kemal/ext/request.cr index f027de5..af182fb 100644 --- a/src/kemal/ext/request.cr +++ b/src/kemal/ext/request.cr @@ -1,5 +1,5 @@ class HTTP::Request - property override_method + property override_method : String? property url_params : Hash(String, String)? getter param_parser : Kemal::ParamParser? @@ -21,7 +21,7 @@ class HTTP::Request @param_parser = Kemal::ParamParser.new(self) params = @param_parser.not_nil!.body if params.has_key?("_method") && HTTP::Request.override_method_valid?(params["_method"]) - @override_method = params["_method"] + @override_method = params["_method"].as(String) end end @override_method