mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #21671 from kaspth/integration-request-encoding-helpers
Add `as` to encode a request as a specific mime type.
This commit is contained in:
commit
688996da7b
2 changed files with 122 additions and 4 deletions
|
@ -321,7 +321,9 @@ module ActionDispatch
|
|||
end
|
||||
|
||||
# Performs the actual request.
|
||||
def process(method, path, params: nil, headers: nil, env: nil, xhr: false)
|
||||
def process(method, path, params: nil, headers: nil, env: nil, xhr: false, as: nil)
|
||||
request_encoder = RequestEncoder.encoder(as)
|
||||
|
||||
if path =~ %r{://}
|
||||
location = URI.parse(path)
|
||||
https! URI::HTTPS === location if location.scheme
|
||||
|
@ -330,14 +332,17 @@ module ActionDispatch
|
|||
url_host += ":#{location.port}" if default != location.port
|
||||
host! url_host
|
||||
end
|
||||
path = location.query ? "#{location.path}?#{location.query}" : location.path
|
||||
path = request_encoder.append_format_to location.path
|
||||
path = location.query ? "#{path}?#{location.query}" : path
|
||||
else
|
||||
path = request_encoder.append_format_to path
|
||||
end
|
||||
|
||||
hostname, port = host.split(':')
|
||||
|
||||
request_env = {
|
||||
:method => method,
|
||||
:params => params,
|
||||
:params => request_encoder.encode_params(params),
|
||||
|
||||
"SERVER_NAME" => hostname,
|
||||
"SERVER_PORT" => port || (https? ? "443" : "80"),
|
||||
|
@ -347,7 +352,7 @@ module ActionDispatch
|
|||
"REQUEST_URI" => path,
|
||||
"HTTP_HOST" => host,
|
||||
"REMOTE_ADDR" => remote_addr,
|
||||
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
|
||||
"CONTENT_TYPE" => request_encoder.content_type,
|
||||
"HTTP_ACCEPT" => accept
|
||||
}
|
||||
|
||||
|
@ -387,6 +392,48 @@ module ActionDispatch
|
|||
def build_full_uri(path, env)
|
||||
"#{env['rack.url_scheme']}://#{env['SERVER_NAME']}:#{env['SERVER_PORT']}#{path}"
|
||||
end
|
||||
|
||||
class RequestEncoder # :nodoc:
|
||||
@encoders = {}
|
||||
|
||||
def initialize(mime_name, param_encoder, url_encoded_form = false)
|
||||
@mime = Mime[mime_name]
|
||||
|
||||
unless @mime
|
||||
raise ArgumentError, "Can't register a request encoder for " \
|
||||
"unregistered MIME Type: #{mime_name}. See `Mime::Type.register`."
|
||||
end
|
||||
|
||||
@url_encoded_form = url_encoded_form
|
||||
@path_format = ".#{@mime.symbol}" unless @url_encoded_form
|
||||
@param_encoder = param_encoder || :"to_#{@mime.symbol}".to_proc
|
||||
end
|
||||
|
||||
def append_format_to(path)
|
||||
path << @path_format unless @url_encoded_form
|
||||
path
|
||||
end
|
||||
|
||||
def content_type
|
||||
@mime.to_s
|
||||
end
|
||||
|
||||
def encode_params(params)
|
||||
@param_encoder.call(params)
|
||||
end
|
||||
|
||||
def self.encoder(name)
|
||||
@encoders[name] || WWWFormEncoder
|
||||
end
|
||||
|
||||
def self.register_encoder(mime_name, ¶m_encoder)
|
||||
@encoders[mime_name] = new(mime_name, param_encoder)
|
||||
end
|
||||
|
||||
register_encoder :json
|
||||
|
||||
WWWFormEncoder = new(:url_encoded_form, -> params { params }, true)
|
||||
end
|
||||
end
|
||||
|
||||
module Runner
|
||||
|
@ -643,6 +690,30 @@ module ActionDispatch
|
|||
# end
|
||||
# end
|
||||
#
|
||||
# You can also test your JSON API easily by setting what the request should
|
||||
# be encoded as:
|
||||
#
|
||||
# require 'test_helper'
|
||||
#
|
||||
# class ApiTest < ActionDispatch::IntegrationTest
|
||||
# test "creates articles" do
|
||||
# assert_difference -> { Article.count } do
|
||||
# post articles_path, params: { article: { title: 'Ahoy!' } }, as: :json
|
||||
# end
|
||||
#
|
||||
# assert_response :success
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# The `as` option sets the format to JSON, sets the content type to
|
||||
# 'application/json' and encodes the parameters as JSON.
|
||||
#
|
||||
# For any custom MIME Types you've registered, you can even add your own encoders with:
|
||||
#
|
||||
# ActionDispatch::IntegrationTest.register_encoder :wibble do |params|
|
||||
# params.to_wibble
|
||||
# end
|
||||
#
|
||||
# Consult the Rails Testing Guide for more.
|
||||
|
||||
class IntegrationTest < ActiveSupport::TestCase
|
||||
|
@ -671,5 +742,9 @@ module ActionDispatch
|
|||
def document_root_element
|
||||
html_document.root
|
||||
end
|
||||
|
||||
def self.register_encoder(*args, ¶m_encoder)
|
||||
Integration::Session::RequestEncoder.register_encoder(*args, ¶m_encoder)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1126,3 +1126,46 @@ class IntegrationRequestsWithSessionSetup < ActionDispatch::IntegrationTest
|
|||
assert_equal({"user_name"=>"david"}, cookies.to_hash)
|
||||
end
|
||||
end
|
||||
|
||||
class IntegrationRequestEncodersTest < ActionDispatch::IntegrationTest
|
||||
class FooController < ActionController::Base
|
||||
def foos
|
||||
render plain: 'ok'
|
||||
end
|
||||
end
|
||||
|
||||
def test_encoding_as_json
|
||||
assert_encoded_as :json, content_type: 'application/json'
|
||||
end
|
||||
|
||||
def test_encoding_as_without_mime_registration
|
||||
assert_raise ArgumentError do
|
||||
ActionDispatch::IntegrationTest.register_encoder :wibble
|
||||
end
|
||||
end
|
||||
|
||||
def test_registering_custom_encoder
|
||||
Mime::Type.register 'text/wibble', :wibble
|
||||
|
||||
ActionDispatch::IntegrationTest.register_encoder(:wibble, &:itself)
|
||||
|
||||
assert_encoded_as :wibble, content_type: 'text/wibble',
|
||||
parsed_parameters: Hash.new # Unregistered MIME Type can't be parsed
|
||||
ensure
|
||||
Mime::Type.unregister :wibble
|
||||
end
|
||||
|
||||
private
|
||||
def assert_encoded_as(format, content_type:, parsed_parameters: { 'foo' => 'fighters' })
|
||||
with_routing do |routes|
|
||||
routes.draw { post ':action' => FooController }
|
||||
|
||||
post '/foos', params: { foo: 'fighters' }, as: format
|
||||
|
||||
assert_response :success
|
||||
assert_match "foos.#{format}", request.path
|
||||
assert_equal content_type, request.content_type
|
||||
assert_equal parsed_parameters, request.request_parameters
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue