rack 1.5.5 → 1.6.0.beta
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/KNOWN-ISSUES +14 -0
- data/README.rdoc +10 -6
- data/Rakefile +3 -4
- data/SPEC +59 -23
- data/lib/rack.rb +2 -1
- data/lib/rack/auth/abstract/request.rb +1 -1
- data/lib/rack/auth/basic.rb +1 -1
- data/lib/rack/auth/digest/md5.rb +1 -1
- data/lib/rack/backports/uri/common_18.rb +1 -1
- data/lib/rack/builder.rb +19 -4
- data/lib/rack/cascade.rb +2 -2
- data/lib/rack/chunked.rb +12 -1
- data/lib/rack/commonlogger.rb +13 -5
- data/lib/rack/conditionalget.rb +14 -2
- data/lib/rack/content_length.rb +5 -1
- data/lib/rack/deflater.rb +52 -13
- data/lib/rack/directory.rb +8 -2
- data/lib/rack/etag.rb +14 -6
- data/lib/rack/file.rb +10 -14
- data/lib/rack/handler.rb +2 -0
- data/lib/rack/handler/fastcgi.rb +4 -1
- data/lib/rack/handler/mongrel.rb +8 -2
- data/lib/rack/handler/scgi.rb +4 -1
- data/lib/rack/handler/thin.rb +8 -2
- data/lib/rack/handler/webrick.rb +46 -6
- data/lib/rack/head.rb +7 -2
- data/lib/rack/lint.rb +73 -25
- data/lib/rack/lobster.rb +8 -3
- data/lib/rack/methodoverride.rb +14 -3
- data/lib/rack/mime.rb +1 -15
- data/lib/rack/mock.rb +15 -7
- data/lib/rack/multipart.rb +2 -2
- data/lib/rack/multipart/parser.rb +107 -53
- data/lib/rack/multipart/uploaded_file.rb +2 -2
- data/lib/rack/nulllogger.rb +21 -2
- data/lib/rack/request.rb +38 -24
- data/lib/rack/response.rb +5 -0
- data/lib/rack/sendfile.rb +10 -5
- data/lib/rack/server.rb +45 -17
- data/lib/rack/session/abstract/id.rb +7 -6
- data/lib/rack/session/cookie.rb +17 -7
- data/lib/rack/session/memcache.rb +4 -4
- data/lib/rack/session/pool.rb +3 -6
- data/lib/rack/showexceptions.rb +20 -11
- data/lib/rack/showstatus.rb +1 -1
- data/lib/rack/static.rb +27 -30
- data/lib/rack/tempfile_reaper.rb +22 -0
- data/lib/rack/urlmap.rb +17 -3
- data/lib/rack/utils.rb +78 -47
- data/lib/rack/utils/okjson.rb +90 -91
- data/rack.gemspec +3 -3
- data/test/multipart/filename_and_no_name +6 -0
- data/test/multipart/invalid_character +6 -0
- data/test/spec_builder.rb +13 -4
- data/test/spec_chunked.rb +16 -0
- data/test/spec_commonlogger.rb +36 -0
- data/test/spec_content_length.rb +3 -1
- data/test/spec_deflater.rb +283 -148
- data/test/spec_etag.rb +11 -2
- data/test/spec_file.rb +11 -3
- data/test/spec_head.rb +2 -0
- data/test/spec_lobster.rb +1 -1
- data/test/spec_mock.rb +8 -0
- data/test/spec_multipart.rb +111 -49
- data/test/spec_request.rb +109 -25
- data/test/spec_response.rb +30 -0
- data/test/spec_server.rb +20 -5
- data/test/spec_session_cookie.rb +45 -2
- data/test/spec_session_memcache.rb +1 -1
- data/test/spec_showexceptions.rb +29 -36
- data/test/spec_showstatus.rb +19 -0
- data/test/spec_tempfile_reaper.rb +63 -0
- data/test/spec_urlmap.rb +23 -0
- data/test/spec_utils.rb +60 -10
- data/test/spec_webrick.rb +41 -0
- metadata +12 -9
- data/test/cgi/lighttpd.errors +0 -1
- data/test/multipart/three_files_three_fields +0 -31
@@ -11,7 +11,7 @@ module Rack
|
|
11
11
|
raise "#{path} file does not exist" unless ::File.exist?(path)
|
12
12
|
@content_type = content_type
|
13
13
|
@original_filename = ::File.basename(path)
|
14
|
-
@tempfile = Tempfile.new(@original_filename)
|
14
|
+
@tempfile = Tempfile.new([@original_filename, ::File.extname(path)])
|
15
15
|
@tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
|
16
16
|
@tempfile.binmode if binary
|
17
17
|
FileUtils.copy_file(path, @tempfile.path)
|
@@ -31,4 +31,4 @@ module Rack
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
34
|
-
end
|
34
|
+
end
|
data/lib/rack/nulllogger.rb
CHANGED
@@ -9,10 +9,29 @@ module Rack
|
|
9
9
|
@app.call(env)
|
10
10
|
end
|
11
11
|
|
12
|
-
def info(progname = nil, &block);
|
12
|
+
def info(progname = nil, &block); end
|
13
13
|
def debug(progname = nil, &block); end
|
14
|
-
def warn(progname = nil, &block);
|
14
|
+
def warn(progname = nil, &block); end
|
15
15
|
def error(progname = nil, &block); end
|
16
16
|
def fatal(progname = nil, &block); end
|
17
|
+
def unknown(progname = nil, &block); end
|
18
|
+
def info? ; end
|
19
|
+
def debug? ; end
|
20
|
+
def warn? ; end
|
21
|
+
def error? ; end
|
22
|
+
def fatal? ; end
|
23
|
+
def level ; end
|
24
|
+
def progname ; end
|
25
|
+
def datetime_format ; end
|
26
|
+
def formatter ; end
|
27
|
+
def sev_threshold ; end
|
28
|
+
def level=(level); end
|
29
|
+
def progname=(progname); end
|
30
|
+
def datetime_format=(datetime_format); end
|
31
|
+
def formatter=(formatter); end
|
32
|
+
def sev_threshold=(sev_threshold); end
|
33
|
+
def close ; end
|
34
|
+
def add(severity, message = nil, progname = nil, &block); end
|
35
|
+
def <<(msg); end
|
17
36
|
end
|
18
37
|
end
|
data/lib/rack/request.rb
CHANGED
@@ -8,10 +8,6 @@ module Rack
|
|
8
8
|
# req = Rack::Request.new(env)
|
9
9
|
# req.post?
|
10
10
|
# req.params["data"]
|
11
|
-
#
|
12
|
-
# The environment hash passed will store a reference to the Request object
|
13
|
-
# instantiated so that it will only instantiate if an instance of the Request
|
14
|
-
# object doesn't already exist.
|
15
11
|
|
16
12
|
class Request
|
17
13
|
# The environment of the request.
|
@@ -56,7 +52,7 @@ module Rack
|
|
56
52
|
return {} if content_type.nil?
|
57
53
|
Hash[*content_type.split(/\s*[;,]\s*/)[1..-1].
|
58
54
|
collect { |s| s.split('=', 2) }.
|
59
|
-
map { |k,v| [k.downcase, v] }.flatten]
|
55
|
+
map { |k,v| [k.downcase, strip_doublequotes(v)] }.flatten]
|
60
56
|
end
|
61
57
|
|
62
58
|
# The character set of the request body if a "charset" media type
|
@@ -101,7 +97,7 @@ module Rack
|
|
101
97
|
elsif @env.has_key?("HTTP_X_FORWARDED_HOST")
|
102
98
|
DEFAULT_PORTS[scheme]
|
103
99
|
elsif @env.has_key?("HTTP_X_FORWARDED_PROTO")
|
104
|
-
DEFAULT_PORTS[@env['HTTP_X_FORWARDED_PROTO']]
|
100
|
+
DEFAULT_PORTS[@env['HTTP_X_FORWARDED_PROTO'].split(',')[0]]
|
105
101
|
else
|
106
102
|
@env["SERVER_PORT"].to_i
|
107
103
|
end
|
@@ -109,7 +105,7 @@ module Rack
|
|
109
105
|
|
110
106
|
def host
|
111
107
|
# Remove port number.
|
112
|
-
host_with_port.to_s.
|
108
|
+
host_with_port.to_s.sub(/:\d+\z/, '')
|
113
109
|
end
|
114
110
|
|
115
111
|
def script_name=(s); @env["SCRIPT_NAME"] = s.to_s end
|
@@ -128,6 +124,9 @@ module Rack
|
|
128
124
|
# Checks the HTTP request method (or verb) to see if it was of type OPTIONS
|
129
125
|
def options?; request_method == "OPTIONS" end
|
130
126
|
|
127
|
+
# Checks the HTTP request method (or verb) to see if it was of type LINK
|
128
|
+
def link?; request_method == "LINK" end
|
129
|
+
|
131
130
|
# Checks the HTTP request method (or verb) to see if it was of type PATCH
|
132
131
|
def patch?; request_method == "PATCH" end
|
133
132
|
|
@@ -140,6 +139,9 @@ module Rack
|
|
140
139
|
# Checks the HTTP request method (or verb) to see if it was of type TRACE
|
141
140
|
def trace?; request_method == "TRACE" end
|
142
141
|
|
142
|
+
# Checks the HTTP request method (or verb) to see if it was of type UNLINK
|
143
|
+
def unlink?; request_method == "UNLINK" end
|
144
|
+
|
143
145
|
|
144
146
|
# The set of form-data media-types. Requests that do not indicate
|
145
147
|
# one of the media types presents in this list will not be eligible
|
@@ -186,8 +188,9 @@ module Rack
|
|
186
188
|
if @env["rack.request.query_string"] == query_string
|
187
189
|
@env["rack.request.query_hash"]
|
188
190
|
else
|
191
|
+
p = parse_query(query_string)
|
189
192
|
@env["rack.request.query_string"] = query_string
|
190
|
-
@env["rack.request.query_hash"] =
|
193
|
+
@env["rack.request.query_hash"] = p
|
191
194
|
end
|
192
195
|
end
|
193
196
|
|
@@ -201,7 +204,6 @@ module Rack
|
|
201
204
|
elsif @env["rack.request.form_input"].equal? @env["rack.input"]
|
202
205
|
@env["rack.request.form_hash"]
|
203
206
|
elsif form_data? || parseable_data?
|
204
|
-
@env["rack.request.form_input"] = @env["rack.input"]
|
205
207
|
unless @env["rack.request.form_hash"] = parse_multipart(env)
|
206
208
|
form_vars = @env["rack.input"].read
|
207
209
|
|
@@ -214,6 +216,7 @@ module Rack
|
|
214
216
|
|
215
217
|
@env["rack.input"].rewind
|
216
218
|
end
|
219
|
+
@env["rack.request.form_input"] = @env["rack.input"]
|
217
220
|
@env["rack.request.form_hash"]
|
218
221
|
else
|
219
222
|
{}
|
@@ -331,14 +334,11 @@ module Rack
|
|
331
334
|
end
|
332
335
|
|
333
336
|
def accept_encoding
|
334
|
-
@env["HTTP_ACCEPT_ENCODING"]
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
end
|
340
|
-
[encoding, quality]
|
341
|
-
end
|
337
|
+
parse_http_accept_header(@env["HTTP_ACCEPT_ENCODING"])
|
338
|
+
end
|
339
|
+
|
340
|
+
def accept_language
|
341
|
+
parse_http_accept_header(@env["HTTP_ACCEPT_LANGUAGE"])
|
342
342
|
end
|
343
343
|
|
344
344
|
def trusted_proxy?(ip)
|
@@ -353,12 +353,6 @@ module Rack
|
|
353
353
|
|
354
354
|
forwarded_ips = split_ip_addresses(@env['HTTP_X_FORWARDED_FOR'])
|
355
355
|
|
356
|
-
if client_ip = @env['HTTP_CLIENT_IP']
|
357
|
-
# If forwarded_ips doesn't include the client_ip, it might be an
|
358
|
-
# ip spoofing attempt, so we ignore HTTP_CLIENT_IP
|
359
|
-
return client_ip if forwarded_ips.include?(client_ip)
|
360
|
-
end
|
361
|
-
|
362
356
|
return reject_trusted_ip_addresses(forwarded_ips).last || @env["REMOTE_ADDR"]
|
363
357
|
end
|
364
358
|
|
@@ -372,11 +366,31 @@ module Rack
|
|
372
366
|
end
|
373
367
|
|
374
368
|
def parse_query(qs)
|
375
|
-
Utils.parse_nested_query(qs)
|
369
|
+
Utils.parse_nested_query(qs, '&')
|
376
370
|
end
|
377
371
|
|
378
372
|
def parse_multipart(env)
|
379
373
|
Rack::Multipart.parse_multipart(env)
|
380
374
|
end
|
375
|
+
|
376
|
+
def parse_http_accept_header(header)
|
377
|
+
header.to_s.split(/\s*,\s*/).map do |part|
|
378
|
+
attribute, parameters = part.split(/\s*;\s*/, 2)
|
379
|
+
quality = 1.0
|
380
|
+
if parameters and /\Aq=([\d.]+)/ =~ parameters
|
381
|
+
quality = $1.to_f
|
382
|
+
end
|
383
|
+
[attribute, quality]
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
private
|
388
|
+
def strip_doublequotes(s)
|
389
|
+
if s[0] == ?" && s[-1] == ?"
|
390
|
+
s[1..-2]
|
391
|
+
else
|
392
|
+
s
|
393
|
+
end
|
394
|
+
end
|
381
395
|
end
|
382
396
|
end
|
data/lib/rack/response.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rack/request'
|
2
2
|
require 'rack/utils'
|
3
|
+
require 'rack/body_proxy'
|
3
4
|
require 'time'
|
4
5
|
|
5
6
|
module Rack
|
@@ -121,10 +122,14 @@ module Rack
|
|
121
122
|
def server_error?; status >= 500 && status < 600; end
|
122
123
|
|
123
124
|
def ok?; status == 200; end
|
125
|
+
def created?; status == 201; end
|
126
|
+
def accepted?; status == 202; end
|
124
127
|
def bad_request?; status == 400; end
|
128
|
+
def unauthorized?; status == 401; end
|
125
129
|
def forbidden?; status == 403; end
|
126
130
|
def not_found?; status == 404; end
|
127
131
|
def method_not_allowed?; status == 405; end
|
132
|
+
def i_m_a_teapot?; status == 418; end
|
128
133
|
def unprocessable?; status == 422; end
|
129
134
|
|
130
135
|
def redirect?; [301, 302, 303, 307].include? status; end
|
data/lib/rack/sendfile.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rack/file'
|
2
|
+
require 'rack/body_proxy'
|
2
3
|
|
3
4
|
module Rack
|
4
5
|
|
@@ -22,7 +23,7 @@ module Rack
|
|
22
23
|
#
|
23
24
|
# Nginx supports the X-Accel-Redirect header. This is similar to X-Sendfile
|
24
25
|
# but requires parts of the filesystem to be mapped into a private URL
|
25
|
-
#
|
26
|
+
# hierarchy.
|
26
27
|
#
|
27
28
|
# The following example shows the Nginx configuration required to create
|
28
29
|
# a private "/files/" area, enable X-Accel-Redirect, and pass the special
|
@@ -117,8 +118,10 @@ module Rack
|
|
117
118
|
if url = map_accel_path(env, path)
|
118
119
|
headers['Content-Length'] = '0'
|
119
120
|
headers[type] = url
|
120
|
-
|
121
|
-
body = []
|
121
|
+
obody = body
|
122
|
+
body = Rack::BodyProxy.new([]) do
|
123
|
+
obody.close if obody.respond_to?(:close)
|
124
|
+
end
|
122
125
|
else
|
123
126
|
env['rack.errors'].puts "X-Accel-Mapping header missing"
|
124
127
|
end
|
@@ -126,8 +129,10 @@ module Rack
|
|
126
129
|
path = F.expand_path(body.to_path)
|
127
130
|
headers['Content-Length'] = '0'
|
128
131
|
headers[type] = path
|
129
|
-
|
130
|
-
body = []
|
132
|
+
obody = body
|
133
|
+
body = Rack::BodyProxy.new([]) do
|
134
|
+
obody.close if obody.respond_to?(:close)
|
135
|
+
end
|
131
136
|
when '', nil
|
132
137
|
else
|
133
138
|
env['rack.errors'].puts "Unknown x-sendfile variation: '#{type}'.\n"
|
data/lib/rack/server.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
require 'optparse'
|
2
2
|
|
3
|
+
|
3
4
|
module Rack
|
5
|
+
|
4
6
|
class Server
|
7
|
+
|
5
8
|
class Options
|
6
9
|
def parse!(args)
|
7
10
|
options = {}
|
@@ -27,6 +30,9 @@ module Rack
|
|
27
30
|
opts.on("-w", "--warn", "turn warnings on for your script") {
|
28
31
|
options[:warn] = true
|
29
32
|
}
|
33
|
+
opts.on("-q", "--quiet", "turn off logging") {
|
34
|
+
options[:quiet] = true
|
35
|
+
}
|
30
36
|
|
31
37
|
opts.on("-I", "--include PATH",
|
32
38
|
"specify $LOAD_PATH (may be used more than once)") { |path|
|
@@ -66,7 +72,7 @@ module Rack
|
|
66
72
|
options[:daemonize] = d ? true : false
|
67
73
|
}
|
68
74
|
|
69
|
-
opts.on("-P", "--pid FILE", "file to store PID
|
75
|
+
opts.on("-P", "--pid FILE", "file to store PID") { |f|
|
70
76
|
options[:pid] = ::File.expand_path(f)
|
71
77
|
}
|
72
78
|
|
@@ -166,7 +172,7 @@ module Rack
|
|
166
172
|
# * :Port
|
167
173
|
# the port to bind to (used by supporting Rack::Handler)
|
168
174
|
# * :AccessLog
|
169
|
-
# webrick
|
175
|
+
# webrick access log options (or supporting Rack::Handler)
|
170
176
|
# * :debug
|
171
177
|
# turn on debug output ($DEBUG = true)
|
172
178
|
# * :warn
|
@@ -185,11 +191,14 @@ module Rack
|
|
185
191
|
end
|
186
192
|
|
187
193
|
def default_options
|
194
|
+
environment = ENV['RACK_ENV'] || 'development'
|
195
|
+
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
196
|
+
|
188
197
|
{
|
189
|
-
:environment =>
|
198
|
+
:environment => environment,
|
190
199
|
:pid => nil,
|
191
200
|
:Port => 9292,
|
192
|
-
:Host =>
|
201
|
+
:Host => default_host,
|
193
202
|
:AccessLog => [],
|
194
203
|
:config => "config.ru"
|
195
204
|
}
|
@@ -199,29 +208,44 @@ module Rack
|
|
199
208
|
@app ||= options[:builder] ? build_app_from_string : build_app_and_options_from_config
|
200
209
|
end
|
201
210
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
211
|
+
class << self
|
212
|
+
def logging_middleware
|
213
|
+
lambda { |server|
|
214
|
+
server.server.name =~ /CGI/ || server.options[:quiet] ? nil : [Rack::CommonLogger, $stderr]
|
215
|
+
}
|
216
|
+
end
|
207
217
|
|
208
|
-
|
209
|
-
@middleware ||= begin
|
218
|
+
def default_middleware_by_environment
|
210
219
|
m = Hash.new {|h,k| h[k] = []}
|
211
|
-
m["deployment"]
|
220
|
+
m["deployment"] = [
|
212
221
|
[Rack::ContentLength],
|
213
222
|
[Rack::Chunked],
|
214
|
-
logging_middleware
|
223
|
+
logging_middleware,
|
224
|
+
[Rack::TempfileReaper]
|
215
225
|
]
|
216
|
-
m["development"]
|
226
|
+
m["development"] = [
|
227
|
+
[Rack::ContentLength],
|
228
|
+
[Rack::Chunked],
|
229
|
+
logging_middleware,
|
230
|
+
[Rack::ShowExceptions],
|
231
|
+
[Rack::Lint],
|
232
|
+
[Rack::TempfileReaper]
|
233
|
+
]
|
234
|
+
|
217
235
|
m
|
218
236
|
end
|
237
|
+
|
238
|
+
# Aliased for backwards-compatibility
|
239
|
+
alias :middleware :default_middleware_by_environment
|
219
240
|
end
|
220
241
|
|
221
|
-
def
|
222
|
-
self.class.
|
242
|
+
def default_middleware_by_environment
|
243
|
+
self.class.default_middleware_by_environment
|
223
244
|
end
|
224
245
|
|
246
|
+
# Aliased for backwards-compatibility
|
247
|
+
alias :middleware :default_middleware_by_environment
|
248
|
+
|
225
249
|
def start &blk
|
226
250
|
if options[:warn]
|
227
251
|
$-w = true
|
@@ -301,7 +325,8 @@ module Rack
|
|
301
325
|
end
|
302
326
|
|
303
327
|
def build_app(app)
|
304
|
-
|
328
|
+
middlewares = default_middleware_by_environment[options[:environment]]
|
329
|
+
middlewares.reverse_each do |middleware|
|
305
330
|
middleware = middleware.call(self) if middleware.respond_to?(:call)
|
306
331
|
next unless middleware
|
307
332
|
klass, *args = middleware
|
@@ -350,6 +375,8 @@ module Rack
|
|
350
375
|
return :exited unless ::File.exist?(options[:pid])
|
351
376
|
|
352
377
|
pid = ::File.read(options[:pid]).to_i
|
378
|
+
return :dead if pid == 0
|
379
|
+
|
353
380
|
Process.kill(0, pid)
|
354
381
|
:running
|
355
382
|
rescue Errno::ESRCH
|
@@ -359,4 +386,5 @@ module Rack
|
|
359
386
|
end
|
360
387
|
|
361
388
|
end
|
389
|
+
|
362
390
|
end
|
@@ -289,7 +289,7 @@ module Rack
|
|
289
289
|
value && !value.empty?
|
290
290
|
end
|
291
291
|
|
292
|
-
# Session should be
|
292
|
+
# Session should be committed if it was loaded, any of specific options like :renew, :drop
|
293
293
|
# or :expire_after was given and the security permissions match. Skips if skip is given.
|
294
294
|
|
295
295
|
def commit_session?(env, session, options)
|
@@ -310,7 +310,7 @@ module Rack
|
|
310
310
|
end
|
311
311
|
|
312
312
|
def force_options?(options)
|
313
|
-
options.values_at(:renew, :drop, :defer, :expire_after).any?
|
313
|
+
options.values_at(:max_age, :renew, :drop, :defer, :expire_after).any?
|
314
314
|
end
|
315
315
|
|
316
316
|
def security_matches?(env, options)
|
@@ -342,11 +342,12 @@ module Rack
|
|
342
342
|
if not data = set_session(env, session_id, session_data, options)
|
343
343
|
env["rack.errors"].puts("Warning! #{self.class.name} failed to save session. Content dropped.")
|
344
344
|
elsif options[:defer] and not options[:renew]
|
345
|
-
env["rack.errors"].puts("
|
345
|
+
env["rack.errors"].puts("Deferring cookie for #{session_id}") if $VERBOSE
|
346
346
|
else
|
347
347
|
cookie = Hash.new
|
348
348
|
cookie[:value] = data
|
349
349
|
cookie[:expires] = Time.now + options[:expire_after] if options[:expire_after]
|
350
|
+
cookie[:expires] = Time.now + options[:max_age] if options[:max_age]
|
350
351
|
set_cookie(env, headers, cookie.merge!(options))
|
351
352
|
end
|
352
353
|
|
@@ -369,7 +370,7 @@ module Rack
|
|
369
370
|
SessionHash
|
370
371
|
end
|
371
372
|
|
372
|
-
# All thread safety and session
|
373
|
+
# All thread safety and session retrieval procedures should occur here.
|
373
374
|
# Should return [session_id, session].
|
374
375
|
# If nil is provided as the session id, generation of a new valid id
|
375
376
|
# should occur within.
|
@@ -378,7 +379,7 @@ module Rack
|
|
378
379
|
raise '#get_session not implemented.'
|
379
380
|
end
|
380
381
|
|
381
|
-
# All thread safety and session storage
|
382
|
+
# All thread safety and session storage procedures should occur here.
|
382
383
|
# Must return the session id if the session was saved successfully, or
|
383
384
|
# false if the session could not be saved.
|
384
385
|
|
@@ -386,7 +387,7 @@ module Rack
|
|
386
387
|
raise '#set_session not implemented.'
|
387
388
|
end
|
388
389
|
|
389
|
-
# All thread safety and session destroy
|
390
|
+
# All thread safety and session destroy procedures should occur here.
|
390
391
|
# Should return a new session id or nil if options[:drop]
|
391
392
|
|
392
393
|
def destroy_session(env, sid, options)
|
data/lib/rack/session/cookie.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'openssl'
|
2
|
+
require 'zlib'
|
2
3
|
require 'rack/request'
|
3
4
|
require 'rack/response'
|
4
5
|
require 'rack/session/abstract/id'
|
@@ -78,6 +79,19 @@ module Rack
|
|
78
79
|
::Rack::Utils::OkJson.decode(super(str)) rescue nil
|
79
80
|
end
|
80
81
|
end
|
82
|
+
|
83
|
+
class ZipJSON < Base64
|
84
|
+
def encode(obj)
|
85
|
+
super(Zlib::Deflate.deflate(::Rack::Utils::OkJson.encode(obj)))
|
86
|
+
end
|
87
|
+
|
88
|
+
def decode(str)
|
89
|
+
return unless str
|
90
|
+
::Rack::Utils::OkJson.decode(Zlib::Inflate.inflate(super(str)))
|
91
|
+
rescue
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
end
|
81
95
|
end
|
82
96
|
|
83
97
|
# Use no encoding for session cookies
|
@@ -86,12 +100,6 @@ module Rack
|
|
86
100
|
def decode(str); str; end
|
87
101
|
end
|
88
102
|
|
89
|
-
# Reverse string encoding. (trollface)
|
90
|
-
class Reverse
|
91
|
-
def encode(str); str.reverse; end
|
92
|
-
def decode(str); str.reverse; end
|
93
|
-
end
|
94
|
-
|
95
103
|
attr_reader :coder
|
96
104
|
|
97
105
|
def initialize(app, options={})
|
@@ -127,7 +135,9 @@ module Rack
|
|
127
135
|
session_data = request.cookies[@key]
|
128
136
|
|
129
137
|
if @secrets.size > 0 && session_data
|
130
|
-
|
138
|
+
digest, session_data = session_data.reverse.split("--", 2)
|
139
|
+
digest.reverse! if digest
|
140
|
+
session_data.reverse! if session_data
|
131
141
|
session_data = nil unless digest_match?(session_data, digest)
|
132
142
|
end
|
133
143
|
|