Allow multiple values for a single parameter key.

This commit is contained in:
Matthew Gerrior 2016-06-11 16:52:07 -04:00
parent c9b206d1d6
commit a5e4bc21f3
4 changed files with 72 additions and 6 deletions

View file

@ -11,6 +11,16 @@ describe "ParamParser" do
query_params["hasan"].should eq "cemal" query_params["hasan"].should eq "cemal"
end 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["hasan"].should eq ["cemal", "lamec"]
end
it "parses url params" do it "parses url params" do
kemal = Kemal::RouteHandler::INSTANCE kemal = Kemal::RouteHandler::INSTANCE
kemal.add_route "POST", "/hello/:hasan" do |env| kemal.add_route "POST", "/hello/:hasan" do |env|
@ -45,6 +55,23 @@ describe "ParamParser" do
body_params.should eq({"name" => "serdar", "age" => "99"}) body_params.should eq({"name" => "serdar", "age" => "99"})
end end
it "parses multiple values in request body" do
route = Route.new "POST", "/" do |env|
hasan = env.params.body["hasan"]
"Hello #{hasan}"
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.should eq({"hasan" => ["cemal", "lamec"]})
end
context "when content type is application/json" do context "when content type is application/json" do
it "parses request body" do it "parses request body" do
route = Route.new "POST", "/" { } route = Route.new "POST", "/" { }

14
spec/request_spec.cr Normal file
View file

@ -0,0 +1,14 @@
require "./spec_helper"
describe "Request" do
it "uses the last method override provided" do
request = HTTP::Request.new(
"POST",
"/",
body: "_method=PUT&_method=PATCH",
headers: HTTP::Headers{"Content-Type": "application/x-www-form-urlencoded"},
)
request.override_method.should eq("PATCH")
end
end

View file

@ -11,8 +11,8 @@ class Kemal::ParamParser
def initialize(@request : HTTP::Request) def initialize(@request : HTTP::Request)
@url = {} of String => String @url = {} of String => String
@query = {} of String => String @query = {} of String => String | Array(String)
@body = {} of String => String @body = {} of String => String | Array(String)
@json = {} of String => AllParamTypes @json = {} of String => AllParamTypes
@url_parsed = false @url_parsed = false
@query_parsed = false @query_parsed = false
@ -68,12 +68,26 @@ class Kemal::ParamParser
end end
def parse_part(part) def parse_part(part)
part_params = {} of String => String part_params = {} of String => String | Array(String)
if part if part
HTTP::Params.parse(part) do |key, value| HTTP::Params.parse(part) do |key, value|
part_params[key as String] ||= value as String key_string = key as String
value_string = value as String
current_value = part_params[key_string]?
part_params[key_string] = if current_value
if current_value.is_a?(Array)
current_value << value_string
else
[current_value, value_string]
end
else
value_string
end
end end
end end
part_params part_params
end end
end end

View file

@ -10,18 +10,29 @@ class HTTP::Request
# Checks if request params contain _method param to override request incoming method # Checks if request params contain _method param to override request incoming method
private def check_for_method_override! private def check_for_method_override!
@override_method = @method @override_method = @method
if @method == "POST" if @method == "POST"
params = Kemal::ParamParser.new(self).body params = Kemal::ParamParser.new(self).body
if params.has_key?("_method") && HTTP::Request.override_method_valid?(params["_method"]) if params.has_key?("_method") && HTTP::Request.override_method_valid?(params["_method"])
@override_method = params["_method"] _method = params["_method"]
@override_method = if _method.is_a?(Array)
_method.last
else
_method
end
end end
end end
@override_method @override_method
end end
# Checks if method contained in _method param is valid one # Checks if method contained in _method param is valid one
def self.override_method_valid?(override_method) def self.override_method_valid?(override_method)
return false unless override_method.is_a?(String) return false unless override_method.is_a?(String) || override_method.is_a?(Array(String))
override_method = override_method.last if override_method.is_a?(Array(String))
override_method = override_method.upcase override_method = override_method.upcase
override_method == "PUT" || override_method == "PATCH" || override_method == "DELETE" override_method == "PUT" || override_method == "PATCH" || override_method == "DELETE"
end end