mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Switch over to rack-test gem
This commit is contained in:
parent
6f40139b53
commit
c63dac81c1
9 changed files with 4 additions and 642 deletions
|
@ -116,6 +116,7 @@ spec = Gem::Specification.new do |s|
|
||||||
s.requirements << 'none'
|
s.requirements << 'none'
|
||||||
|
|
||||||
s.add_dependency('activesupport', '= 3.0.pre' + PKG_BUILD)
|
s.add_dependency('activesupport', '= 3.0.pre' + PKG_BUILD)
|
||||||
|
s.add_dependency('rack-test', '~> 0.4.1')
|
||||||
|
|
||||||
s.require_path = 'lib'
|
s.require_path = 'lib'
|
||||||
s.autorequire = 'action_controller'
|
s.autorequire = 'action_controller'
|
||||||
|
|
|
@ -33,7 +33,9 @@ end
|
||||||
|
|
||||||
require 'rack'
|
require 'rack'
|
||||||
|
|
||||||
$:.unshift "#{File.dirname(__FILE__)}/action_dispatch/vendor/rack-test"
|
module Rack
|
||||||
|
autoload :Test, 'rack/test'
|
||||||
|
end
|
||||||
|
|
||||||
module ActionDispatch
|
module ActionDispatch
|
||||||
autoload :Request, 'action_dispatch/http/request'
|
autoload :Request, 'action_dispatch/http/request'
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
module Rack
|
|
||||||
|
|
||||||
class MockSession
|
|
||||||
attr_writer :cookie_jar
|
|
||||||
attr_reader :last_response
|
|
||||||
|
|
||||||
def initialize(app, default_host = Rack::Test::DEFAULT_HOST)
|
|
||||||
@app = app
|
|
||||||
@default_host = default_host
|
|
||||||
end
|
|
||||||
|
|
||||||
def clear_cookies
|
|
||||||
@cookie_jar = Rack::Test::CookieJar.new([], @default_host)
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_cookie(cookie, uri = nil)
|
|
||||||
cookie_jar.merge(cookie, uri)
|
|
||||||
end
|
|
||||||
|
|
||||||
def request(uri, env)
|
|
||||||
env["HTTP_COOKIE"] ||= cookie_jar.for(uri)
|
|
||||||
@last_request = Rack::Request.new(env)
|
|
||||||
status, headers, body = @app.call(@last_request.env)
|
|
||||||
@last_response = MockResponse.new(status, headers, body, env["rack.errors"].flush)
|
|
||||||
cookie_jar.merge(last_response.headers["Set-Cookie"], uri)
|
|
||||||
|
|
||||||
@last_response
|
|
||||||
end
|
|
||||||
|
|
||||||
# Return the last request issued in the session. Raises an error if no
|
|
||||||
# requests have been sent yet.
|
|
||||||
def last_request
|
|
||||||
raise Rack::Test::Error.new("No request yet. Request a page first.") unless @last_request
|
|
||||||
@last_request
|
|
||||||
end
|
|
||||||
|
|
||||||
# Return the last response received in the session. Raises an error if
|
|
||||||
# no requests have been sent yet.
|
|
||||||
def last_response
|
|
||||||
raise Rack::Test::Error.new("No response yet. Request a page first.") unless @last_response
|
|
||||||
@last_response
|
|
||||||
end
|
|
||||||
|
|
||||||
def cookie_jar
|
|
||||||
@cookie_jar ||= Rack::Test::CookieJar.new([], @default_host)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
|
@ -1,239 +0,0 @@
|
||||||
unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__) + "/.."))
|
|
||||||
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/.."))
|
|
||||||
end
|
|
||||||
|
|
||||||
require "uri"
|
|
||||||
require "rack"
|
|
||||||
require "rack/mock_session"
|
|
||||||
require "rack/test/cookie_jar"
|
|
||||||
require "rack/test/mock_digest_request"
|
|
||||||
require "rack/test/utils"
|
|
||||||
require "rack/test/methods"
|
|
||||||
require "rack/test/uploaded_file"
|
|
||||||
|
|
||||||
module Rack
|
|
||||||
module Test
|
|
||||||
|
|
||||||
VERSION = "0.3.0"
|
|
||||||
|
|
||||||
DEFAULT_HOST = "example.org"
|
|
||||||
MULTIPART_BOUNDARY = "----------XnJLe9ZIbbGUYtzPQJ16u1"
|
|
||||||
|
|
||||||
# The common base class for exceptions raised by Rack::Test
|
|
||||||
class Error < StandardError; end
|
|
||||||
|
|
||||||
class Session
|
|
||||||
extend Forwardable
|
|
||||||
include Rack::Test::Utils
|
|
||||||
|
|
||||||
def_delegators :@rack_mock_session, :clear_cookies, :set_cookie, :last_response, :last_request
|
|
||||||
|
|
||||||
# Initialize a new session for the given Rack app
|
|
||||||
def initialize(app, default_host = DEFAULT_HOST)
|
|
||||||
@headers = {}
|
|
||||||
@default_host = default_host
|
|
||||||
@rack_mock_session = Rack::MockSession.new(app, default_host)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Issue a GET request for the given URI with the given params and Rack
|
|
||||||
# environment. Stores the issues request object in #last_request and
|
|
||||||
# the app's response in #last_response. Yield #last_response to a block
|
|
||||||
# if given.
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# get "/"
|
|
||||||
def get(uri, params = {}, env = {}, &block)
|
|
||||||
env = env_for(uri, env.merge(:method => "GET", :params => params))
|
|
||||||
process_request(uri, env, &block)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Issue a POST request for the given URI. See #get
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# post "/signup", "name" => "Bryan"
|
|
||||||
def post(uri, params = {}, env = {}, &block)
|
|
||||||
env = env_for(uri, env.merge(:method => "POST", :params => params))
|
|
||||||
process_request(uri, env, &block)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Issue a PUT request for the given URI. See #get
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# put "/"
|
|
||||||
def put(uri, params = {}, env = {}, &block)
|
|
||||||
env = env_for(uri, env.merge(:method => "PUT", :params => params))
|
|
||||||
process_request(uri, env, &block)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Issue a DELETE request for the given URI. See #get
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# delete "/"
|
|
||||||
def delete(uri, params = {}, env = {}, &block)
|
|
||||||
env = env_for(uri, env.merge(:method => "DELETE", :params => params))
|
|
||||||
process_request(uri, env, &block)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Issue a HEAD request for the given URI. See #get
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# head "/"
|
|
||||||
def head(uri, params = {}, env = {}, &block)
|
|
||||||
env = env_for(uri, env.merge(:method => "HEAD", :params => params))
|
|
||||||
process_request(uri, env, &block)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Issue a request to the Rack app for the given URI and optional Rack
|
|
||||||
# environment. Stores the issues request object in #last_request and
|
|
||||||
# the app's response in #last_response. Yield #last_response to a block
|
|
||||||
# if given.
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# request "/"
|
|
||||||
def request(uri, env = {}, &block)
|
|
||||||
env = env_for(uri, env)
|
|
||||||
process_request(uri, env, &block)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Set a header to be included on all subsequent requests through the
|
|
||||||
# session. Use a value of nil to remove a previously configured header.
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# header "User-Agent", "Firefox"
|
|
||||||
def header(name, value)
|
|
||||||
if value.nil?
|
|
||||||
@headers.delete(name)
|
|
||||||
else
|
|
||||||
@headers[name] = value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Set the username and password for HTTP Basic authorization, to be
|
|
||||||
# included in subsequent requests in the HTTP_AUTHORIZATION header.
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# basic_authorize "bryan", "secret"
|
|
||||||
def basic_authorize(username, password)
|
|
||||||
encoded_login = ["#{username}:#{password}"].pack("m*")
|
|
||||||
header('HTTP_AUTHORIZATION', "Basic #{encoded_login}")
|
|
||||||
end
|
|
||||||
|
|
||||||
alias_method :authorize, :basic_authorize
|
|
||||||
|
|
||||||
def digest_authorize(username, password)
|
|
||||||
@digest_username = username
|
|
||||||
@digest_password = password
|
|
||||||
end
|
|
||||||
|
|
||||||
# Rack::Test will not follow any redirects automatically. This method
|
|
||||||
# will follow the redirect returned in the last response. If the last
|
|
||||||
# response was not a redirect, an error will be raised.
|
|
||||||
def follow_redirect!
|
|
||||||
unless last_response.redirect?
|
|
||||||
raise Error.new("Last response was not a redirect. Cannot follow_redirect!")
|
|
||||||
end
|
|
||||||
|
|
||||||
get(last_response["Location"])
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def env_for(path, env)
|
|
||||||
uri = URI.parse(path)
|
|
||||||
uri.host ||= @default_host
|
|
||||||
|
|
||||||
env = default_env.merge(env)
|
|
||||||
|
|
||||||
env.update("HTTPS" => "on") if URI::HTTPS === uri
|
|
||||||
env["X-Requested-With"] = "XMLHttpRequest" if env[:xhr]
|
|
||||||
|
|
||||||
if (env[:method] == "POST" || env["REQUEST_METHOD"] == "POST") && !env.has_key?(:input)
|
|
||||||
env["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
|
|
||||||
|
|
||||||
multipart = (Hash === env[:params]) &&
|
|
||||||
env[:params].any? { |_, v| UploadedFile === v }
|
|
||||||
|
|
||||||
if multipart
|
|
||||||
env[:input] = multipart_body(env.delete(:params))
|
|
||||||
env["CONTENT_LENGTH"] ||= env[:input].length.to_s
|
|
||||||
env["CONTENT_TYPE"] = "multipart/form-data; boundary=#{MULTIPART_BOUNDARY}"
|
|
||||||
else
|
|
||||||
env[:input] = params_to_string(env.delete(:params))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
params = env[:params] || {}
|
|
||||||
params.update(parse_query(uri.query))
|
|
||||||
|
|
||||||
uri.query = requestify(params)
|
|
||||||
|
|
||||||
if env.has_key?(:cookie)
|
|
||||||
set_cookie(env.delete(:cookie), uri)
|
|
||||||
end
|
|
||||||
|
|
||||||
Rack::MockRequest.env_for(uri.to_s, env)
|
|
||||||
end
|
|
||||||
|
|
||||||
def process_request(uri, env)
|
|
||||||
uri = URI.parse(uri)
|
|
||||||
uri.host ||= @default_host
|
|
||||||
|
|
||||||
@rack_mock_session.request(uri, env)
|
|
||||||
|
|
||||||
if retry_with_digest_auth?(env)
|
|
||||||
auth_env = env.merge({
|
|
||||||
"HTTP_AUTHORIZATION" => digest_auth_header,
|
|
||||||
"rack-test.digest_auth_retry" => true
|
|
||||||
})
|
|
||||||
auth_env.delete('rack.request')
|
|
||||||
process_request(uri.path, auth_env)
|
|
||||||
else
|
|
||||||
yield last_response if block_given?
|
|
||||||
|
|
||||||
last_response
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def digest_auth_header
|
|
||||||
challenge = last_response["WWW-Authenticate"].split(" ", 2).last
|
|
||||||
params = Rack::Auth::Digest::Params.parse(challenge)
|
|
||||||
|
|
||||||
params.merge!({
|
|
||||||
"username" => @digest_username,
|
|
||||||
"nc" => "00000001",
|
|
||||||
"cnonce" => "nonsensenonce",
|
|
||||||
"uri" => last_request.path_info,
|
|
||||||
"method" => last_request.env["REQUEST_METHOD"],
|
|
||||||
})
|
|
||||||
|
|
||||||
params["response"] = MockDigestRequest.new(params).response(@digest_password)
|
|
||||||
|
|
||||||
"Digest #{params}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def retry_with_digest_auth?(env)
|
|
||||||
last_response.status == 401 &&
|
|
||||||
digest_auth_configured? &&
|
|
||||||
!env["rack-test.digest_auth_retry"]
|
|
||||||
end
|
|
||||||
|
|
||||||
def digest_auth_configured?
|
|
||||||
@digest_username
|
|
||||||
end
|
|
||||||
|
|
||||||
def default_env
|
|
||||||
{ "rack.test" => true, "REMOTE_ADDR" => "127.0.0.1" }.merge(@headers)
|
|
||||||
end
|
|
||||||
|
|
||||||
def params_to_string(params)
|
|
||||||
case params
|
|
||||||
when Hash then requestify(params)
|
|
||||||
when nil then ""
|
|
||||||
else params
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,169 +0,0 @@
|
||||||
require "uri"
|
|
||||||
module Rack
|
|
||||||
module Test
|
|
||||||
|
|
||||||
class Cookie
|
|
||||||
include Rack::Utils
|
|
||||||
|
|
||||||
# :api: private
|
|
||||||
attr_reader :name, :value
|
|
||||||
|
|
||||||
# :api: private
|
|
||||||
def initialize(raw, uri = nil, default_host = DEFAULT_HOST)
|
|
||||||
@default_host = default_host
|
|
||||||
uri ||= default_uri
|
|
||||||
|
|
||||||
# separate the name / value pair from the cookie options
|
|
||||||
@name_value_raw, options = raw.split(/[;,] */n, 2)
|
|
||||||
|
|
||||||
@name, @value = parse_query(@name_value_raw, ';').to_a.first
|
|
||||||
@options = parse_query(options, ';')
|
|
||||||
|
|
||||||
@options["domain"] ||= (uri.host || default_host)
|
|
||||||
@options["path"] ||= uri.path.sub(/\/[^\/]*\Z/, "")
|
|
||||||
end
|
|
||||||
|
|
||||||
def replaces?(other)
|
|
||||||
[name.downcase, domain, path] == [other.name.downcase, other.domain, other.path]
|
|
||||||
end
|
|
||||||
|
|
||||||
# :api: private
|
|
||||||
def raw
|
|
||||||
@name_value_raw
|
|
||||||
end
|
|
||||||
|
|
||||||
# :api: private
|
|
||||||
def empty?
|
|
||||||
@value.nil? || @value.empty?
|
|
||||||
end
|
|
||||||
|
|
||||||
# :api: private
|
|
||||||
def domain
|
|
||||||
@options["domain"]
|
|
||||||
end
|
|
||||||
|
|
||||||
def secure?
|
|
||||||
@options.has_key?("secure")
|
|
||||||
end
|
|
||||||
|
|
||||||
# :api: private
|
|
||||||
def path
|
|
||||||
@options["path"].strip || "/"
|
|
||||||
end
|
|
||||||
|
|
||||||
# :api: private
|
|
||||||
def expires
|
|
||||||
Time.parse(@options["expires"]) if @options["expires"]
|
|
||||||
end
|
|
||||||
|
|
||||||
# :api: private
|
|
||||||
def expired?
|
|
||||||
expires && expires < Time.now
|
|
||||||
end
|
|
||||||
|
|
||||||
# :api: private
|
|
||||||
def valid?(uri)
|
|
||||||
uri ||= default_uri
|
|
||||||
|
|
||||||
if uri.host.nil?
|
|
||||||
uri.host = @default_host
|
|
||||||
end
|
|
||||||
|
|
||||||
(!secure? || (secure? && uri.scheme == "https")) &&
|
|
||||||
uri.host =~ Regexp.new("#{Regexp.escape(domain)}$", Regexp::IGNORECASE) &&
|
|
||||||
uri.path =~ Regexp.new("^#{Regexp.escape(path)}")
|
|
||||||
end
|
|
||||||
|
|
||||||
# :api: private
|
|
||||||
def matches?(uri)
|
|
||||||
! expired? && valid?(uri)
|
|
||||||
end
|
|
||||||
|
|
||||||
# :api: private
|
|
||||||
def <=>(other)
|
|
||||||
# Orders the cookies from least specific to most
|
|
||||||
[name, path, domain.reverse] <=> [other.name, other.path, other.domain.reverse]
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def default_uri
|
|
||||||
URI.parse("//" + @default_host + "/")
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class CookieJar
|
|
||||||
|
|
||||||
# :api: private
|
|
||||||
def initialize(cookies = [], default_host = DEFAULT_HOST)
|
|
||||||
@default_host = default_host
|
|
||||||
@cookies = cookies
|
|
||||||
@cookies.sort!
|
|
||||||
end
|
|
||||||
|
|
||||||
def [](name)
|
|
||||||
cookies = hash_for(nil)
|
|
||||||
# TODO: Should be case insensitive
|
|
||||||
cookies[name] && cookies[name].value
|
|
||||||
end
|
|
||||||
|
|
||||||
def []=(name, value)
|
|
||||||
# TODO: needs proper escaping
|
|
||||||
merge("#{name}=#{value}")
|
|
||||||
end
|
|
||||||
|
|
||||||
def merge(raw_cookies, uri = nil)
|
|
||||||
return unless raw_cookies
|
|
||||||
|
|
||||||
raw_cookies.each_line do |raw_cookie|
|
|
||||||
cookie = Cookie.new(raw_cookie, uri, @default_host)
|
|
||||||
self << cookie if cookie.valid?(uri)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def <<(new_cookie)
|
|
||||||
@cookies.reject! do |existing_cookie|
|
|
||||||
new_cookie.replaces?(existing_cookie)
|
|
||||||
end
|
|
||||||
|
|
||||||
@cookies << new_cookie
|
|
||||||
@cookies.sort!
|
|
||||||
end
|
|
||||||
|
|
||||||
# :api: private
|
|
||||||
def for(uri)
|
|
||||||
hash_for(uri).values.map { |c| c.raw }.join(';')
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_hash
|
|
||||||
cookies = {}
|
|
||||||
|
|
||||||
hash_for(nil).each do |name, cookie|
|
|
||||||
cookies[name] = cookie.value
|
|
||||||
end
|
|
||||||
|
|
||||||
return cookies
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def hash_for(uri = nil)
|
|
||||||
cookies = {}
|
|
||||||
|
|
||||||
# The cookies are sorted by most specific first. So, we loop through
|
|
||||||
# all the cookies in order and add it to a hash by cookie name if
|
|
||||||
# the cookie can be sent to the current URI. It's added to the hash
|
|
||||||
# so that when we are done, the cookies will be unique by name and
|
|
||||||
# we'll have grabbed the most specific to the URI.
|
|
||||||
@cookies.each do |cookie|
|
|
||||||
cookies[cookie.name] = cookie if cookie.matches?(uri)
|
|
||||||
end
|
|
||||||
|
|
||||||
return cookies
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,45 +0,0 @@
|
||||||
require "forwardable"
|
|
||||||
|
|
||||||
module Rack
|
|
||||||
module Test
|
|
||||||
module Methods
|
|
||||||
extend Forwardable
|
|
||||||
|
|
||||||
def rack_test_session
|
|
||||||
@_rack_test_session ||= Rack::Test::Session.new(app)
|
|
||||||
end
|
|
||||||
|
|
||||||
def rack_mock_session
|
|
||||||
@_rack_mock_session ||= Rack::MockSession.new(app)
|
|
||||||
end
|
|
||||||
|
|
||||||
METHODS = [
|
|
||||||
:request,
|
|
||||||
|
|
||||||
# HTTP verbs
|
|
||||||
:get,
|
|
||||||
:post,
|
|
||||||
:put,
|
|
||||||
:delete,
|
|
||||||
:head,
|
|
||||||
|
|
||||||
# Redirects
|
|
||||||
:follow_redirect!,
|
|
||||||
|
|
||||||
# Header-related features
|
|
||||||
:header,
|
|
||||||
:set_cookie,
|
|
||||||
:clear_cookies,
|
|
||||||
:authorize,
|
|
||||||
:basic_authorize,
|
|
||||||
:digest_authorize,
|
|
||||||
|
|
||||||
# Expose the last request and response
|
|
||||||
:last_response,
|
|
||||||
:last_request
|
|
||||||
]
|
|
||||||
|
|
||||||
def_delegators :rack_test_session, *METHODS
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,27 +0,0 @@
|
||||||
module Rack
|
|
||||||
module Test
|
|
||||||
|
|
||||||
class MockDigestRequest
|
|
||||||
def initialize(params)
|
|
||||||
@params = params
|
|
||||||
end
|
|
||||||
|
|
||||||
def method_missing(sym)
|
|
||||||
if @params.has_key? k = sym.to_s
|
|
||||||
return @params[k]
|
|
||||||
end
|
|
||||||
|
|
||||||
super
|
|
||||||
end
|
|
||||||
|
|
||||||
def method
|
|
||||||
@params['method']
|
|
||||||
end
|
|
||||||
|
|
||||||
def response(password)
|
|
||||||
Rack::Auth::Digest::MD5.new(nil).send :digest, self, password
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,36 +0,0 @@
|
||||||
require "tempfile"
|
|
||||||
|
|
||||||
module Rack
|
|
||||||
module Test
|
|
||||||
|
|
||||||
class UploadedFile
|
|
||||||
# The filename, *not* including the path, of the "uploaded" file
|
|
||||||
attr_reader :original_filename
|
|
||||||
|
|
||||||
# The content type of the "uploaded" file
|
|
||||||
attr_accessor :content_type
|
|
||||||
|
|
||||||
def initialize(path, content_type = "text/plain", binary = false)
|
|
||||||
raise "#{path} file does not exist" unless ::File.exist?(path)
|
|
||||||
@content_type = content_type
|
|
||||||
@original_filename = ::File.basename(path)
|
|
||||||
@tempfile = Tempfile.new(@original_filename)
|
|
||||||
@tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
|
|
||||||
@tempfile.binmode if binary
|
|
||||||
FileUtils.copy_file(path, @tempfile.path)
|
|
||||||
end
|
|
||||||
|
|
||||||
def path
|
|
||||||
@tempfile.path
|
|
||||||
end
|
|
||||||
|
|
||||||
alias_method :local_path, :path
|
|
||||||
|
|
||||||
def method_missing(method_name, *args, &block) #:nodoc:
|
|
||||||
@tempfile.__send__(method_name, *args, &block)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,75 +0,0 @@
|
||||||
module Rack
|
|
||||||
module Test
|
|
||||||
|
|
||||||
module Utils
|
|
||||||
include Rack::Utils
|
|
||||||
|
|
||||||
def requestify(value, prefix = nil)
|
|
||||||
case value
|
|
||||||
when Array
|
|
||||||
value.map do |v|
|
|
||||||
requestify(v, "#{prefix}[]")
|
|
||||||
end.join("&")
|
|
||||||
when Hash
|
|
||||||
value.map do |k, v|
|
|
||||||
requestify(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
|
|
||||||
end.join("&")
|
|
||||||
else
|
|
||||||
"#{prefix}=#{escape(value)}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
module_function :requestify
|
|
||||||
|
|
||||||
def multipart_requestify(params, first=true)
|
|
||||||
p = Hash.new
|
|
||||||
|
|
||||||
params.each do |key, value|
|
|
||||||
k = first ? key.to_s : "[#{key}]"
|
|
||||||
|
|
||||||
if Hash === value
|
|
||||||
multipart_requestify(value, false).each do |subkey, subvalue|
|
|
||||||
p[k + subkey] = subvalue
|
|
||||||
end
|
|
||||||
else
|
|
||||||
p[k] = value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return p
|
|
||||||
end
|
|
||||||
|
|
||||||
module_function :multipart_requestify
|
|
||||||
|
|
||||||
def multipart_body(params)
|
|
||||||
multipart_requestify(params).map do |key, value|
|
|
||||||
if value.respond_to?(:original_filename)
|
|
||||||
::File.open(value.path, "rb") do |f|
|
|
||||||
f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
|
|
||||||
|
|
||||||
<<-EOF
|
|
||||||
--#{MULTIPART_BOUNDARY}\r
|
|
||||||
Content-Disposition: form-data; name="#{key}"; filename="#{escape(value.original_filename)}"\r
|
|
||||||
Content-Type: #{value.content_type}\r
|
|
||||||
Content-Length: #{::File.stat(value.path).size}\r
|
|
||||||
\r
|
|
||||||
#{f.read}\r
|
|
||||||
EOF
|
|
||||||
end
|
|
||||||
else
|
|
||||||
<<-EOF
|
|
||||||
--#{MULTIPART_BOUNDARY}\r
|
|
||||||
Content-Disposition: form-data; name="#{key}"\r
|
|
||||||
\r
|
|
||||||
#{value}\r
|
|
||||||
EOF
|
|
||||||
end
|
|
||||||
end.join("")+"--#{MULTIPART_BOUNDARY}--\r"
|
|
||||||
end
|
|
||||||
|
|
||||||
module_function :multipart_body
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Reference in a new issue