Skip to content

Commit

Permalink
Allow GET request body data
Browse files Browse the repository at this point in the history
Related: #211

We don't merge GET request body data to get parameter by default.
Because it's commitee original rule so it's difficult to understand.
  • Loading branch information
ota42y committed Jan 28, 2019
1 parent f9efa01 commit 4717f43
Show file tree
Hide file tree
Showing 12 changed files with 81 additions and 14 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Options and their defaults:
|-----------:|------------:|------------:| :------------ |
|allow_form_params | true | true | Specifies that input can alternatively be specified as `application/x-www-form-urlencoded` parameters when possible. This won't work for more complex schema validations. |
|allow_query_params | true | true | Specifies that query string parameters will be taken into consideration when doing validation. |
|allow_get_body | true | false | Allow GET request body, which merge to request parameter. See (#211) |
|coerce_date_times | false | true | Convert the string with `"format": "date-time"` parameter to DateTime object. |
|coerce_form_params| false | true | Tries to convert POST data encoded into an `application/x-www-form-urlencoded` body (where values are all strings) into concrete types required by the schema. This works for `null` (empty value), `integer` (numeric value without decimals), `number` (numeric value) and `boolean` ("true" is converted to `true` and "false" to `false`). If coercion is not possible, the original value is passed unchanged to schema validation. |
|coerce_query_params| false | true | The same as `coerce_form_params`, but tries to coerce `GET` parameters encoded in a request's query string. |
Expand Down Expand Up @@ -285,6 +286,7 @@ Committee 3.* has many breaking changes so we recommend upgrading to the latest
2. Run your test suite and fix any deprecation warnings that appear.
3. Update to the latest 3.* release.
4. Switch to OpenAPI 3 if you'd like to do so.
(If you use GET request body data, don't forget to set allow_get_body true.)

Important changes are also described below.

Expand Down
5 changes: 5 additions & 0 deletions lib/committee/drivers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ def default_coerce_form_params
raise "needs implementation"
end

# Use GET request body to request parameter (request body merge to parameter)
def default_allow_get_body
raise "needs implementation"
end

# Whether parameters in a request's path will be considered and coerced
# by default.
def default_path_params
Expand Down
4 changes: 4 additions & 0 deletions lib/committee/drivers/hyper_schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ def default_coerce_form_params
false
end

def default_allow_get_body
true
end

# Whether parameters in a request's path will be considered and coerced by
# default.
def default_path_params
Expand Down
4 changes: 4 additions & 0 deletions lib/committee/drivers/open_api_2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ def default_coerce_form_params
true
end

def default_allow_get_body
true
end

# Whether parameters in a request's path will be considered and coerced by
# default.
def default_path_params
Expand Down
4 changes: 4 additions & 0 deletions lib/committee/drivers/open_api_3.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ def default_coerce_form_params
true
end

def default_allow_get_body
false
end

# Whether parameters in a request's path will be considered and coerced by
# default.
def default_path_params
Expand Down
26 changes: 14 additions & 12 deletions lib/committee/request_unpacker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ def initialize(request, options={})
@coerce_form_params = options[:coerce_form_params]
@optimistic_json = options[:optimistic_json]
@schema_validator = options[:schema_validator]
@allow_get_body = options[:allow_get_body]
end

def call
Expand Down Expand Up @@ -70,20 +71,21 @@ def indifferent_params(object)
end

def parse_json
if (body = @request.body.read).length != 0
@request.body.rewind
hash = JSON.parse(body)
# We want a hash specifically. '42', 42, and [42] will all be
# decoded properly, but we can't use them here.
if !hash.is_a?(Hash)
raise BadRequest,
"Invalid JSON input. Require object with parameters as keys."
end
indifferent_params(hash)
return nil if @request.request_method == "GET" && !@allow_get_body

body = @request.body.read
# if request body is empty, we just have empty params
else
nil
return nil if body.length == 0

@request.body.rewind
hash = JSON.parse(body)
# We want a hash specifically. '42', 42, and [42] will all be
# decoded properly, but we can't use them here.
if !hash.is_a?(Hash)
raise BadRequest,
"Invalid JSON input. Require object with parameters as keys."
end
indifferent_params(hash)
end

def headers
Expand Down
1 change: 1 addition & 0 deletions lib/committee/schema_validator/hyper_schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def request_unpack(request)
allow_query_params: validator_option.allow_query_params,
coerce_form_params: validator_option.coerce_form_params,
optimistic_json: validator_option.optimistic_json,
allow_get_body: validator_option.allow_get_body,
schema_validator: self
).call
end
Expand Down
1 change: 1 addition & 0 deletions lib/committee/schema_validator/open_api_3.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def request_unpack(request)
allow_query_params: validator_option.allow_query_params,
coerce_form_params: validator_option.coerce_form_params,
optimistic_json: validator_option.optimistic_json,
allow_get_body: validator_option.allow_get_body,
schema_validator: self
).call
end
Expand Down
11 changes: 10 additions & 1 deletion lib/committee/schema_validator/option.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
class Committee::SchemaValidator
class Option
attr_reader :coerce_recursive, :params_key, :allow_form_params, :allow_query_params, :optimistic_json, :coerce_form_params, :headers_key, :coerce_query_params, :coerce_path_params, :check_content_type, :check_header, :coerce_date_times, :prefix, :validate_success_only
attr_reader :coerce_recursive, :params_key,
:allow_form_params, :allow_query_params,
:optimistic_json,
:coerce_form_params, :headers_key,
:coerce_query_params, :coerce_path_params,
:check_content_type, :check_header,
:coerce_date_times, :prefix,
:validate_success_only, :allow_get_body

def initialize(options, schema, schema_type)
@headers_key = options[:headers_key] || "committee.headers"
Expand All @@ -23,6 +30,8 @@ def initialize(options, schema, schema_type)

@check_content_type = options.fetch(:check_content_type, true)
@check_header = options.fetch(:check_header, true)

@allow_get_body = options.fetch(:allow_get_body, schema.driver.default_allow_get_body)
end
end
end
1 change: 1 addition & 0 deletions test/drivers_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
:default_coerce_form_params => [],
:default_path_params => [],
:default_query_params => [],
:default_allow_get_body => [],
:name => [],
:parse => [nil],
:schema_class => [],
Expand Down
14 changes: 13 additions & 1 deletion test/middleware/request_validation_open_api_3_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,24 @@ def app
[200, {}, []]
}

@app = new_rack_app_with_lambda(check_parameter, schema: open_api_3_schema, coerce_date_times: true)
@app = new_rack_app_with_lambda(check_parameter,
schema: open_api_3_schema,
coerce_date_times: true,
allow_get_body: true)

get "/get_body_test", { no_problem: true }, { input: params.to_json }
assert_equal 200, last_response.status
end

it "get error given a datetime and with coerce_date_times enabled on GET endpoint with request body" do
params = { "datetime_string" => "2016-04-01T16:00:00.000+09:00" }

@app = new_rack_app(schema: open_api_3_schema, allow_get_body: false)

get "/get_body_test", { no_problem: true }, { input: params.to_json }
assert_equal 400, last_response.status
end

it "passes given a datetime and with coerce_date_times enabled on POST endpoint" do
params = {
"nested_array" => [
Expand Down
22 changes: 22 additions & 0 deletions test/request_unpacker_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -234,4 +234,26 @@
_, headers = Committee::RequestUnpacker.new(request, { allow_header_params: true }).call
assert_equal({ "FOO-BAR" => "some header value" }, headers)
end

it "use_get_body = true" do
env = {
"rack.input" => StringIO.new('{"x":1, "y":2}'),
"REQUEST_METHOD" => "GET",
"QUERY_STRING"=>"data=value&x=aaa",
}
request = Rack::Request.new(env)
params, _ = Committee::RequestUnpacker.new(request, { allow_query_params: true, allow_get_body: true }).call
assert_equal({ 'data' => 'value', 'x' => 1, 'y' => 2 }, params)
end

it "use_get_body = false" do
env = {
"rack.input" => StringIO.new('{"x":1, "y":2}'),
"REQUEST_METHOD" => "GET",
"QUERY_STRING"=>"data=value&x=aaa",
}
request = Rack::Request.new(env)
params, _ = Committee::RequestUnpacker.new(request, { allow_query_params: true, use_get_body: false }).call
assert_equal({ 'data' => 'value', 'x' => 'aaa' }, params)
end
end

0 comments on commit 4717f43

Please sign in to comment.