rack 2.2.9 → 3.0.0.beta1
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 +138 -101
- data/CONTRIBUTING.md +53 -47
- data/MIT-LICENSE +1 -1
- data/README.md +287 -0
- data/Rakefile +40 -7
- data/SPEC.rdoc +166 -125
- data/contrib/LICENSE.md +7 -0
- data/contrib/logo.webp +0 -0
- data/lib/rack/auth/abstract/handler.rb +3 -1
- data/lib/rack/auth/abstract/request.rb +3 -1
- data/lib/rack/auth/digest/md5.rb +1 -131
- data/lib/rack/auth/digest/nonce.rb +1 -54
- data/lib/rack/auth/digest/params.rb +1 -54
- data/lib/rack/auth/digest/request.rb +1 -43
- data/lib/rack/auth/digest.rb +256 -0
- data/lib/rack/body_proxy.rb +3 -1
- data/lib/rack/builder.rb +60 -42
- data/lib/rack/cascade.rb +2 -0
- data/lib/rack/chunked.rb +16 -13
- data/lib/rack/common_logger.rb +23 -18
- data/lib/rack/conditional_get.rb +18 -15
- data/lib/rack/constants.rb +62 -0
- data/lib/rack/content_length.rb +12 -16
- data/lib/rack/content_type.rb +8 -5
- data/lib/rack/deflater.rb +40 -26
- data/lib/rack/directory.rb +9 -3
- data/lib/rack/etag.rb +14 -23
- data/lib/rack/events.rb +4 -0
- data/lib/rack/file.rb +2 -0
- data/lib/rack/files.rb +15 -17
- data/lib/rack/head.rb +9 -8
- data/lib/rack/headers.rb +154 -0
- data/lib/rack/lint.rb +740 -649
- data/lib/rack/lock.rb +2 -5
- data/lib/rack/logger.rb +2 -0
- data/lib/rack/media_type.rb +4 -9
- data/lib/rack/method_override.rb +5 -1
- data/lib/rack/mime.rb +8 -0
- data/lib/rack/mock.rb +1 -271
- data/lib/rack/mock_request.rb +166 -0
- data/lib/rack/mock_response.rb +124 -0
- data/lib/rack/multipart/generator.rb +7 -5
- data/lib/rack/multipart/parser.rb +123 -85
- data/lib/rack/multipart/uploaded_file.rb +4 -0
- data/lib/rack/multipart.rb +20 -40
- data/lib/rack/null_logger.rb +9 -0
- data/lib/rack/query_parser.rb +76 -44
- data/lib/rack/recursive.rb +2 -0
- data/lib/rack/reloader.rb +0 -2
- data/lib/rack/request.rb +189 -91
- data/lib/rack/response.rb +131 -61
- data/lib/rack/rewindable_input.rb +24 -5
- data/lib/rack/runtime.rb +7 -6
- data/lib/rack/sendfile.rb +30 -25
- data/lib/rack/show_exceptions.rb +15 -2
- data/lib/rack/show_status.rb +17 -7
- data/lib/rack/static.rb +8 -8
- data/lib/rack/tempfile_reaper.rb +15 -4
- data/lib/rack/urlmap.rb +4 -2
- data/lib/rack/utils.rb +210 -199
- data/lib/rack/version.rb +9 -4
- data/lib/rack.rb +5 -76
- data/rack.gemspec +6 -6
- metadata +19 -31
- data/README.rdoc +0 -320
- data/bin/rackup +0 -5
- data/contrib/rack.png +0 -0
- data/contrib/rack.svg +0 -150
- data/contrib/rack_logo.svg +0 -164
- data/lib/rack/core_ext/regexp.rb +0 -14
- data/lib/rack/handler/cgi.rb +0 -59
- data/lib/rack/handler/fastcgi.rb +0 -100
- data/lib/rack/handler/lsws.rb +0 -61
- data/lib/rack/handler/scgi.rb +0 -71
- data/lib/rack/handler/thin.rb +0 -36
- data/lib/rack/handler/webrick.rb +0 -129
- data/lib/rack/handler.rb +0 -104
- data/lib/rack/lobster.rb +0 -70
- data/lib/rack/server.rb +0 -466
- data/lib/rack/session/abstract/id.rb +0 -523
- data/lib/rack/session/cookie.rb +0 -204
- data/lib/rack/session/memcache.rb +0 -10
- data/lib/rack/session/pool.rb +0 -85
data/lib/rack/session/cookie.rb
DELETED
@@ -1,204 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'openssl'
|
4
|
-
require 'zlib'
|
5
|
-
require_relative 'abstract/id'
|
6
|
-
require 'json'
|
7
|
-
require 'base64'
|
8
|
-
require 'delegate'
|
9
|
-
|
10
|
-
module Rack
|
11
|
-
|
12
|
-
module Session
|
13
|
-
|
14
|
-
# Rack::Session::Cookie provides simple cookie based session management.
|
15
|
-
# By default, the session is a Ruby Hash stored as base64 encoded marshalled
|
16
|
-
# data set to :key (default: rack.session). The object that encodes the
|
17
|
-
# session data is configurable and must respond to +encode+ and +decode+.
|
18
|
-
# Both methods must take a string and return a string.
|
19
|
-
#
|
20
|
-
# When the secret key is set, cookie data is checked for data integrity.
|
21
|
-
# The old secret key is also accepted and allows graceful secret rotation.
|
22
|
-
#
|
23
|
-
# Example:
|
24
|
-
#
|
25
|
-
# use Rack::Session::Cookie, :key => 'rack.session',
|
26
|
-
# :domain => 'foo.com',
|
27
|
-
# :path => '/',
|
28
|
-
# :expire_after => 2592000,
|
29
|
-
# :secret => 'change_me',
|
30
|
-
# :old_secret => 'also_change_me'
|
31
|
-
#
|
32
|
-
# All parameters are optional.
|
33
|
-
#
|
34
|
-
# Example of a cookie with no encoding:
|
35
|
-
#
|
36
|
-
# Rack::Session::Cookie.new(application, {
|
37
|
-
# :coder => Rack::Session::Cookie::Identity.new
|
38
|
-
# })
|
39
|
-
#
|
40
|
-
# Example of a cookie with custom encoding:
|
41
|
-
#
|
42
|
-
# Rack::Session::Cookie.new(application, {
|
43
|
-
# :coder => Class.new {
|
44
|
-
# def encode(str); str.reverse; end
|
45
|
-
# def decode(str); str.reverse; end
|
46
|
-
# }.new
|
47
|
-
# })
|
48
|
-
#
|
49
|
-
|
50
|
-
class Cookie < Abstract::PersistedSecure
|
51
|
-
# Encode session cookies as Base64
|
52
|
-
class Base64
|
53
|
-
def encode(str)
|
54
|
-
::Base64.strict_encode64(str)
|
55
|
-
end
|
56
|
-
|
57
|
-
def decode(str)
|
58
|
-
::Base64.decode64(str)
|
59
|
-
end
|
60
|
-
|
61
|
-
# Encode session cookies as Marshaled Base64 data
|
62
|
-
class Marshal < Base64
|
63
|
-
def encode(str)
|
64
|
-
super(::Marshal.dump(str))
|
65
|
-
end
|
66
|
-
|
67
|
-
def decode(str)
|
68
|
-
return unless str
|
69
|
-
::Marshal.load(super(str)) rescue nil
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# N.B. Unlike other encoding methods, the contained objects must be a
|
74
|
-
# valid JSON composite type, either a Hash or an Array.
|
75
|
-
class JSON < Base64
|
76
|
-
def encode(obj)
|
77
|
-
super(::JSON.dump(obj))
|
78
|
-
end
|
79
|
-
|
80
|
-
def decode(str)
|
81
|
-
return unless str
|
82
|
-
::JSON.parse(super(str)) rescue nil
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
class ZipJSON < Base64
|
87
|
-
def encode(obj)
|
88
|
-
super(Zlib::Deflate.deflate(::JSON.dump(obj)))
|
89
|
-
end
|
90
|
-
|
91
|
-
def decode(str)
|
92
|
-
return unless str
|
93
|
-
::JSON.parse(Zlib::Inflate.inflate(super(str)))
|
94
|
-
rescue
|
95
|
-
nil
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
# Use no encoding for session cookies
|
101
|
-
class Identity
|
102
|
-
def encode(str); str; end
|
103
|
-
def decode(str); str; end
|
104
|
-
end
|
105
|
-
|
106
|
-
attr_reader :coder
|
107
|
-
|
108
|
-
def initialize(app, options = {})
|
109
|
-
@secrets = options.values_at(:secret, :old_secret).compact
|
110
|
-
@hmac = options.fetch(:hmac, OpenSSL::Digest::SHA1)
|
111
|
-
|
112
|
-
warn <<-MSG unless secure?(options)
|
113
|
-
SECURITY WARNING: No secret option provided to Rack::Session::Cookie.
|
114
|
-
This poses a security threat. It is strongly recommended that you
|
115
|
-
provide a secret to prevent exploits that may be possible from crafted
|
116
|
-
cookies. This will not be supported in future versions of Rack, and
|
117
|
-
future versions will even invalidate your existing user cookies.
|
118
|
-
|
119
|
-
Called from: #{caller[0]}.
|
120
|
-
MSG
|
121
|
-
@coder = options[:coder] ||= Base64::Marshal.new
|
122
|
-
super(app, options.merge!(cookie_only: true))
|
123
|
-
end
|
124
|
-
|
125
|
-
private
|
126
|
-
|
127
|
-
def find_session(req, sid)
|
128
|
-
data = unpacked_cookie_data(req)
|
129
|
-
data = persistent_session_id!(data)
|
130
|
-
[data["session_id"], data]
|
131
|
-
end
|
132
|
-
|
133
|
-
def extract_session_id(request)
|
134
|
-
unpacked_cookie_data(request)["session_id"]
|
135
|
-
end
|
136
|
-
|
137
|
-
def unpacked_cookie_data(request)
|
138
|
-
request.fetch_header(RACK_SESSION_UNPACKED_COOKIE_DATA) do |k|
|
139
|
-
session_data = request.cookies[@key]
|
140
|
-
|
141
|
-
if @secrets.size > 0 && session_data
|
142
|
-
session_data, _, digest = session_data.rpartition('--')
|
143
|
-
session_data = nil unless digest_match?(session_data, digest)
|
144
|
-
end
|
145
|
-
|
146
|
-
request.set_header(k, coder.decode(session_data) || {})
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
def persistent_session_id!(data, sid = nil)
|
151
|
-
data ||= {}
|
152
|
-
data["session_id"] ||= sid || generate_sid
|
153
|
-
data
|
154
|
-
end
|
155
|
-
|
156
|
-
class SessionId < DelegateClass(Session::SessionId)
|
157
|
-
attr_reader :cookie_value
|
158
|
-
|
159
|
-
def initialize(session_id, cookie_value)
|
160
|
-
super(session_id)
|
161
|
-
@cookie_value = cookie_value
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def write_session(req, session_id, session, options)
|
166
|
-
session = session.merge("session_id" => session_id)
|
167
|
-
session_data = coder.encode(session)
|
168
|
-
|
169
|
-
if @secrets.first
|
170
|
-
session_data << "--#{generate_hmac(session_data, @secrets.first)}"
|
171
|
-
end
|
172
|
-
|
173
|
-
if session_data.size > (4096 - @key.size)
|
174
|
-
req.get_header(RACK_ERRORS).puts("Warning! Rack::Session::Cookie data size exceeds 4K.")
|
175
|
-
nil
|
176
|
-
else
|
177
|
-
SessionId.new(session_id, session_data)
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
def delete_session(req, session_id, options)
|
182
|
-
# Nothing to do here, data is in the client
|
183
|
-
generate_sid unless options[:drop]
|
184
|
-
end
|
185
|
-
|
186
|
-
def digest_match?(data, digest)
|
187
|
-
return unless data && digest
|
188
|
-
@secrets.any? do |secret|
|
189
|
-
Rack::Utils.secure_compare(digest, generate_hmac(data, secret))
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
def generate_hmac(data, secret)
|
194
|
-
OpenSSL::HMAC.hexdigest(@hmac.new, secret, data)
|
195
|
-
end
|
196
|
-
|
197
|
-
def secure?(options)
|
198
|
-
@secrets.size >= 1 ||
|
199
|
-
(options[:coder] && options[:let_coder_handle_secure_encoding])
|
200
|
-
end
|
201
|
-
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
data/lib/rack/session/pool.rb
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# AUTHOR: blink <blinketje@gmail.com>; blink#ruby-lang@irc.freenode.net
|
4
|
-
# THANKS:
|
5
|
-
# apeiros, for session id generation, expiry setup, and threadiness
|
6
|
-
# sergio, threadiness and bugreps
|
7
|
-
|
8
|
-
require_relative 'abstract/id'
|
9
|
-
require 'thread'
|
10
|
-
|
11
|
-
module Rack
|
12
|
-
module Session
|
13
|
-
# Rack::Session::Pool provides simple cookie based session management.
|
14
|
-
# Session data is stored in a hash held by @pool.
|
15
|
-
# In the context of a multithreaded environment, sessions being
|
16
|
-
# committed to the pool is done in a merging manner.
|
17
|
-
#
|
18
|
-
# The :drop option is available in rack.session.options if you wish to
|
19
|
-
# explicitly remove the session from the session cache.
|
20
|
-
#
|
21
|
-
# Example:
|
22
|
-
# myapp = MyRackApp.new
|
23
|
-
# sessioned = Rack::Session::Pool.new(myapp,
|
24
|
-
# :domain => 'foo.com',
|
25
|
-
# :expire_after => 2592000
|
26
|
-
# )
|
27
|
-
# Rack::Handler::WEBrick.run sessioned
|
28
|
-
|
29
|
-
class Pool < Abstract::PersistedSecure
|
30
|
-
attr_reader :mutex, :pool
|
31
|
-
DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge drop: false
|
32
|
-
|
33
|
-
def initialize(app, options = {})
|
34
|
-
super
|
35
|
-
@pool = Hash.new
|
36
|
-
@mutex = Mutex.new
|
37
|
-
end
|
38
|
-
|
39
|
-
def generate_sid
|
40
|
-
loop do
|
41
|
-
sid = super
|
42
|
-
break sid unless @pool.key? sid.private_id
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def find_session(req, sid)
|
47
|
-
with_lock(req) do
|
48
|
-
unless sid and session = get_session_with_fallback(sid)
|
49
|
-
sid, session = generate_sid, {}
|
50
|
-
@pool.store sid.private_id, session
|
51
|
-
end
|
52
|
-
[sid, session]
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def write_session(req, session_id, new_session, options)
|
57
|
-
with_lock(req) do
|
58
|
-
@pool.store session_id.private_id, new_session
|
59
|
-
session_id
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def delete_session(req, session_id, options)
|
64
|
-
with_lock(req) do
|
65
|
-
@pool.delete(session_id.public_id)
|
66
|
-
@pool.delete(session_id.private_id)
|
67
|
-
generate_sid unless options[:drop]
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def with_lock(req)
|
72
|
-
@mutex.lock if req.multithread?
|
73
|
-
yield
|
74
|
-
ensure
|
75
|
-
@mutex.unlock if @mutex.locked?
|
76
|
-
end
|
77
|
-
|
78
|
-
private
|
79
|
-
|
80
|
-
def get_session_with_fallback(sid)
|
81
|
-
@pool[sid.private_id] || @pool[sid.public_id]
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|