rack 2.0.9 → 2.1.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rack might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +77 -0
- data/{COPYING → MIT-LICENSE} +4 -2
- data/README.rdoc +77 -117
- data/Rakefile +25 -18
- data/SPEC +3 -4
- data/bin/rackup +1 -0
- data/example/lobster.ru +2 -0
- data/example/protectedlobster.rb +3 -1
- data/example/protectedlobster.ru +2 -0
- data/lib/rack.rb +63 -60
- data/lib/rack/auth/abstract/handler.rb +3 -1
- data/lib/rack/auth/abstract/request.rb +2 -0
- data/lib/rack/auth/basic.rb +4 -1
- data/lib/rack/auth/digest/md5.rb +9 -7
- data/lib/rack/auth/digest/nonce.rb +6 -3
- data/lib/rack/auth/digest/params.rb +4 -2
- data/lib/rack/auth/digest/request.rb +2 -0
- data/lib/rack/body_proxy.rb +3 -6
- data/lib/rack/builder.rb +39 -15
- data/lib/rack/cascade.rb +6 -5
- data/lib/rack/chunked.rb +29 -6
- data/lib/rack/common_logger.rb +9 -8
- data/lib/rack/conditional_get.rb +3 -1
- data/lib/rack/config.rb +2 -0
- data/lib/rack/content_length.rb +3 -1
- data/lib/rack/content_type.rb +3 -1
- data/lib/rack/core_ext/regexp.rb +14 -0
- data/lib/rack/deflater.rb +32 -17
- data/lib/rack/directory.rb +19 -16
- data/lib/rack/etag.rb +3 -1
- data/lib/rack/events.rb +5 -3
- data/lib/rack/file.rb +4 -173
- data/lib/rack/files.rb +178 -0
- data/lib/rack/handler.rb +7 -2
- data/lib/rack/handler/cgi.rb +3 -1
- data/lib/rack/handler/fastcgi.rb +4 -2
- data/lib/rack/handler/lsws.rb +3 -1
- data/lib/rack/handler/scgi.rb +9 -6
- data/lib/rack/handler/thin.rb +3 -1
- data/lib/rack/handler/webrick.rb +4 -2
- data/lib/rack/head.rb +2 -0
- data/lib/rack/lint.rb +14 -11
- data/lib/rack/lobster.rb +7 -5
- data/lib/rack/lock.rb +2 -0
- data/lib/rack/logger.rb +2 -0
- data/lib/rack/media_type.rb +10 -5
- data/lib/rack/method_override.rb +4 -2
- data/lib/rack/mime.rb +9 -1
- data/lib/rack/mock.rb +74 -15
- data/lib/rack/multipart.rb +5 -3
- data/lib/rack/multipart/generator.rb +6 -7
- data/lib/rack/multipart/parser.rb +51 -45
- data/lib/rack/multipart/uploaded_file.rb +2 -0
- data/lib/rack/null_logger.rb +2 -0
- data/lib/rack/query_parser.rb +51 -25
- data/lib/rack/recursive.rb +7 -5
- data/lib/rack/reloader.rb +10 -4
- data/lib/rack/request.rb +79 -26
- data/lib/rack/response.rb +71 -31
- data/lib/rack/rewindable_input.rb +4 -2
- data/lib/rack/runtime.rb +4 -2
- data/lib/rack/sendfile.rb +15 -8
- data/lib/rack/server.rb +88 -18
- data/lib/rack/session/abstract/id.rb +30 -20
- data/lib/rack/session/cookie.rb +10 -9
- data/lib/rack/session/memcache.rb +4 -93
- data/lib/rack/session/pool.rb +4 -2
- data/lib/rack/show_exceptions.rb +15 -9
- data/lib/rack/show_status.rb +4 -2
- data/lib/rack/static.rb +15 -10
- data/lib/rack/tempfile_reaper.rb +2 -0
- data/lib/rack/urlmap.rb +11 -2
- data/lib/rack/utils.rb +59 -72
- data/rack.gemspec +17 -7
- metadata +33 -175
- data/HISTORY.md +0 -505
- data/test/builder/an_underscore_app.rb +0 -5
- data/test/builder/anything.rb +0 -5
- data/test/builder/comment.ru +0 -4
- data/test/builder/end.ru +0 -5
- data/test/builder/line.ru +0 -1
- data/test/builder/options.ru +0 -2
- data/test/cgi/assets/folder/test.js +0 -1
- data/test/cgi/assets/fonts/font.eot +0 -1
- data/test/cgi/assets/images/image.png +0 -1
- data/test/cgi/assets/index.html +0 -1
- data/test/cgi/assets/javascripts/app.js +0 -1
- data/test/cgi/assets/stylesheets/app.css +0 -1
- data/test/cgi/lighttpd.conf +0 -26
- data/test/cgi/rackup_stub.rb +0 -6
- data/test/cgi/sample_rackup.ru +0 -5
- data/test/cgi/test +0 -9
- data/test/cgi/test+directory/test+file +0 -1
- data/test/cgi/test.fcgi +0 -9
- data/test/cgi/test.gz +0 -0
- data/test/cgi/test.ru +0 -5
- data/test/gemloader.rb +0 -10
- data/test/helper.rb +0 -34
- data/test/multipart/bad_robots +0 -259
- data/test/multipart/binary +0 -0
- data/test/multipart/content_type_and_no_filename +0 -6
- data/test/multipart/empty +0 -10
- data/test/multipart/fail_16384_nofile +0 -814
- data/test/multipart/file1.txt +0 -1
- data/test/multipart/filename_and_modification_param +0 -7
- data/test/multipart/filename_and_no_name +0 -6
- data/test/multipart/filename_with_encoded_words +0 -7
- data/test/multipart/filename_with_escaped_quotes +0 -6
- data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
- data/test/multipart/filename_with_null_byte +0 -7
- data/test/multipart/filename_with_percent_escaped_quotes +0 -6
- data/test/multipart/filename_with_single_quote +0 -7
- data/test/multipart/filename_with_unescaped_percentages +0 -6
- data/test/multipart/filename_with_unescaped_percentages2 +0 -6
- data/test/multipart/filename_with_unescaped_percentages3 +0 -6
- data/test/multipart/filename_with_unescaped_quotes +0 -6
- data/test/multipart/ie +0 -6
- data/test/multipart/invalid_character +0 -6
- data/test/multipart/mixed_files +0 -21
- data/test/multipart/nested +0 -10
- data/test/multipart/none +0 -9
- data/test/multipart/quoted +0 -15
- data/test/multipart/rack-logo.png +0 -0
- data/test/multipart/semicolon +0 -6
- data/test/multipart/text +0 -15
- data/test/multipart/three_files_three_fields +0 -31
- data/test/multipart/unity3d_wwwform +0 -11
- data/test/multipart/webkit +0 -32
- data/test/rackup/config.ru +0 -31
- data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
- data/test/spec_auth_basic.rb +0 -89
- data/test/spec_auth_digest.rb +0 -260
- data/test/spec_body_proxy.rb +0 -85
- data/test/spec_builder.rb +0 -233
- data/test/spec_cascade.rb +0 -63
- data/test/spec_cgi.rb +0 -84
- data/test/spec_chunked.rb +0 -103
- data/test/spec_common_logger.rb +0 -95
- data/test/spec_conditional_get.rb +0 -103
- data/test/spec_config.rb +0 -23
- data/test/spec_content_length.rb +0 -86
- data/test/spec_content_type.rb +0 -46
- data/test/spec_deflater.rb +0 -375
- data/test/spec_directory.rb +0 -148
- data/test/spec_etag.rb +0 -108
- data/test/spec_events.rb +0 -133
- data/test/spec_fastcgi.rb +0 -85
- data/test/spec_file.rb +0 -264
- data/test/spec_handler.rb +0 -57
- data/test/spec_head.rb +0 -46
- data/test/spec_lint.rb +0 -515
- data/test/spec_lobster.rb +0 -59
- data/test/spec_lock.rb +0 -204
- data/test/spec_logger.rb +0 -24
- data/test/spec_media_type.rb +0 -42
- data/test/spec_method_override.rb +0 -110
- data/test/spec_mime.rb +0 -51
- data/test/spec_mock.rb +0 -359
- data/test/spec_multipart.rb +0 -722
- data/test/spec_null_logger.rb +0 -21
- data/test/spec_recursive.rb +0 -75
- data/test/spec_request.rb +0 -1407
- data/test/spec_response.rb +0 -528
- data/test/spec_rewindable_input.rb +0 -128
- data/test/spec_runtime.rb +0 -50
- data/test/spec_sendfile.rb +0 -125
- data/test/spec_server.rb +0 -193
- data/test/spec_session_abstract_id.rb +0 -31
- data/test/spec_session_abstract_session_hash.rb +0 -45
- data/test/spec_session_cookie.rb +0 -442
- data/test/spec_session_memcache.rb +0 -357
- data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
- data/test/spec_session_pool.rb +0 -247
- data/test/spec_show_exceptions.rb +0 -93
- data/test/spec_show_status.rb +0 -104
- data/test/spec_static.rb +0 -184
- data/test/spec_tempfile_reaper.rb +0 -64
- data/test/spec_thin.rb +0 -96
- data/test/spec_urlmap.rb +0 -237
- data/test/spec_utils.rb +0 -742
- data/test/spec_version.rb +0 -11
- data/test/spec_webrick.rb +0 -206
- data/test/static/another/index.html +0 -1
- data/test/static/foo.html +0 -1
- data/test/static/index.html +0 -1
- data/test/testrequest.rb +0 -78
- data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
- data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
data/lib/rack/handler/lsws.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'lsapi'
|
2
4
|
require 'rack/content_length'
|
3
5
|
require 'rack/rewindable_input'
|
@@ -5,7 +7,7 @@ require 'rack/rewindable_input'
|
|
5
7
|
module Rack
|
6
8
|
module Handler
|
7
9
|
class LSWS
|
8
|
-
def self.run(app, options=nil)
|
10
|
+
def self.run(app, options = nil)
|
9
11
|
while LSAPI.accept != nil
|
10
12
|
serve app
|
11
13
|
end
|
data/lib/rack/handler/scgi.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'scgi'
|
2
4
|
require 'stringio'
|
3
5
|
require 'rack/content_length'
|
@@ -8,12 +10,12 @@ module Rack
|
|
8
10
|
class SCGI < ::SCGI::Processor
|
9
11
|
attr_accessor :app
|
10
12
|
|
11
|
-
def self.run(app, options=nil)
|
13
|
+
def self.run(app, options = nil)
|
12
14
|
options[:Socket] = UNIXServer.new(options[:File]) if options[:File]
|
13
|
-
new(options.merge(:app
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
15
|
+
new(options.merge(app: app,
|
16
|
+
host: options[:Host],
|
17
|
+
port: options[:Port],
|
18
|
+
socket: options[:Socket])).listen
|
17
19
|
end
|
18
20
|
|
19
21
|
def self.valid_options
|
@@ -41,7 +43,8 @@ module Rack
|
|
41
43
|
env[QUERY_STRING] ||= ""
|
42
44
|
env[SCRIPT_NAME] = ""
|
43
45
|
|
44
|
-
rack_input = StringIO.new(input_body
|
46
|
+
rack_input = StringIO.new(input_body)
|
47
|
+
rack_input.set_encoding(Encoding::BINARY)
|
45
48
|
|
46
49
|
env.update(
|
47
50
|
RACK_VERSION => Rack::VERSION,
|
data/lib/rack/handler/thin.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "thin"
|
2
4
|
require "thin/server"
|
3
5
|
require "thin/logging"
|
@@ -8,7 +10,7 @@ require "rack/chunked"
|
|
8
10
|
module Rack
|
9
11
|
module Handler
|
10
12
|
class Thin
|
11
|
-
def self.run(app, options={})
|
13
|
+
def self.run(app, options = {})
|
12
14
|
environment = ENV['RACK_ENV'] || 'development'
|
13
15
|
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
14
16
|
|
data/lib/rack/handler/webrick.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'webrick'
|
2
4
|
require 'stringio'
|
3
5
|
require 'rack/content_length'
|
@@ -22,7 +24,7 @@ end
|
|
22
24
|
module Rack
|
23
25
|
module Handler
|
24
26
|
class WEBrick < ::WEBrick::HTTPServlet::AbstractServlet
|
25
|
-
def self.run(app, options={})
|
27
|
+
def self.run(app, options = {})
|
26
28
|
environment = ENV['RACK_ENV'] || 'development'
|
27
29
|
default_host = environment == 'development' ? 'localhost' : nil
|
28
30
|
|
@@ -79,7 +81,7 @@ module Rack
|
|
79
81
|
env[QUERY_STRING] ||= ""
|
80
82
|
unless env[PATH_INFO] == ""
|
81
83
|
path, n = req.request_uri.path, env[SCRIPT_NAME].length
|
82
|
-
env[PATH_INFO] = path[n, path.length-n]
|
84
|
+
env[PATH_INFO] = path[n, path.length - n]
|
83
85
|
end
|
84
86
|
env[REQUEST_PATH] ||= [env[SCRIPT_NAME], env[PATH_INFO]].join
|
85
87
|
|
data/lib/rack/head.rb
CHANGED
data/lib/rack/lint.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rack/utils'
|
2
4
|
require 'forwardable'
|
3
5
|
|
@@ -33,7 +35,7 @@ module Rack
|
|
33
35
|
|
34
36
|
## A Rack application is a Ruby object (not a class) that
|
35
37
|
## responds to +call+.
|
36
|
-
def call(env=nil)
|
38
|
+
def call(env = nil)
|
37
39
|
dup._call(env)
|
38
40
|
end
|
39
41
|
|
@@ -123,9 +125,8 @@ module Rack
|
|
123
125
|
## the presence or absence of the
|
124
126
|
## appropriate HTTP header in the
|
125
127
|
## request. See
|
126
|
-
##
|
127
|
-
##
|
128
|
-
## specific behavior.
|
128
|
+
## {RFC3875 section 4.1.18}[https://tools.ietf.org/html/rfc3875#section-4.1.18]
|
129
|
+
## for specific behavior.
|
129
130
|
|
130
131
|
## In addition to this, the Rack environment must include these
|
131
132
|
## Rack-specific variables:
|
@@ -263,7 +264,7 @@ module Rack
|
|
263
264
|
## <tt>HTTP_CONTENT_TYPE</tt> or <tt>HTTP_CONTENT_LENGTH</tt>
|
264
265
|
## (use the versions without <tt>HTTP_</tt>).
|
265
266
|
%w[HTTP_CONTENT_TYPE HTTP_CONTENT_LENGTH].each { |header|
|
266
|
-
assert("env contains #{header}, must use #{header[5
|
267
|
+
assert("env contains #{header}, must use #{header[5, -1]}") {
|
267
268
|
not env.include? header
|
268
269
|
}
|
269
270
|
}
|
@@ -626,15 +627,17 @@ module Rack
|
|
626
627
|
assert("headers object should respond to #each, but doesn't (got #{header.class} as headers)") {
|
627
628
|
header.respond_to? :each
|
628
629
|
}
|
629
|
-
header.each { |key, value|
|
630
|
-
## Special headers starting "rack." are for communicating with the
|
631
|
-
## server, and must not be sent back to the client.
|
632
|
-
next if key =~ /^rack\..+$/
|
633
630
|
|
631
|
+
header.each { |key, value|
|
634
632
|
## The header keys must be Strings.
|
635
633
|
assert("header key must be a string, was #{key.class}") {
|
636
634
|
key.kind_of? String
|
637
635
|
}
|
636
|
+
|
637
|
+
## Special headers starting "rack." are for communicating with the
|
638
|
+
## server, and must not be sent back to the client.
|
639
|
+
next if key =~ /^rack\..+$/
|
640
|
+
|
638
641
|
## The header must not contain a +Status+ key.
|
639
642
|
assert("header must not contain Status") { key.downcase != "status" }
|
640
643
|
## The header must conform to RFC7230 token specification, i.e. cannot
|
@@ -662,7 +665,7 @@ module Rack
|
|
662
665
|
## 204 or 304.
|
663
666
|
if key.downcase == "content-type"
|
664
667
|
assert("Content-Type header found in #{status} response, not allowed") {
|
665
|
-
not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.
|
668
|
+
not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.key? status.to_i
|
666
669
|
}
|
667
670
|
return
|
668
671
|
end
|
@@ -676,7 +679,7 @@ module Rack
|
|
676
679
|
## There must not be a <tt>Content-Length</tt> header when the
|
677
680
|
## +Status+ is 1xx, 204 or 304.
|
678
681
|
assert("Content-Length header found in #{status} response, not allowed") {
|
679
|
-
not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.
|
682
|
+
not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.key? status.to_i
|
680
683
|
}
|
681
684
|
@content_length = value
|
682
685
|
end
|
data/lib/rack/lobster.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'zlib'
|
2
4
|
|
3
5
|
require 'rack/request'
|
@@ -25,8 +27,8 @@ module Rack
|
|
25
27
|
content = ["<title>Lobstericious!</title>",
|
26
28
|
"<pre>", lobster, "</pre>",
|
27
29
|
"<a href='#{href}'>flip!</a>"]
|
28
|
-
length = content.inject(0) { |a,e| a+e.size }.to_s
|
29
|
-
[200, {CONTENT_TYPE => "text/html", CONTENT_LENGTH => length}, content]
|
30
|
+
length = content.inject(0) { |a, e| a + e.size }.to_s
|
31
|
+
[200, { CONTENT_TYPE => "text/html", CONTENT_LENGTH => length }, content]
|
30
32
|
}
|
31
33
|
|
32
34
|
def call(env)
|
@@ -37,8 +39,8 @@ module Rack
|
|
37
39
|
gsub('\\', 'TEMP').
|
38
40
|
gsub('/', '\\').
|
39
41
|
gsub('TEMP', '/').
|
40
|
-
gsub('{','}').
|
41
|
-
gsub('(',')')
|
42
|
+
gsub('{', '}').
|
43
|
+
gsub('(', ')')
|
42
44
|
end.join("\n")
|
43
45
|
href = "?flip=right"
|
44
46
|
elsif req.GET["flip"] == "crash"
|
@@ -65,6 +67,6 @@ if $0 == __FILE__
|
|
65
67
|
require 'rack'
|
66
68
|
require 'rack/show_exceptions'
|
67
69
|
Rack::Server.start(
|
68
|
-
:
|
70
|
+
app: Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), Port: 9292
|
69
71
|
)
|
70
72
|
end
|
data/lib/rack/lock.rb
CHANGED
data/lib/rack/logger.rb
CHANGED
data/lib/rack/media_type.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rack
|
2
4
|
# Rack::MediaType parse media type and parameters out of content_type string
|
3
5
|
|
@@ -13,7 +15,7 @@ module Rack
|
|
13
15
|
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
|
14
16
|
def type(content_type)
|
15
17
|
return nil unless content_type
|
16
|
-
content_type.split(SPLIT_PATTERN, 2).first.downcase
|
18
|
+
content_type.split(SPLIT_PATTERN, 2).first.tap &:downcase!
|
17
19
|
end
|
18
20
|
|
19
21
|
# The media type parameters provided in CONTENT_TYPE as a Hash, or
|
@@ -23,15 +25,18 @@ module Rack
|
|
23
25
|
# { 'charset' => 'utf-8' }
|
24
26
|
def params(content_type)
|
25
27
|
return {} if content_type.nil?
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
|
29
|
+
content_type.split(SPLIT_PATTERN)[1..-1].each_with_object({}) do |s, hsh|
|
30
|
+
k, v = s.split('=', 2)
|
31
|
+
|
32
|
+
hsh[k.tap(&:downcase!)] = strip_doublequotes(v)
|
33
|
+
end
|
29
34
|
end
|
30
35
|
|
31
36
|
private
|
32
37
|
|
33
38
|
def strip_doublequotes(str)
|
34
|
-
(str
|
39
|
+
(str.start_with?('"') && str.end_with?('"')) ? str[1..-2] : str
|
35
40
|
end
|
36
41
|
end
|
37
42
|
end
|
data/lib/rack/method_override.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rack
|
2
4
|
class MethodOverride
|
3
5
|
HTTP_METHODS = %w[GET HEAD PUT POST DELETE OPTIONS PATCH LINK UNLINK]
|
4
6
|
|
5
|
-
METHOD_OVERRIDE_PARAM_KEY = "_method"
|
6
|
-
HTTP_METHOD_OVERRIDE_HEADER = "HTTP_X_HTTP_METHOD_OVERRIDE"
|
7
|
+
METHOD_OVERRIDE_PARAM_KEY = "_method"
|
8
|
+
HTTP_METHOD_OVERRIDE_HEADER = "HTTP_X_HTTP_METHOD_OVERRIDE"
|
7
9
|
ALLOWED_METHODS = %w[POST]
|
8
10
|
|
9
11
|
def initialize(app)
|
data/lib/rack/mime.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rack
|
2
4
|
module Mime
|
3
5
|
# Returns String with mime type if found, otherwise use +fallback+.
|
@@ -13,7 +15,7 @@ module Rack
|
|
13
15
|
# This is a shortcut for:
|
14
16
|
# Rack::Mime::MIME_TYPES.fetch('.foo', 'application/octet-stream')
|
15
17
|
|
16
|
-
def mime_type(ext, fallback='application/octet-stream')
|
18
|
+
def mime_type(ext, fallback = 'application/octet-stream')
|
17
19
|
MIME_TYPES.fetch(ext.to_s.downcase, fallback)
|
18
20
|
end
|
19
21
|
module_function :mime_type
|
@@ -306,6 +308,7 @@ module Rack
|
|
306
308
|
".lvp" => "audio/vnd.lucent.voice",
|
307
309
|
".lwp" => "application/vnd.lotus-wordpro",
|
308
310
|
".m3u" => "audio/x-mpegurl",
|
311
|
+
".m3u8" => "application/x-mpegurl",
|
309
312
|
".m4a" => "audio/mp4a-latm",
|
310
313
|
".m4v" => "video/mp4",
|
311
314
|
".ma" => "application/mathematica",
|
@@ -343,6 +346,7 @@ module Rack
|
|
343
346
|
".mp4s" => "application/mp4",
|
344
347
|
".mp4v" => "video/mp4",
|
345
348
|
".mpc" => "application/vnd.mophun.certificate",
|
349
|
+
".mpd" => "application/dash+xml",
|
346
350
|
".mpeg" => "video/mpeg",
|
347
351
|
".mpg" => "video/mpeg",
|
348
352
|
".mpga" => "audio/mpeg",
|
@@ -542,6 +546,7 @@ module Rack
|
|
542
546
|
".spp" => "application/scvp-vp-response",
|
543
547
|
".spq" => "application/scvp-vp-request",
|
544
548
|
".src" => "application/x-wais-source",
|
549
|
+
".srt" => "text/srt",
|
545
550
|
".srx" => "application/sparql-results+xml",
|
546
551
|
".sse" => "application/vnd.kodak-descriptor",
|
547
552
|
".ssf" => "application/vnd.epson.ssf",
|
@@ -576,6 +581,7 @@ module Rack
|
|
576
581
|
".tr" => "text/troff",
|
577
582
|
".tra" => "application/vnd.trueapp",
|
578
583
|
".trm" => "application/x-msterminal",
|
584
|
+
".ts" => "video/mp2t",
|
579
585
|
".tsv" => "text/tab-separated-values",
|
580
586
|
".ttf" => "application/octet-stream",
|
581
587
|
".twd" => "application/vnd.simtech-mindmapper",
|
@@ -600,9 +606,11 @@ module Rack
|
|
600
606
|
".vrml" => "model/vrml",
|
601
607
|
".vsd" => "application/vnd.visio",
|
602
608
|
".vsf" => "application/vnd.vsf",
|
609
|
+
".vtt" => "text/vtt",
|
603
610
|
".vtu" => "model/vnd.vtu",
|
604
611
|
".vxml" => "application/voicexml+xml",
|
605
612
|
".war" => "application/java-archive",
|
613
|
+
".wasm" => "application/wasm",
|
606
614
|
".wav" => "audio/x-wav",
|
607
615
|
".wax" => "audio/x-ms-wax",
|
608
616
|
".wbmp" => "image/vnd.wap.wbmp",
|
data/lib/rack/mock.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'uri'
|
2
4
|
require 'stringio'
|
3
5
|
require 'rack'
|
4
6
|
require 'rack/lint'
|
5
7
|
require 'rack/utils'
|
6
8
|
require 'rack/response'
|
9
|
+
require 'cgi/cookie'
|
7
10
|
|
8
11
|
module Rack
|
9
12
|
# Rack::MockRequest helps testing your Rack application without
|
@@ -53,16 +56,16 @@ module Rack
|
|
53
56
|
@app = app
|
54
57
|
end
|
55
58
|
|
56
|
-
def get(uri, opts={}) request(GET, uri, opts) end
|
57
|
-
def post(uri, opts={}) request(POST, uri, opts) end
|
58
|
-
def put(uri, opts={}) request(PUT, uri, opts) end
|
59
|
-
def patch(uri, opts={}) request(PATCH, uri, opts) end
|
60
|
-
def delete(uri, opts={}) request(DELETE, uri, opts) end
|
61
|
-
def head(uri, opts={}) request(HEAD, uri, opts) end
|
62
|
-
def options(uri, opts={}) request(OPTIONS, uri, opts) end
|
59
|
+
def get(uri, opts = {}) request(GET, uri, opts) end
|
60
|
+
def post(uri, opts = {}) request(POST, uri, opts) end
|
61
|
+
def put(uri, opts = {}) request(PUT, uri, opts) end
|
62
|
+
def patch(uri, opts = {}) request(PATCH, uri, opts) end
|
63
|
+
def delete(uri, opts = {}) request(DELETE, uri, opts) end
|
64
|
+
def head(uri, opts = {}) request(HEAD, uri, opts) end
|
65
|
+
def options(uri, opts = {}) request(OPTIONS, uri, opts) end
|
63
66
|
|
64
|
-
def request(method=GET, uri="", opts={})
|
65
|
-
env = self.class.env_for(uri, opts.merge(:
|
67
|
+
def request(method = GET, uri = "", opts = {})
|
68
|
+
env = self.class.env_for(uri, opts.merge(method: method))
|
66
69
|
|
67
70
|
if opts[:lint]
|
68
71
|
app = Rack::Lint.new(@app)
|
@@ -71,7 +74,7 @@ module Rack
|
|
71
74
|
end
|
72
75
|
|
73
76
|
errors = env[RACK_ERRORS]
|
74
|
-
status, headers, body
|
77
|
+
status, headers, body = app.call(env)
|
75
78
|
MockResponse.new(status, headers, body, errors)
|
76
79
|
ensure
|
77
80
|
body.close if body.respond_to?(:close)
|
@@ -85,7 +88,7 @@ module Rack
|
|
85
88
|
end
|
86
89
|
|
87
90
|
# Return the Rack environment used for a request to +uri+.
|
88
|
-
def self.env_for(uri="", opts={})
|
91
|
+
def self.env_for(uri = "", opts = {})
|
89
92
|
uri = parse_uri_rfc2396(uri)
|
90
93
|
uri.path = "/#{uri.path}" unless uri.path[0] == ?/
|
91
94
|
|
@@ -139,7 +142,7 @@ module Rack
|
|
139
142
|
rack_input.set_encoding(Encoding::BINARY)
|
140
143
|
env[RACK_INPUT] = rack_input
|
141
144
|
|
142
|
-
env["CONTENT_LENGTH"] ||= env[RACK_INPUT].
|
145
|
+
env["CONTENT_LENGTH"] ||= env[RACK_INPUT].size.to_s if env[RACK_INPUT].respond_to?(:size)
|
143
146
|
|
144
147
|
opts.each { |field, value|
|
145
148
|
env[field] = value if String === field
|
@@ -155,16 +158,19 @@ module Rack
|
|
155
158
|
|
156
159
|
class MockResponse < Rack::Response
|
157
160
|
# Headers
|
158
|
-
attr_reader :original_headers
|
161
|
+
attr_reader :original_headers, :cookies
|
159
162
|
|
160
163
|
# Errors
|
161
164
|
attr_accessor :errors
|
162
165
|
|
163
|
-
def initialize(status, headers, body, errors=StringIO.new(""))
|
166
|
+
def initialize(status, headers, body, errors = StringIO.new(""))
|
164
167
|
@original_headers = headers
|
165
168
|
@errors = errors.string if errors.respond_to?(:string)
|
169
|
+
@cookies = parse_cookies_from_header
|
166
170
|
|
167
171
|
super(body, status, headers)
|
172
|
+
|
173
|
+
buffered_body!
|
168
174
|
end
|
169
175
|
|
170
176
|
def =~(other)
|
@@ -186,11 +192,64 @@ module Rack
|
|
186
192
|
# ...
|
187
193
|
# res.body.should == "foo!"
|
188
194
|
# end
|
189
|
-
|
195
|
+
buffer = String.new
|
196
|
+
|
197
|
+
super.each do |chunk|
|
198
|
+
buffer << chunk
|
199
|
+
end
|
200
|
+
|
201
|
+
return buffer
|
190
202
|
end
|
191
203
|
|
192
204
|
def empty?
|
193
205
|
[201, 204, 304].include? status
|
194
206
|
end
|
207
|
+
|
208
|
+
def cookie(name)
|
209
|
+
cookies.fetch(name, nil)
|
210
|
+
end
|
211
|
+
|
212
|
+
private
|
213
|
+
|
214
|
+
def parse_cookies_from_header
|
215
|
+
cookies = Hash.new
|
216
|
+
if original_headers.has_key? 'Set-Cookie'
|
217
|
+
set_cookie_header = original_headers.fetch('Set-Cookie')
|
218
|
+
set_cookie_header.split("\n").each do |cookie|
|
219
|
+
cookie_name, cookie_filling = cookie.split('=', 2)
|
220
|
+
cookie_attributes = identify_cookie_attributes cookie_filling
|
221
|
+
parsed_cookie = CGI::Cookie.new(
|
222
|
+
'name' => cookie_name.strip,
|
223
|
+
'value' => cookie_attributes.fetch('value'),
|
224
|
+
'path' => cookie_attributes.fetch('path', nil),
|
225
|
+
'domain' => cookie_attributes.fetch('domain', nil),
|
226
|
+
'expires' => cookie_attributes.fetch('expires', nil),
|
227
|
+
'secure' => cookie_attributes.fetch('secure', false)
|
228
|
+
)
|
229
|
+
cookies.store(cookie_name, parsed_cookie)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
cookies
|
233
|
+
end
|
234
|
+
|
235
|
+
def identify_cookie_attributes(cookie_filling)
|
236
|
+
cookie_bits = cookie_filling.split(';')
|
237
|
+
cookie_attributes = Hash.new
|
238
|
+
cookie_attributes.store('value', cookie_bits[0].strip)
|
239
|
+
cookie_bits.each do |bit|
|
240
|
+
if bit.include? '='
|
241
|
+
cookie_attribute, attribute_value = bit.split('=')
|
242
|
+
cookie_attributes.store(cookie_attribute.strip, attribute_value.strip)
|
243
|
+
if cookie_attribute.include? 'max-age'
|
244
|
+
cookie_attributes.store('expires', Time.now + attribute_value.strip.to_i)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
if bit.include? 'secure'
|
248
|
+
cookie_attributes.store('secure', true)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
cookie_attributes
|
252
|
+
end
|
253
|
+
|
195
254
|
end
|
196
255
|
end
|