1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/actionpack/test/dispatch/request/json_params_parsing_test.rb
Andrew White 6520ea5f7e Deprecate :controller and :action path parameters
Allowing :controller and :action values to be specified via the path
in config/routes.rb has been an underlying cause of a number of issues
in Rails that have resulted in security releases. In light of this it's
better that controllers and actions are explicitly whitelisted rather
than trying to blacklist or sanitize 'bad' values.
2016-03-01 08:48:53 +00:00

203 lines
6.4 KiB
Ruby

require 'abstract_unit'
class JsonParamsParsingTest < ActionDispatch::IntegrationTest
class TestController < ActionController::Base
class << self
attr_accessor :last_request_parameters
end
def parse
self.class.last_request_parameters = request.request_parameters
head :ok
end
end
def teardown
TestController.last_request_parameters = nil
end
test "parses json params for application json" do
assert_parses(
{"person" => {"name" => "David"}},
"{\"person\": {\"name\": \"David\"}}", { 'CONTENT_TYPE' => 'application/json' }
)
end
test "parses boolean and number json params for application json" do
assert_parses(
{"item" => {"enabled" => false, "count" => 10}},
"{\"item\": {\"enabled\": false, \"count\": 10}}", { 'CONTENT_TYPE' => 'application/json' }
)
end
test "parses json params for application jsonrequest" do
assert_parses(
{"person" => {"name" => "David"}},
"{\"person\": {\"name\": \"David\"}}", { 'CONTENT_TYPE' => 'application/jsonrequest' }
)
end
test "does not parse unregistered media types such as application/vnd.api+json" do
assert_parses(
{},
"{\"person\": {\"name\": \"David\"}}", { 'CONTENT_TYPE' => 'application/vnd.api+json' }
)
end
test "nils are stripped from collections" do
assert_parses(
{"person" => []},
"{\"person\":[null]}", { 'CONTENT_TYPE' => 'application/json' }
)
assert_parses(
{"person" => ['foo']},
"{\"person\":[\"foo\",null]}", { 'CONTENT_TYPE' => 'application/json' }
)
assert_parses(
{"person" => []},
"{\"person\":[null, null]}", { 'CONTENT_TYPE' => 'application/json' }
)
end
test "logs error if parsing unsuccessful" do
with_test_routing do
output = StringIO.new
json = "[\"person]\": {\"name\": \"David\"}}"
post "/parse", params: json, headers: { 'CONTENT_TYPE' => 'application/json', 'action_dispatch.show_exceptions' => true, 'action_dispatch.logger' => ActiveSupport::Logger.new(output) }
assert_response :bad_request
output.rewind && err = output.read
assert err =~ /Error occurred while parsing request parameters/
end
end
test "occurring a parse error if parsing unsuccessful" do
with_test_routing do
begin
$stderr = StringIO.new # suppress the log
json = "[\"person]\": {\"name\": \"David\"}}"
exception = assert_raise(ActionDispatch::ParamsParser::ParseError) { post "/parse", json, {'CONTENT_TYPE' => 'application/json', 'action_dispatch.show_exceptions' => false} }
assert_equal JSON::ParserError, exception.cause.class
assert_equal exception.cause.message, exception.message
ensure
$stderr = STDERR
end
end
end
test 'raw_post is not empty for JSON request' do
with_test_routing do
post '/parse', params: '{"posts": [{"title": "Post Title"}]}', headers: { 'CONTENT_TYPE' => 'application/json' }
assert_equal '{"posts": [{"title": "Post Title"}]}', request.raw_post
end
end
private
def assert_parses(expected, actual, headers = {})
with_test_routing do
post "/parse", params: actual, headers: headers
assert_response :ok
assert_equal(expected, TestController.last_request_parameters)
end
end
def with_test_routing
with_routing do |set|
set.draw do
ActiveSupport::Deprecation.silence do
post ':action', :to => ::JsonParamsParsingTest::TestController
end
end
yield
end
end
end
class RootLessJSONParamsParsingTest < ActionDispatch::IntegrationTest
class UsersController < ActionController::Base
wrap_parameters :format => :json
class << self
attr_accessor :last_request_parameters, :last_parameters
end
def parse
self.class.last_request_parameters = request.request_parameters
self.class.last_parameters = params.to_unsafe_h
head :ok
end
end
def teardown
UsersController.last_request_parameters = nil
end
test "parses json params for application json" do
assert_parses(
{"user" => {"username" => "sikachu"}, "username" => "sikachu"},
"{\"username\": \"sikachu\"}", { 'CONTENT_TYPE' => 'application/json' }
)
end
test "parses json params for application jsonrequest" do
assert_parses(
{"user" => {"username" => "sikachu"}, "username" => "sikachu"},
"{\"username\": \"sikachu\"}", { 'CONTENT_TYPE' => 'application/jsonrequest' }
)
end
test "parses json with non-object JSON content" do
assert_parses(
{"user" => {"_json" => "string content" }, "_json" => "string content" },
"\"string content\"", { 'CONTENT_TYPE' => 'application/json' }
)
end
test "parses json params after custom json mime type registered" do
begin
Mime::Type.unregister :json
Mime::Type.register "application/json", :json, %w(application/vnd.api+json)
assert_parses(
{"user" => {"username" => "meinac"}, "username" => "meinac"},
"{\"username\": \"meinac\"}", { 'CONTENT_TYPE' => 'application/json' }
)
ensure
Mime::Type.unregister :json
Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest )
end
end
test "parses json params after custom json mime type registered with synonym" do
begin
Mime::Type.unregister :json
Mime::Type.register "application/json", :json, %w(application/vnd.api+json)
assert_parses(
{"user" => {"username" => "meinac"}, "username" => "meinac"},
"{\"username\": \"meinac\"}", { 'CONTENT_TYPE' => 'application/vnd.api+json' }
)
ensure
Mime::Type.unregister :json
Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest )
end
end
private
def assert_parses(expected, actual, headers = {})
with_test_routing(UsersController) do
post "/parse", params: actual, headers: headers
assert_response :ok
assert_equal(expected, UsersController.last_request_parameters)
assert_equal(expected.merge({"action" => "parse"}), UsersController.last_parameters)
end
end
def with_test_routing(controller)
with_routing do |set|
set.draw do
ActiveSupport::Deprecation.silence do
post ':action', :to => controller
end
end
yield
end
end
end