diff --git a/spec/std/http/request_spec.cr b/spec/std/http/request_spec.cr index b030692fc842..f997ca8998bc 100644 --- a/spec/std/http/request_spec.cr +++ b/spec/std/http/request_spec.cr @@ -438,7 +438,30 @@ module HTTP request.query = new_query request.query_params.to_s.should eq(new_query) end + end + + describe "#form_params" do + it "returns can safely be called on get requests" do + request = Request.from_io(IO::Memory.new("GET /api/v3/some/resource HTTP/1.1\r\n\r\n")).as(Request) + request.form_params?.should eq(nil) + request.form_params.size.should eq(0) + end + + it "returns parsed HTTP::Params" do + request = Request.new("POST", "/form", HTTP::Headers{"Content-Type" => "application/x-www-form-urlencoded"}, HTTP::Params.encode({"test" => "foobar"})) + request.form_params?.should_not eq(nil) + request.form_params.size.should eq(1) + request.form_params["test"].should eq("foobar") + end + it "returns ignors invalid content-type" do + request = Request.new("POST", "/form", nil, HTTP::Params.encode({"test" => "foobar"})) + request.form_params?.should eq(nil) + request.form_params.size.should eq(0) + end + end + + describe "#hostname" do it "gets request hostname from the headers" do request = Request.from_io(IO::Memory.new("GET / HTTP/1.1\r\nHost: host.example.org:3000\r\nReferer:\r\n\r\n")).as(Request) request.hostname.should eq("host.example.org") @@ -472,7 +495,9 @@ module HTTP request = Request.new("GET", "/") request.hostname.should be_nil end + end + describe "#host_with_port" do it "gets request host with port from the headers" do request = Request.from_io(IO::Memory.new("GET / HTTP/1.1\r\nHost: host.example.org:3000\r\nReferer:\r\n\r\n")).as(Request) request.host_with_port.should eq("host.example.org:3000") diff --git a/src/http/request.cr b/src/http/request.cr index c6a72d3469c0..185ee99c56bf 100644 --- a/src/http/request.cr +++ b/src/http/request.cr @@ -21,6 +21,7 @@ class HTTP::Request property version : String @cookies : Cookies? @query_params : URI::Params? + @form_params : HTTP::Params? @uri : URI? # The network address that sent the request to an HTTP server. @@ -80,6 +81,24 @@ class HTTP::Request @query_params ||= uri.query_params end + # Returns a convenience wrapper to parse form params, see `URI::Params`. + # Returns `nil` in case the content type `"application/x-www-form-urlencoded"` + # is not present or the body is `nil`. + def form_params? : HTTP::Params? + @form_params ||= begin + if headers["Content-Type"]? == "application/x-www-form-urlencoded" + if body = self.body + HTTP::Params.parse(body.gets_to_end) + end + end + end + end + + # Returns a convenience wrapper to parse form params, see `URI::Params`. + def form_params : HTTP::Params + form_params? || HTTP::Params.new + end + def resource : String update_uri @uri.try(&.request_target) || @resource