rack-test 0.6.3 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/History.md +229 -0
- data/README.md +140 -0
- data/lib/rack/mock_session.rb +6 -9
- data/lib/rack/test/cookie_jar.rb +38 -28
- data/lib/rack/test/methods.rb +22 -22
- data/lib/rack/test/mock_digest_request.rb +1 -5
- data/lib/rack/test/uploaded_file.rb +50 -19
- data/lib/rack/test/utils.rb +37 -43
- data/lib/rack/test/version.rb +5 -0
- data/lib/rack/test.rb +86 -85
- metadata +139 -60
- data/.document +0 -4
- data/.gitignore +0 -6
- data/Gemfile +0 -8
- data/Gemfile.lock +0 -41
- data/History.txt +0 -179
- data/README.rdoc +0 -85
- data/Rakefile +0 -33
- data/Thorfile +0 -114
- data/rack-test.gemspec +0 -77
- data/spec/fixtures/bar.txt +0 -1
- data/spec/fixtures/config.ru +0 -3
- data/spec/fixtures/fake_app.rb +0 -143
- data/spec/fixtures/foo.txt +0 -1
- data/spec/rack/test/cookie_spec.rb +0 -219
- data/spec/rack/test/digest_auth_spec.rb +0 -46
- data/spec/rack/test/multipart_spec.rb +0 -145
- data/spec/rack/test/uploaded_file_spec.rb +0 -24
- data/spec/rack/test/utils_spec.rb +0 -193
- data/spec/rack/test_spec.rb +0 -550
- data/spec/spec_helper.rb +0 -69
- data/spec/support/matchers/body.rb +0 -9
- data/spec/support/matchers/challenge.rb +0 -11
@@ -1,16 +1,15 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'fileutils'
|
2
|
+
require 'pathname'
|
3
|
+
require 'tempfile'
|
3
4
|
|
4
5
|
module Rack
|
5
6
|
module Test
|
6
|
-
|
7
7
|
# Wraps a Tempfile with a content type. Including one or more UploadedFile's
|
8
8
|
# in the params causes Rack::Test to build and issue a multipart request.
|
9
9
|
#
|
10
10
|
# Example:
|
11
11
|
# post "/photos", "file" => Rack::Test::UploadedFile.new("me.jpg", "image/jpeg")
|
12
12
|
class UploadedFile
|
13
|
-
|
14
13
|
# The filename, *not* including the path, of the "uploaded" file
|
15
14
|
attr_reader :original_filename
|
16
15
|
|
@@ -20,34 +19,66 @@ module Rack
|
|
20
19
|
# The content type of the "uploaded" file
|
21
20
|
attr_accessor :content_type
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
# Creates a new UploadedFile instance.
|
23
|
+
#
|
24
|
+
# @param content [IO, Pathname, String, StringIO] a path to a file, or an {IO} or {StringIO} object representing the
|
25
|
+
# file.
|
26
|
+
# @param content_type [String]
|
27
|
+
# @param binary [Boolean] an optional flag that indicates whether the file should be open in binary mode or not.
|
28
|
+
# @param original_filename [String] an optional parameter that provides the original filename if `content` is a StringIO
|
29
|
+
# object. Not used for other kind of `content` objects.
|
30
|
+
def initialize(content, content_type = 'text/plain', binary = false, original_filename: nil)
|
31
|
+
if original_filename
|
32
|
+
initialize_from_stringio(content, original_filename)
|
33
|
+
else
|
34
|
+
initialize_from_file_path(content)
|
35
|
+
end
|
26
36
|
@content_type = content_type
|
27
|
-
@original_filename = ::File.basename(path)
|
28
|
-
|
29
|
-
@tempfile = Tempfile.new(@original_filename)
|
30
|
-
@tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
|
31
37
|
@tempfile.binmode if binary
|
32
|
-
|
33
|
-
FileUtils.copy_file(path, @tempfile.path)
|
34
38
|
end
|
35
39
|
|
36
40
|
def path
|
37
|
-
|
41
|
+
tempfile.path
|
38
42
|
end
|
39
43
|
|
40
|
-
|
44
|
+
alias local_path path
|
41
45
|
|
42
46
|
def method_missing(method_name, *args, &block) #:nodoc:
|
43
|
-
|
47
|
+
tempfile.public_send(method_name, *args, &block)
|
44
48
|
end
|
45
49
|
|
46
|
-
def
|
47
|
-
|
50
|
+
def respond_to_missing?(method_name, include_private = false) #:nodoc:
|
51
|
+
tempfile.respond_to?(method_name, include_private) || super
|
48
52
|
end
|
49
53
|
|
50
|
-
|
54
|
+
def self.finalize(file)
|
55
|
+
proc { actually_finalize file }
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.actually_finalize(file)
|
59
|
+
file.close
|
60
|
+
file.unlink
|
61
|
+
end
|
51
62
|
|
63
|
+
private
|
64
|
+
|
65
|
+
def initialize_from_stringio(stringio, original_filename)
|
66
|
+
@tempfile = stringio
|
67
|
+
@original_filename = original_filename || raise(ArgumentError, 'Missing `original_filename` for StringIO object')
|
68
|
+
end
|
69
|
+
|
70
|
+
def initialize_from_file_path(path)
|
71
|
+
raise "#{path} file does not exist" unless ::File.exist?(path)
|
72
|
+
|
73
|
+
@original_filename = ::File.basename(path)
|
74
|
+
|
75
|
+
@tempfile = Tempfile.new([@original_filename, ::File.extname(path)])
|
76
|
+
@tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
|
77
|
+
|
78
|
+
ObjectSpace.define_finalizer(self, self.class.finalize(@tempfile))
|
79
|
+
|
80
|
+
FileUtils.copy_file(path, @tempfile.path)
|
81
|
+
end
|
82
|
+
end
|
52
83
|
end
|
53
84
|
end
|
data/lib/rack/test/utils.rb
CHANGED
@@ -1,38 +1,36 @@
|
|
1
1
|
module Rack
|
2
2
|
module Test
|
3
|
-
|
4
3
|
module Utils # :nodoc:
|
5
4
|
include Rack::Utils
|
5
|
+
extend Rack::Utils
|
6
6
|
|
7
7
|
def build_nested_query(value, prefix = nil)
|
8
8
|
case value
|
9
9
|
when Array
|
10
|
-
value.
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
if value.empty?
|
11
|
+
"#{prefix}[]="
|
12
|
+
else
|
13
|
+
value.map do |v|
|
14
|
+
prefix = "#{prefix}[]" unless unescape(prefix) =~ /\[\]$/
|
15
|
+
build_nested_query(v, prefix.to_s)
|
16
|
+
end.join('&')
|
17
|
+
end
|
16
18
|
when Hash
|
17
19
|
value.map do |k, v|
|
18
20
|
build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
|
19
|
-
end.join(
|
21
|
+
end.join('&')
|
20
22
|
when NilClass
|
21
23
|
prefix.to_s
|
22
24
|
else
|
23
25
|
"#{prefix}=#{escape(value)}"
|
24
26
|
end
|
25
27
|
end
|
26
|
-
|
27
28
|
module_function :build_nested_query
|
28
29
|
|
29
|
-
def build_multipart(params, first = true)
|
30
|
+
def build_multipart(params, first = true, multipart = false)
|
30
31
|
if first
|
31
|
-
unless params.is_a?(Hash)
|
32
|
-
raise ArgumentError, "value must be a Hash"
|
33
|
-
end
|
32
|
+
raise ArgumentError, 'value must be a Hash' unless params.is_a?(Hash)
|
34
33
|
|
35
|
-
multipart = false
|
36
34
|
query = lambda { |value|
|
37
35
|
case value
|
38
36
|
when Array
|
@@ -47,7 +45,7 @@ module Rack
|
|
47
45
|
return nil unless multipart
|
48
46
|
end
|
49
47
|
|
50
|
-
flattened_params =
|
48
|
+
flattened_params = {}
|
51
49
|
|
52
50
|
params.each do |key, value|
|
53
51
|
k = first ? key.to_s : "[#{key}]"
|
@@ -55,23 +53,21 @@ module Rack
|
|
55
53
|
case value
|
56
54
|
when Array
|
57
55
|
value.map do |v|
|
58
|
-
|
59
|
-
if (v.is_a?(Hash))
|
56
|
+
if v.is_a?(Hash)
|
60
57
|
nested_params = {}
|
61
|
-
build_multipart(v, false).each
|
58
|
+
build_multipart(v, false).each do |subkey, subvalue|
|
62
59
|
nested_params[subkey] = subvalue
|
63
|
-
|
60
|
+
end
|
64
61
|
flattened_params["#{k}[]"] ||= []
|
65
62
|
flattened_params["#{k}[]"] << nested_params
|
66
63
|
else
|
67
64
|
flattened_params["#{k}[]"] = value
|
68
65
|
end
|
69
|
-
|
70
66
|
end
|
71
67
|
when Hash
|
72
|
-
build_multipart(value, false).each
|
68
|
+
build_multipart(value, false).each do |subkey, subvalue|
|
73
69
|
flattened_params[k + subkey] = subvalue
|
74
|
-
|
70
|
+
end
|
75
71
|
else
|
76
72
|
flattened_params[k] = value
|
77
73
|
end
|
@@ -83,27 +79,28 @@ module Rack
|
|
83
79
|
flattened_params
|
84
80
|
end
|
85
81
|
end
|
86
|
-
|
87
82
|
module_function :build_multipart
|
88
83
|
|
89
|
-
|
84
|
+
private
|
85
|
+
|
90
86
|
def build_parts(parameters)
|
91
87
|
get_parts(parameters).join + "--#{MULTIPART_BOUNDARY}--\r"
|
92
88
|
end
|
89
|
+
module_function :build_parts
|
93
90
|
|
94
91
|
def get_parts(parameters)
|
95
|
-
parameters.map
|
96
|
-
if name =~ /\[\]\Z/ && value.is_a?(Array) && value.all? {|v| v.is_a?(Hash)}
|
97
|
-
value.map
|
92
|
+
parameters.map do |name, value|
|
93
|
+
if name =~ /\[\]\Z/ && value.is_a?(Array) && value.all? { |v| v.is_a?(Hash) }
|
94
|
+
value.map do |hash|
|
98
95
|
new_value = {}
|
99
|
-
hash.each { |k, v| new_value[name+k] = v }
|
96
|
+
hash.each { |k, v| new_value[name + k] = v }
|
100
97
|
get_parts(new_value).join
|
101
|
-
|
98
|
+
end.join
|
102
99
|
else
|
103
100
|
if value.respond_to?(:original_filename)
|
104
101
|
build_file_part(name, value)
|
105
102
|
|
106
|
-
elsif value.is_a?(Array)
|
103
|
+
elsif value.is_a?(Array) && value.all? { |v| v.respond_to?(:original_filename) }
|
107
104
|
value.map do |v|
|
108
105
|
build_file_part(name, v)
|
109
106
|
end.join
|
@@ -113,15 +110,14 @@ module Rack
|
|
113
110
|
Rack::Test.encoding_aware_strings? ? primitive_part.force_encoding('BINARY') : primitive_part
|
114
111
|
end
|
115
112
|
end
|
116
|
-
|
113
|
+
end
|
117
114
|
end
|
115
|
+
module_function :get_parts
|
118
116
|
|
119
117
|
def build_primitive_part(parameter_name, value)
|
120
|
-
unless value.is_a? Array
|
121
|
-
value = [value]
|
122
|
-
end
|
118
|
+
value = [value] unless value.is_a? Array
|
123
119
|
value.map do |v|
|
124
|
-
<<-EOF
|
120
|
+
<<-EOF
|
125
121
|
--#{MULTIPART_BOUNDARY}\r
|
126
122
|
Content-Disposition: form-data; name="#{parameter_name}"\r
|
127
123
|
\r
|
@@ -129,22 +125,20 @@ Content-Disposition: form-data; name="#{parameter_name}"\r
|
|
129
125
|
EOF
|
130
126
|
end.join
|
131
127
|
end
|
128
|
+
module_function :build_primitive_part
|
132
129
|
|
133
130
|
def build_file_part(parameter_name, uploaded_file)
|
134
|
-
|
135
|
-
|
136
|
-
<<-EOF
|
131
|
+
uploaded_file.set_encoding(Encoding::BINARY) if uploaded_file.respond_to?(:set_encoding)
|
132
|
+
<<-EOF
|
137
133
|
--#{MULTIPART_BOUNDARY}\r
|
138
134
|
Content-Disposition: form-data; name="#{parameter_name}"; filename="#{escape(uploaded_file.original_filename)}"\r
|
139
135
|
Content-Type: #{uploaded_file.content_type}\r
|
140
|
-
Content-Length: #{
|
136
|
+
Content-Length: #{uploaded_file.size}\r
|
141
137
|
\r
|
142
|
-
#{
|
138
|
+
#{uploaded_file.read}\r
|
143
139
|
EOF
|
144
|
-
end
|
145
140
|
end
|
146
|
-
|
141
|
+
module_function :build_file_part
|
147
142
|
end
|
148
|
-
|
149
143
|
end
|
150
144
|
end
|
data/lib/rack/test.rb
CHANGED
@@ -1,18 +1,17 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
1
|
+
require 'uri'
|
2
|
+
require 'rack'
|
3
|
+
require 'rack/mock_session'
|
4
|
+
require 'rack/test/cookie_jar'
|
5
|
+
require 'rack/test/mock_digest_request'
|
6
|
+
require 'rack/test/utils'
|
7
|
+
require 'rack/test/methods'
|
8
|
+
require 'rack/test/uploaded_file'
|
9
|
+
require 'rack/test/version'
|
9
10
|
|
10
11
|
module Rack
|
11
12
|
module Test
|
12
|
-
|
13
|
-
|
14
|
-
DEFAULT_HOST = "example.org"
|
15
|
-
MULTIPART_BOUNDARY = "----------XnJLe9ZIbbGUYtzPQJ16u1"
|
13
|
+
DEFAULT_HOST = 'example.org'.freeze
|
14
|
+
MULTIPART_BOUNDARY = '----------XnJLe9ZIbbGUYtzPQJ16u1'.freeze
|
16
15
|
|
17
16
|
# The common base class for exceptions raised by Rack::Test
|
18
17
|
class Error < StandardError; end
|
@@ -36,11 +35,13 @@ module Rack
|
|
36
35
|
def initialize(mock_session)
|
37
36
|
@headers = {}
|
38
37
|
@env = {}
|
38
|
+
@digest_username = nil
|
39
|
+
@digest_password = nil
|
39
40
|
|
40
|
-
if mock_session.is_a?(MockSession)
|
41
|
-
|
41
|
+
@rack_mock_session = if mock_session.is_a?(MockSession)
|
42
|
+
mock_session
|
42
43
|
else
|
43
|
-
|
44
|
+
MockSession.new(mock_session)
|
44
45
|
end
|
45
46
|
|
46
47
|
@default_host = @rack_mock_session.default_host
|
@@ -54,8 +55,7 @@ module Rack
|
|
54
55
|
# Example:
|
55
56
|
# get "/"
|
56
57
|
def get(uri, params = {}, env = {}, &block)
|
57
|
-
|
58
|
-
process_request(uri, env, &block)
|
58
|
+
custom_request('GET', uri, params, env, &block)
|
59
59
|
end
|
60
60
|
|
61
61
|
# Issue a POST request for the given URI. See #get
|
@@ -63,8 +63,7 @@ module Rack
|
|
63
63
|
# Example:
|
64
64
|
# post "/signup", "name" => "Bryan"
|
65
65
|
def post(uri, params = {}, env = {}, &block)
|
66
|
-
|
67
|
-
process_request(uri, env, &block)
|
66
|
+
custom_request('POST', uri, params, env, &block)
|
68
67
|
end
|
69
68
|
|
70
69
|
# Issue a PUT request for the given URI. See #get
|
@@ -72,8 +71,7 @@ module Rack
|
|
72
71
|
# Example:
|
73
72
|
# put "/"
|
74
73
|
def put(uri, params = {}, env = {}, &block)
|
75
|
-
|
76
|
-
process_request(uri, env, &block)
|
74
|
+
custom_request('PUT', uri, params, env, &block)
|
77
75
|
end
|
78
76
|
|
79
77
|
# Issue a PATCH request for the given URI. See #get
|
@@ -81,8 +79,7 @@ module Rack
|
|
81
79
|
# Example:
|
82
80
|
# patch "/"
|
83
81
|
def patch(uri, params = {}, env = {}, &block)
|
84
|
-
|
85
|
-
process_request(uri, env, &block)
|
82
|
+
custom_request('PATCH', uri, params, env, &block)
|
86
83
|
end
|
87
84
|
|
88
85
|
# Issue a DELETE request for the given URI. See #get
|
@@ -90,8 +87,7 @@ module Rack
|
|
90
87
|
# Example:
|
91
88
|
# delete "/"
|
92
89
|
def delete(uri, params = {}, env = {}, &block)
|
93
|
-
|
94
|
-
process_request(uri, env, &block)
|
90
|
+
custom_request('DELETE', uri, params, env, &block)
|
95
91
|
end
|
96
92
|
|
97
93
|
# Issue an OPTIONS request for the given URI. See #get
|
@@ -99,8 +95,7 @@ module Rack
|
|
99
95
|
# Example:
|
100
96
|
# options "/"
|
101
97
|
def options(uri, params = {}, env = {}, &block)
|
102
|
-
|
103
|
-
process_request(uri, env, &block)
|
98
|
+
custom_request('OPTIONS', uri, params, env, &block)
|
104
99
|
end
|
105
100
|
|
106
101
|
# Issue a HEAD request for the given URI. See #get
|
@@ -108,8 +103,7 @@ module Rack
|
|
108
103
|
# Example:
|
109
104
|
# head "/"
|
110
105
|
def head(uri, params = {}, env = {}, &block)
|
111
|
-
|
112
|
-
process_request(uri, env, &block)
|
106
|
+
custom_request('HEAD', uri, params, env, &block)
|
113
107
|
end
|
114
108
|
|
115
109
|
# Issue a request to the Rack app for the given URI and optional Rack
|
@@ -120,10 +114,21 @@ module Rack
|
|
120
114
|
# Example:
|
121
115
|
# request "/"
|
122
116
|
def request(uri, env = {}, &block)
|
117
|
+
uri = parse_uri(uri, env)
|
123
118
|
env = env_for(uri, env)
|
124
119
|
process_request(uri, env, &block)
|
125
120
|
end
|
126
121
|
|
122
|
+
# Issue a request using the given verb for the given URI. See #get
|
123
|
+
#
|
124
|
+
# Example:
|
125
|
+
# custom_request "LINK", "/"
|
126
|
+
def custom_request(verb, uri, params = {}, env = {}, &block)
|
127
|
+
uri = parse_uri(uri, env)
|
128
|
+
env = env_for(uri, env.merge(method: verb.to_s.upcase, params: params))
|
129
|
+
process_request(uri, env, &block)
|
130
|
+
end
|
131
|
+
|
127
132
|
# Set a header to be included on all subsequent requests through the
|
128
133
|
# session. Use a value of nil to remove a previously configured header.
|
129
134
|
#
|
@@ -159,11 +164,11 @@ module Rack
|
|
159
164
|
# Example:
|
160
165
|
# basic_authorize "bryan", "secret"
|
161
166
|
def basic_authorize(username, password)
|
162
|
-
encoded_login = ["#{username}:#{password}"].pack(
|
167
|
+
encoded_login = ["#{username}:#{password}"].pack('m0')
|
163
168
|
header('Authorization', "Basic #{encoded_login}")
|
164
169
|
end
|
165
170
|
|
166
|
-
|
171
|
+
alias authorize basic_authorize
|
167
172
|
|
168
173
|
# Set the username and password for HTTP Digest authorization, to be
|
169
174
|
# included in subsequent requests in the HTTP_AUTHORIZATION header.
|
@@ -181,73 +186,73 @@ module Rack
|
|
181
186
|
# a redirect, an error will be raised.
|
182
187
|
def follow_redirect!
|
183
188
|
unless last_response.redirect?
|
184
|
-
raise Error
|
189
|
+
raise Error, 'Last response was not a redirect. Cannot follow_redirect!'
|
190
|
+
end
|
191
|
+
if last_response.status == 307
|
192
|
+
send(last_request.request_method.downcase.to_sym, last_response['Location'], last_request.params, 'HTTP_REFERER' => last_request.url)
|
193
|
+
else
|
194
|
+
get(last_response['Location'], {}, 'HTTP_REFERER' => last_request.url)
|
185
195
|
end
|
186
|
-
|
187
|
-
get(last_response["Location"], {}, { "HTTP_REFERER" => last_request.url })
|
188
196
|
end
|
189
197
|
|
190
|
-
|
198
|
+
private
|
191
199
|
|
192
|
-
def
|
193
|
-
|
194
|
-
|
195
|
-
|
200
|
+
def parse_uri(path, env)
|
201
|
+
URI.parse(path).tap do |uri|
|
202
|
+
uri.path = "/#{uri.path}" unless uri.path[0] == '/'
|
203
|
+
uri.host ||= @default_host
|
204
|
+
uri.scheme ||= 'https' if env['HTTPS'] == 'on'
|
205
|
+
end
|
206
|
+
end
|
196
207
|
|
208
|
+
def env_for(uri, env)
|
197
209
|
env = default_env.merge(env)
|
198
210
|
|
199
|
-
env[
|
211
|
+
env['HTTP_HOST'] ||= [uri.host, (uri.port if uri.port != uri.default_port)].compact.join(':')
|
200
212
|
|
201
|
-
env.update(
|
202
|
-
env[
|
213
|
+
env.update('HTTPS' => 'on') if URI::HTTPS === uri
|
214
|
+
env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' if env[:xhr]
|
203
215
|
|
204
216
|
# TODO: Remove this after Rack 1.1 has been released.
|
205
217
|
# Stringifying and upcasing methods has be commit upstream
|
206
|
-
env[
|
218
|
+
env['REQUEST_METHOD'] ||= env[:method] ? env[:method].to_s.upcase : 'GET'
|
219
|
+
|
220
|
+
params = env.delete(:params) do {} end
|
207
221
|
|
208
|
-
if env[
|
222
|
+
if env['REQUEST_METHOD'] == 'GET'
|
209
223
|
# merge :params with the query string
|
210
|
-
if params
|
224
|
+
if params
|
211
225
|
params = parse_nested_query(params) if params.is_a?(String)
|
212
|
-
|
213
|
-
uri.query = build_nested_query(params)
|
226
|
+
|
227
|
+
uri.query = [uri.query, build_nested_query(params)].compact.reject { |v| v == '' }.join('&')
|
214
228
|
end
|
215
|
-
elsif !env.
|
216
|
-
env[
|
229
|
+
elsif !env.key?(:input)
|
230
|
+
env['CONTENT_TYPE'] ||= 'application/x-www-form-urlencoded' unless params.nil?
|
217
231
|
|
218
|
-
if
|
219
|
-
if data = build_multipart(
|
232
|
+
if params.is_a?(Hash)
|
233
|
+
if data = build_multipart(params)
|
220
234
|
env[:input] = data
|
221
|
-
env[
|
222
|
-
env[
|
235
|
+
env['CONTENT_LENGTH'] ||= data.length.to_s
|
236
|
+
env['CONTENT_TYPE'] = "multipart/form-data; boundary=#{MULTIPART_BOUNDARY}"
|
223
237
|
else
|
224
|
-
env[:input] = params_to_string(
|
238
|
+
env[:input] = params_to_string(params)
|
225
239
|
end
|
226
240
|
else
|
227
|
-
env[:input] =
|
241
|
+
env[:input] = params
|
228
242
|
end
|
229
243
|
end
|
230
244
|
|
231
|
-
env.delete(:
|
232
|
-
|
233
|
-
if env.has_key?(:cookie)
|
234
|
-
set_cookie(env.delete(:cookie), uri)
|
235
|
-
end
|
245
|
+
set_cookie(env.delete(:cookie), uri) if env.key?(:cookie)
|
236
246
|
|
237
247
|
Rack::MockRequest.env_for(uri.to_s, env)
|
238
248
|
end
|
239
249
|
|
240
250
|
def process_request(uri, env)
|
241
|
-
uri = URI.parse(uri)
|
242
|
-
uri.host ||= @default_host
|
243
|
-
|
244
251
|
@rack_mock_session.request(uri, env)
|
245
252
|
|
246
253
|
if retry_with_digest_auth?(env)
|
247
|
-
auth_env = env.merge(
|
248
|
-
|
249
|
-
"rack-test.digest_auth_retry" => true
|
250
|
-
})
|
254
|
+
auth_env = env.merge('HTTP_AUTHORIZATION' => digest_auth_header,
|
255
|
+
'rack-test.digest_auth_retry' => true)
|
251
256
|
auth_env.delete('rack.request')
|
252
257
|
process_request(uri.path, auth_env)
|
253
258
|
else
|
@@ -258,26 +263,24 @@ module Rack
|
|
258
263
|
end
|
259
264
|
|
260
265
|
def digest_auth_header
|
261
|
-
challenge = last_response[
|
266
|
+
challenge = last_response['WWW-Authenticate'].split(' ', 2).last
|
262
267
|
params = Rack::Auth::Digest::Params.parse(challenge)
|
263
268
|
|
264
|
-
params.merge!(
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
"method" => last_request.env["REQUEST_METHOD"],
|
270
|
-
})
|
269
|
+
params.merge!('username' => @digest_username,
|
270
|
+
'nc' => '00000001',
|
271
|
+
'cnonce' => 'nonsensenonce',
|
272
|
+
'uri' => last_request.fullpath,
|
273
|
+
'method' => last_request.env['REQUEST_METHOD'])
|
271
274
|
|
272
|
-
params[
|
275
|
+
params['response'] = MockDigestRequest.new(params).response(@digest_password)
|
273
276
|
|
274
277
|
"Digest #{params}"
|
275
278
|
end
|
276
279
|
|
277
280
|
def retry_with_digest_auth?(env)
|
278
281
|
last_response.status == 401 &&
|
279
|
-
|
280
|
-
|
282
|
+
digest_auth_configured? &&
|
283
|
+
!env['rack-test.digest_auth_retry']
|
281
284
|
end
|
282
285
|
|
283
286
|
def digest_auth_configured?
|
@@ -285,15 +288,15 @@ module Rack
|
|
285
288
|
end
|
286
289
|
|
287
290
|
def default_env
|
288
|
-
{
|
291
|
+
{ 'rack.test' => true, 'REMOTE_ADDR' => '127.0.0.1' }.merge(@env).merge(headers_for_env)
|
289
292
|
end
|
290
293
|
|
291
294
|
def headers_for_env
|
292
295
|
converted_headers = {}
|
293
296
|
|
294
297
|
@headers.each do |name, value|
|
295
|
-
env_key = name.upcase.
|
296
|
-
env_key =
|
298
|
+
env_key = name.upcase.tr('-', '_')
|
299
|
+
env_key = 'HTTP_' + env_key unless env_key == 'CONTENT_TYPE'
|
297
300
|
converted_headers[env_key] = value
|
298
301
|
end
|
299
302
|
|
@@ -303,16 +306,14 @@ module Rack
|
|
303
306
|
def params_to_string(params)
|
304
307
|
case params
|
305
308
|
when Hash then build_nested_query(params)
|
306
|
-
when nil then
|
309
|
+
when nil then ''
|
307
310
|
else params
|
308
311
|
end
|
309
312
|
end
|
310
|
-
|
311
313
|
end
|
312
314
|
|
313
315
|
def self.encoding_aware_strings?
|
314
|
-
defined?(Encoding) &&
|
316
|
+
defined?(Encoding) && ''.respond_to?(:encode)
|
315
317
|
end
|
316
|
-
|
317
318
|
end
|
318
319
|
end
|