From 8267ffe2c5d2b68511534c71648465f9f64a9a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fatih=20Kadir=20Ak=C4=B1n?= Date: Sun, 6 Mar 2016 13:22:24 +0200 Subject: [PATCH 1/6] Upgrade ParamParser to make it more convinient. It now decouples `env.params` to `env.params.query`, `env.params.body`, `env.params.json` and `env.params.url` and you still can access merged values using `env.params.all` --- spec/param_parser_spec.cr | 72 +++++++++++++++++++++++++++----------- spec/route_handler_spec.cr | 14 ++++---- spec/view_spec.cr | 6 ++-- src/kemal/context.cr | 3 +- src/kemal/param_parser.cr | 44 ++++++++++++++++------- src/kemal/request.cr | 2 +- 6 files changed, 96 insertions(+), 45 deletions(-) diff --git a/spec/param_parser_spec.cr b/spec/param_parser_spec.cr index f2b4f0e..c825b4e 100644 --- a/spec/param_parser_spec.cr +++ b/spec/param_parser_spec.cr @@ -3,19 +3,31 @@ require "./spec_helper" describe "ParamParser" do it "parses query params" do route = Route.new "POST", "/" do |env| - hasan = env.params["hasan"] + hasan = env.params.query["hasan"] "Hello #{hasan}" end request = HTTP::Request.new("POST", "/?hasan=cemal") - params = Kemal::ParamParser.new(request).parse - params["hasan"].should eq "cemal" + query_params = Kemal::ParamParser.new(request).params.query + query_params["hasan"].should eq "cemal" + 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).params.url + url_params["hasan"].should eq "cemal" end it "parses request body" do route = Route.new "POST", "/" do |env| - name = env.params["name"] - age = env.params["age"] - hasan = env.params["hasan"] + name = env.params.query["name"] + age = env.params.query["age"] + hasan = env.params.body["hasan"] "Hello #{name} #{hasan} #{age}" end @@ -26,8 +38,11 @@ describe "ParamParser" do headers: HTTP::Headers{"Content-Type": "application/x-www-form-urlencoded"}, ) - params = Kemal::ParamParser.new(request).parse - params.should eq({"hasan" => "cemal", "name" => "serdar", "age" => "99"}) + query_params = Kemal::ParamParser.new(request).params.query + query_params.should eq({"hasan" => "cemal"}) + + body_params = Kemal::ParamParser.new(request).params.body + body_params.should eq({"name" => "serdar", "age" => "99"}) end context "when content type is application/json" do @@ -41,8 +56,8 @@ describe "ParamParser" do headers: HTTP::Headers{"Content-Type": "application/json"}, ) - params = Kemal::ParamParser.new(request).parse - params.should eq({"name": "Serdar"}) + json_params = Kemal::ParamParser.new(request).params.json + json_params.should eq({"name": "Serdar"}) end it "parses request body for array" do @@ -55,8 +70,8 @@ describe "ParamParser" do headers: HTTP::Headers{"Content-Type": "application/json"}, ) - params = Kemal::ParamParser.new(request).parse - params.should eq({"_json": [1]}) + json_params = Kemal::ParamParser.new(request).params.json + json_params.should eq({"_json": [1]}) end it "parses request body and query params" do @@ -69,8 +84,11 @@ describe "ParamParser" do headers: HTTP::Headers{"Content-Type": "application/json"}, ) - params = Kemal::ParamParser.new(request).parse - params.should eq({"foo": "bar", "_json": [1]}) + query_params = Kemal::ParamParser.new(request).params.query + query_params.should eq({"foo": "bar"}) + + json_params = Kemal::ParamParser.new(request).params.json + json_params.should eq({"_json": [1]}) end it "handles no request body" do @@ -82,17 +100,26 @@ describe "ParamParser" do headers: HTTP::Headers{"Content-Type": "application/json"}, ) - params = Kemal::ParamParser.new(request).parse - params.should eq({} of String => AllParamTypes) + url_params = Kemal::ParamParser.new(request).params.url + url_params.should eq({} of String => String) + + query_params = Kemal::ParamParser.new(request).params.query + query_params.should eq({} of String => String) + + body_params = Kemal::ParamParser.new(request).params.body + body_params.should eq({} of String => String) + + json_params = Kemal::ParamParser.new(request).params.json + json_params.should eq({} of String => AllParamTypes) end end context "when content type is incorrect" do it "does not parse request body" do route = Route.new "POST", "/" do |env| - name = env.params["name"] - age = env.params["age"] - hasan = env.params["hasan"] + name = env.params.body["name"] + age = env.params.body["age"] + hasan = env.params.query["hasan"] "Hello #{name} #{hasan} #{age}" end @@ -103,8 +130,11 @@ describe "ParamParser" do headers: HTTP::Headers{"Content-Type": "text/plain"}, ) - params = Kemal::ParamParser.new(request).parse - params.should eq({"hasan" => "cemal"}) + query_params = Kemal::ParamParser.new(request).params.query + query_params.should eq({"hasan" => "cemal"}) + + body_params = Kemal::ParamParser.new(request).params.body + body_params.should eq({} of String => String) end end end diff --git a/spec/route_handler_spec.cr b/spec/route_handler_spec.cr index 2df06c5..69e742a 100644 --- a/spec/route_handler_spec.cr +++ b/spec/route_handler_spec.cr @@ -15,7 +15,7 @@ describe "Kemal::RouteHandler" do it "routes request with query string" do kemal = Kemal::RouteHandler::INSTANCE kemal.add_route "GET", "/" do |env| - "hello #{env.params["message"]}" + "hello #{env.params.query["message"]}" end request = HTTP::Request.new("GET", "/?message=world") io_with_context = create_request_and_return_io(kemal, request) @@ -26,7 +26,7 @@ describe "Kemal::RouteHandler" do it "routes request with multiple query strings" do kemal = Kemal::RouteHandler::INSTANCE kemal.add_route "GET", "/" do |env| - "hello #{env.params["message"]} time #{env.params["time"]}" + "hello #{env.params.query["message"]} time #{env.params.query["time"]}" end request = HTTP::Request.new("GET", "/?message=world&time=now") io_with_context = create_request_and_return_io(kemal, request) @@ -37,7 +37,7 @@ describe "Kemal::RouteHandler" do it "route parameter has more precedence than query string arguments" do kemal = Kemal::RouteHandler::INSTANCE kemal.add_route "GET", "/:message" do |env| - "hello #{env.params["message"]}" + "hello #{env.params.url["message"]}" end request = HTTP::Request.new("GET", "/world?message=coco") io_with_context = create_request_and_return_io(kemal, request) @@ -48,8 +48,8 @@ describe "Kemal::RouteHandler" do it "parses simple JSON body" do kemal = Kemal::RouteHandler::INSTANCE kemal.add_route "POST", "/" do |env| - name = env.params["name"] - age = env.params["age"] + name = env.params.json["name"] + age = env.params.json["age"] "Hello #{name} Age #{age}" end @@ -68,7 +68,7 @@ describe "Kemal::RouteHandler" do it "parses JSON with string array" do kemal = Kemal::RouteHandler::INSTANCE kemal.add_route "POST", "/" do |env| - skills = env.params["skills"] as Array + skills = env.params.json["skills"] as Array "Skills #{skills.each.join(',')}" end @@ -87,7 +87,7 @@ describe "Kemal::RouteHandler" do it "parses JSON with json object array" do kemal = Kemal::RouteHandler::INSTANCE kemal.add_route "POST", "/" do |env| - skills = env.params["skills"] as Array + skills = env.params.json["skills"] as Array skills_from_languages = skills.map do |skill| skill = skill as Hash skill["language"] diff --git a/spec/view_spec.cr b/spec/view_spec.cr index 42c49af..5906e3f 100644 --- a/spec/view_spec.cr +++ b/spec/view_spec.cr @@ -8,7 +8,7 @@ describe "Views" do it "renders file" do kemal = Kemal::RouteHandler::INSTANCE kemal.add_route "GET", "/view/:name" do |env| - name = env.params["name"] + name = env.params.url["name"] render "spec/asset/hello.ecr" end request = HTTP::Request.new("GET", "/view/world") @@ -20,7 +20,7 @@ describe "Views" do it "renders file with dynamic variables" do kemal = Kemal::RouteHandler::INSTANCE kemal.add_route "GET", "/view/:name" do |env| - name = env.params["name"] + name = env.params.url["name"] render_with_base_and_layout "hello.ecr" end request = HTTP::Request.new("GET", "/view/world") @@ -32,7 +32,7 @@ describe "Views" do it "renders layout" do kemal = Kemal::RouteHandler::INSTANCE kemal.add_route "GET", "/view/:name" do |env| - name = env.params["name"] + name = env.params.url["name"] render "spec/asset/hello.ecr", "spec/asset/layout.ecr" end request = HTTP::Request.new("GET", "/view/world") diff --git a/src/kemal/context.cr b/src/kemal/context.cr index 84867db..41a55dc 100644 --- a/src/kemal/context.cr +++ b/src/kemal/context.cr @@ -2,9 +2,10 @@ # information such as params, content_type e.g class HTTP::Server class Context + def params @request.url_params = route_lookup.params - @params ||= Kemal::ParamParser.new(@request).parse + @params ||= Kemal::ParamParser.new(@request).params end def redirect(url, status_code = 302) diff --git a/src/kemal/param_parser.cr b/src/kemal/param_parser.cr index ad0bf45..37f24dc 100644 --- a/src/kemal/param_parser.cr +++ b/src/kemal/param_parser.cr @@ -5,16 +5,34 @@ require "json" # context. alias AllParamTypes = Nil | String | Int64 | Float64 | Bool | Hash(String, JSON::Type) | Array(JSON::Type) +class Kemal::ParamContainer + getter url + getter query + getter body + getter json + + def initialize(@url, @query, @body, @json) + end + + def all + @url.merge(@query).merge(@body).merge(@json) + end +end + class Kemal::ParamParser URL_ENCODED_FORM = "application/x-www-form-urlencoded" APPLICATION_JSON = "application/json" def initialize(@request) - @params = {} of String => AllParamTypes + @url = {} of String => String + @query = {} of String => String + @body = {} of String => String + @json = {} of String => AllParamTypes end - def parse + def params parse_request + Kemal::ParamContainer.new(@url, @query, @body, @json) end def parse_request @@ -22,22 +40,21 @@ class Kemal::ParamParser parse_body parse_json parse_url_params - @params end def parse_body return if (@request.headers["Content-Type"]? =~ /#{URL_ENCODED_FORM}/).nil? - parse_part(@request.body) + @body = parse_part(@request.body) end def parse_query - parse_part(@request.query) + @query = parse_part(@request.query) end def parse_url_params if params = @request.url_params params.each do |key, value| - @params[key] = value + @url[key as String] = value as String end end end @@ -52,18 +69,21 @@ class Kemal::ParamParser body = @request.body as String case json = JSON.parse(body).raw when Hash - json.each do |k, v| - @params[k as String] = v as AllParamTypes + json.each do |key, value| + @json[key as String] = value as AllParamTypes end when Array - @params["_json"] = json + @json["_json"] = json end end def parse_part(part) - return unless part - HTTP::Params.parse(part) do |key, value| - @params[key] ||= value + part_params = {} of String => String + if part + HTTP::Params.parse(part) do |key, value| + part_params[key as String] ||= value as String + end end + part_params end end diff --git a/src/kemal/request.cr b/src/kemal/request.cr index 44cd118..dfc4935 100644 --- a/src/kemal/request.cr +++ b/src/kemal/request.cr @@ -11,7 +11,7 @@ class HTTP::Request private def check_for_method_override! @override_method = @method if @method == "POST" - params = Kemal::ParamParser.new(self).parse_request + params = Kemal::ParamParser.new(self).params.all if params.has_key?("_method") && HTTP::Request.override_method_valid?(params["_method"]) @override_method = params["_method"] end From e53ba1d9da3be00007f204250a62c7ff4648825e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fatih=20Kadir=20Ak=C4=B1n?= Date: Sun, 6 Mar 2016 14:08:59 +0200 Subject: [PATCH 2/6] Decouple ParamContainer which makes the code cleaner, and fix kemal.cr url -- by @sdogruyol --- src/kemal.cr | 2 +- src/kemal/param_parser.cr | 34 +++++++++++++++++++--------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/kemal.cr b/src/kemal.cr index f89976e..db3ea3b 100644 --- a/src/kemal.cr +++ b/src/kemal.cr @@ -18,7 +18,7 @@ at_exit do # This route serves the built-in images for not_found and exceptions. get "/__kemal__/:image" do |env| - image = env.params["image"] + image = env.params.url["image"] file_path = File.expand_path("libs/kemal/images/#{image}", Dir.current) if File.exists? file_path env.response.headers.add "Content-Type", "application/octet-stream" diff --git a/src/kemal/param_parser.cr b/src/kemal/param_parser.cr index 37f24dc..673c806 100644 --- a/src/kemal/param_parser.cr +++ b/src/kemal/param_parser.cr @@ -6,12 +6,16 @@ require "json" alias AllParamTypes = Nil | String | Int64 | Float64 | Bool | Hash(String, JSON::Type) | Array(JSON::Type) class Kemal::ParamContainer - getter url - getter query - getter body - getter json + property url + property query + property body + property json - def initialize(@url, @query, @body, @json) + def initialize + @url = {} of String => String + @query = {} of String => String + @body = {} of String => String + @json = {} of String => AllParamTypes end def all @@ -24,15 +28,12 @@ class Kemal::ParamParser APPLICATION_JSON = "application/json" def initialize(@request) - @url = {} of String => String - @query = {} of String => String - @body = {} of String => String - @json = {} of String => AllParamTypes + @param_container = Kemal::ParamContainer.new end def params parse_request - Kemal::ParamContainer.new(@url, @query, @body, @json) + @param_container end def parse_request @@ -44,17 +45,17 @@ class Kemal::ParamParser def parse_body return if (@request.headers["Content-Type"]? =~ /#{URL_ENCODED_FORM}/).nil? - @body = parse_part(@request.body) + @param_container.body = parse_part(@request.body) end def parse_query - @query = parse_part(@request.query) + @param_container.query = parse_part(@request.query) end def parse_url_params if params = @request.url_params params.each do |key, value| - @url[key as String] = value as String + @param_container.url[key as String] = value as String end end end @@ -70,10 +71,10 @@ class Kemal::ParamParser case json = JSON.parse(body).raw when Hash json.each do |key, value| - @json[key as String] = value as AllParamTypes + @param_container.json[key as String] = value as AllParamTypes end when Array - @json["_json"] = json + @param_container.json["_json"] = json end end @@ -86,4 +87,7 @@ class Kemal::ParamParser end part_params end + + delegate url, body, query, json, @param_container end + From 53d12534b787ca939467f7faa559653898643d6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fatih=20Kadir=20Ak=C4=B1n?= Date: Sun, 6 Mar 2016 21:43:13 +0200 Subject: [PATCH 3/6] Remove ParamContainer abstraction to make it faster. --- spec/param_parser_spec.cr | 28 ++++++++++++------------- src/kemal/context.cr | 2 +- src/kemal/param_parser.cr | 44 +++++++++++++++------------------------ src/kemal/request.cr | 2 +- 4 files changed, 33 insertions(+), 43 deletions(-) diff --git a/spec/param_parser_spec.cr b/spec/param_parser_spec.cr index c825b4e..f2d6c63 100644 --- a/spec/param_parser_spec.cr +++ b/spec/param_parser_spec.cr @@ -7,7 +7,7 @@ describe "ParamParser" do "Hello #{hasan}" end request = HTTP::Request.new("POST", "/?hasan=cemal") - query_params = Kemal::ParamParser.new(request).params.query + query_params = Kemal::ParamParser.new(request).query query_params["hasan"].should eq "cemal" end @@ -19,7 +19,7 @@ describe "ParamParser" do 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).params.url + url_params = Kemal::ParamParser.new(request).url url_params["hasan"].should eq "cemal" end @@ -38,10 +38,10 @@ describe "ParamParser" do headers: HTTP::Headers{"Content-Type": "application/x-www-form-urlencoded"}, ) - query_params = Kemal::ParamParser.new(request).params.query + query_params = Kemal::ParamParser.new(request).query query_params.should eq({"hasan" => "cemal"}) - body_params = Kemal::ParamParser.new(request).params.body + body_params = Kemal::ParamParser.new(request).body body_params.should eq({"name" => "serdar", "age" => "99"}) end @@ -56,7 +56,7 @@ describe "ParamParser" do headers: HTTP::Headers{"Content-Type": "application/json"}, ) - json_params = Kemal::ParamParser.new(request).params.json + json_params = Kemal::ParamParser.new(request).json json_params.should eq({"name": "Serdar"}) end @@ -70,7 +70,7 @@ describe "ParamParser" do headers: HTTP::Headers{"Content-Type": "application/json"}, ) - json_params = Kemal::ParamParser.new(request).params.json + json_params = Kemal::ParamParser.new(request).json json_params.should eq({"_json": [1]}) end @@ -84,10 +84,10 @@ describe "ParamParser" do headers: HTTP::Headers{"Content-Type": "application/json"}, ) - query_params = Kemal::ParamParser.new(request).params.query + query_params = Kemal::ParamParser.new(request).query query_params.should eq({"foo": "bar"}) - json_params = Kemal::ParamParser.new(request).params.json + json_params = Kemal::ParamParser.new(request).json json_params.should eq({"_json": [1]}) end @@ -100,16 +100,16 @@ describe "ParamParser" do headers: HTTP::Headers{"Content-Type": "application/json"}, ) - url_params = Kemal::ParamParser.new(request).params.url + url_params = Kemal::ParamParser.new(request).url url_params.should eq({} of String => String) - query_params = Kemal::ParamParser.new(request).params.query + query_params = Kemal::ParamParser.new(request).query query_params.should eq({} of String => String) - body_params = Kemal::ParamParser.new(request).params.body + body_params = Kemal::ParamParser.new(request).body body_params.should eq({} of String => String) - json_params = Kemal::ParamParser.new(request).params.json + json_params = Kemal::ParamParser.new(request).json json_params.should eq({} of String => AllParamTypes) end end @@ -130,10 +130,10 @@ describe "ParamParser" do headers: HTTP::Headers{"Content-Type": "text/plain"}, ) - query_params = Kemal::ParamParser.new(request).params.query + query_params = Kemal::ParamParser.new(request).query query_params.should eq({"hasan" => "cemal"}) - body_params = Kemal::ParamParser.new(request).params.body + body_params = Kemal::ParamParser.new(request).body body_params.should eq({} of String => String) end end diff --git a/src/kemal/context.cr b/src/kemal/context.cr index 41a55dc..f744236 100644 --- a/src/kemal/context.cr +++ b/src/kemal/context.cr @@ -5,7 +5,7 @@ class HTTP::Server def params @request.url_params = route_lookup.params - @params ||= Kemal::ParamParser.new(@request).params + @params ||= Kemal::ParamParser.new(@request) end def redirect(url, status_code = 302) diff --git a/src/kemal/param_parser.cr b/src/kemal/param_parser.cr index 673c806..48e97f8 100644 --- a/src/kemal/param_parser.cr +++ b/src/kemal/param_parser.cr @@ -5,35 +5,26 @@ require "json" # context. alias AllParamTypes = Nil | String | Int64 | Float64 | Bool | Hash(String, JSON::Type) | Array(JSON::Type) -class Kemal::ParamContainer - property url - property query - property body - property json - - def initialize - @url = {} of String => String - @query = {} of String => String - @body = {} of String => String - @json = {} of String => AllParamTypes - end - - def all - @url.merge(@query).merge(@body).merge(@json) - end -end - class Kemal::ParamParser URL_ENCODED_FORM = "application/x-www-form-urlencoded" APPLICATION_JSON = "application/json" + getter url + getter query + getter body + getter json + def initialize(@request) - @param_container = Kemal::ParamContainer.new + @url = {} of String => String + @query = {} of String => String + @body = {} of String => String + @json = {} of String => AllParamTypes + + parse_request end def params - parse_request - @param_container + @query.merge(@body).merge(@json).merge(@url) end def parse_request @@ -45,17 +36,17 @@ class Kemal::ParamParser def parse_body return if (@request.headers["Content-Type"]? =~ /#{URL_ENCODED_FORM}/).nil? - @param_container.body = parse_part(@request.body) + @body = parse_part(@request.body) end def parse_query - @param_container.query = parse_part(@request.query) + @query = parse_part(@request.query) end def parse_url_params if params = @request.url_params params.each do |key, value| - @param_container.url[key as String] = value as String + @url[key as String] = value as String end end end @@ -71,10 +62,10 @@ class Kemal::ParamParser case json = JSON.parse(body).raw when Hash json.each do |key, value| - @param_container.json[key as String] = value as AllParamTypes + @json[key as String] = value as AllParamTypes end when Array - @param_container.json["_json"] = json + @json["_json"] = json end end @@ -88,6 +79,5 @@ class Kemal::ParamParser part_params end - delegate url, body, query, json, @param_container end diff --git a/src/kemal/request.cr b/src/kemal/request.cr index dfc4935..92317c2 100644 --- a/src/kemal/request.cr +++ b/src/kemal/request.cr @@ -11,7 +11,7 @@ class HTTP::Request private def check_for_method_override! @override_method = @method if @method == "POST" - params = Kemal::ParamParser.new(self).params.all + params = Kemal::ParamParser.new(self).params if params.has_key?("_method") && HTTP::Request.override_method_valid?(params["_method"]) @override_method = params["_method"] end From 42deb956882127e90c2c1e653efcbff05aea6c10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fatih=20Kadir=20Ak=C4=B1n?= Date: Sun, 6 Mar 2016 21:46:35 +0200 Subject: [PATCH 4/6] Remove merged params to improve performance --- spec/route_handler_spec.cr | 4 ++-- src/kemal/param_parser.cr | 4 ---- src/kemal/request.cr | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/spec/route_handler_spec.cr b/spec/route_handler_spec.cr index 69e742a..6d21334 100644 --- a/spec/route_handler_spec.cr +++ b/spec/route_handler_spec.cr @@ -170,8 +170,8 @@ describe "Kemal::RouteHandler" do request = HTTP::Request.new( "POST", "/", - body: json_payload.to_json, - headers: HTTP::Headers{"Content-Type": "application/json"} + body: "_method=DELETE", + headers: HTTP::Headers{"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"} ) io_with_context = create_request_and_return_io(kemal, request) client_response = HTTP::Client::Response.from_io(io_with_context, decompress: false) diff --git a/src/kemal/param_parser.cr b/src/kemal/param_parser.cr index 48e97f8..c383689 100644 --- a/src/kemal/param_parser.cr +++ b/src/kemal/param_parser.cr @@ -23,10 +23,6 @@ class Kemal::ParamParser parse_request end - def params - @query.merge(@body).merge(@json).merge(@url) - end - def parse_request parse_query parse_body diff --git a/src/kemal/request.cr b/src/kemal/request.cr index 92317c2..60dc1cd 100644 --- a/src/kemal/request.cr +++ b/src/kemal/request.cr @@ -11,7 +11,7 @@ class HTTP::Request private def check_for_method_override! @override_method = @method if @method == "POST" - params = Kemal::ParamParser.new(self).params + params = Kemal::ParamParser.new(self).body if params.has_key?("_method") && HTTP::Request.override_method_valid?(params["_method"]) @override_method = params["_method"] end From 4ee4b66135bba66101ceaed703f1a9d34a5682e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fatih=20Kadir=20Ak=C4=B1n?= Date: Sun, 6 Mar 2016 22:29:23 +0200 Subject: [PATCH 5/6] Make the param getters lazy to improve performance --- src/kemal/param_parser.cr | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/kemal/param_parser.cr b/src/kemal/param_parser.cr index c383689..69459cc 100644 --- a/src/kemal/param_parser.cr +++ b/src/kemal/param_parser.cr @@ -9,26 +9,19 @@ class Kemal::ParamParser URL_ENCODED_FORM = "application/x-www-form-urlencoded" APPLICATION_JSON = "application/json" - getter url - getter query - getter body - getter json - def initialize(@request) @url = {} of String => String @query = {} of String => String @body = {} of String => String @json = {} of String => AllParamTypes - - parse_request end - def parse_request - parse_query - parse_body - parse_json - parse_url_params + {% for method in %w(url query body json) %} + def {{method.id}} + parse_{{method.id}} + @{{method.id}} end + {% end %} def parse_body return if (@request.headers["Content-Type"]? =~ /#{URL_ENCODED_FORM}/).nil? @@ -39,7 +32,7 @@ class Kemal::ParamParser @query = parse_part(@request.query) end - def parse_url_params + def parse_url if params = @request.url_params params.each do |key, value| @url[key as String] = value as String From 043d1c8aa26ed510b491b6859b60cb29d8c43ddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fatih=20Kadir=20Ak=C4=B1n?= Date: Sun, 6 Mar 2016 22:39:10 +0200 Subject: [PATCH 6/6] Add memoization to lazy param parsing --- src/kemal/context.cr | 1 - src/kemal/param_parser.cr | 7 +++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/kemal/context.cr b/src/kemal/context.cr index f744236..333e752 100644 --- a/src/kemal/context.cr +++ b/src/kemal/context.cr @@ -2,7 +2,6 @@ # information such as params, content_type e.g class HTTP::Server class Context - def params @request.url_params = route_lookup.params @params ||= Kemal::ParamParser.new(@request) diff --git a/src/kemal/param_parser.cr b/src/kemal/param_parser.cr index 69459cc..e7ef0f5 100644 --- a/src/kemal/param_parser.cr +++ b/src/kemal/param_parser.cr @@ -18,7 +18,12 @@ class Kemal::ParamParser {% for method in %w(url query body json) %} def {{method.id}} + # check memoization + return @{{method.id}} if @{{method.id}}_parsed + parse_{{method.id}} + # memoize + @{{method.id}}_parsed = true @{{method.id}} end {% end %} @@ -67,6 +72,4 @@ class Kemal::ParamParser end part_params end - end -