rack-redic 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b908eba6dfd16a9c0288fc441f5034a71d90182b
4
- data.tar.gz: 3670a26907451fee9bfbe96b47563e4048fd0d69
3
+ metadata.gz: 0343dd0cb8b4c338b4ffb2f103969e6aa9681556
4
+ data.tar.gz: f8493e153c5f85648d55d5e99433351645e52cb7
5
5
  SHA512:
6
- metadata.gz: 171a60f038d7a62e9af3f5bcf577f89efe7db6a7ea1aaeb73a0de3025147818ed461a9fa2cffb6fff44622006fe90dbbc600d5140a004e668eea670a4006dc29
7
- data.tar.gz: 6e7ff29f664c03f3901dd869a9784837c0a815de439a0f966fc507f5f6ee9bdeb34a3aa2e39fb0189ea33762b5f7d322faf74d4202b38baf81d7c1b7658cd48b
6
+ metadata.gz: 5dbfc8659cc61a1610acb82c1306da982f1ca07bdc39295394743c928ee04d53b038f5454e892dc64eee93b49b605fa4f5005f304b550d855122533fdf893384
7
+ data.tar.gz: ad56f8b4d338f9b6a375309397ab28969a0c92485b159c064d1017816328b408365e38845a976ddf6a58afbad74571d6c3439e1abeaa7cf8f4ac50c6443703cd
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -30,14 +30,16 @@ module Rack
30
30
  class Redic < Abstract::Persisted
31
31
  REDIS_URL = 'REDIS_URL'.freeze
32
32
 
33
+ attr_reader :storage
34
+
33
35
  def initialize(app, options = {})
34
36
  super
35
37
 
36
38
  @mutex = Mutex.new
37
39
  @storage = Storage.new(
38
40
  options[:expire_after],
39
- options.fetch(:marshaller, Marshal),
40
- options.fetch(:url, ENV.fetch(REDIS_URL))
41
+ options.fetch(:marshaller) { Marshal },
42
+ options.fetch(:url) { ENV.fetch(REDIS_URL) }
41
43
  )
42
44
  end
43
45
 
@@ -52,8 +54,9 @@ module Rack
52
54
  # Find the session (or generate a blank one).
53
55
  def find_session(_req, sid)
54
56
  @mutex.synchronize do
55
- sid ||= generate_sid
56
- session = @storage.get(sid) || @storage.init(sid, {})
57
+ unless sid && session = @storage.get(sid)
58
+ sid, session = generate_sid, {}
59
+ end
57
60
 
58
61
  [sid, session]
59
62
  end
@@ -100,11 +103,6 @@ module Rack
100
103
  @storage.call(EXISTS, id) != ZERO
101
104
  end
102
105
 
103
- def init(sid, initial)
104
- set(sid, initial)
105
- initial
106
- end
107
-
108
106
  def get(id)
109
107
  deserialize(@storage.call(GET, id))
110
108
  end
data/rack-redic.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'rack-redic'
5
- spec.version = '0.5.0'
5
+ spec.version = '0.6.0'
6
6
  spec.authors = ['Evan Lecklider']
7
7
  spec.email = ['evan@lecklider.com']
8
8
 
@@ -11,7 +11,10 @@ Gem::Specification.new do |spec|
11
11
  spec.homepage = 'https://github.com/evanleck/rack-redic'
12
12
  spec.license = 'MIT'
13
13
  spec.files = `git ls-files`.split("\n")
14
+ spec.test_files = spec.files.grep(/^spec/)
14
15
 
15
16
  spec.add_dependency 'rack'
16
17
  spec.add_dependency 'redic'
18
+
19
+ spec.add_development_dependency 'rspec'
17
20
  end
@@ -0,0 +1,234 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+ require 'rack/lint'
4
+ require 'rack/mock'
5
+
6
+ # These tests are unceremoniously copied and modified from
7
+ # https://github.com/rack/rack/blob/master/test/spec_session_memcache.rb.
8
+ describe Rack::Session::Redic do
9
+ ROOT = '/'
10
+
11
+ session_key = Rack::Session::Abstract::Persisted::DEFAULT_OPTIONS[:key]
12
+ session_match = /#{session_key}=([0-9a-fA-F]+);/
13
+
14
+ incrementor = lambda do |env|
15
+ env['rack.session']['counter'] ||= 0
16
+ env['rack.session']['counter'] += 1
17
+
18
+ Rack::Response.new(env['rack.session'].inspect).to_a
19
+ end
20
+
21
+ drop_session = Rack::Lint.new(proc do |env|
22
+ env['rack.session.options'][:drop] = true
23
+ incrementor.call(env)
24
+ end)
25
+
26
+ renew_session = Rack::Lint.new(proc do |env|
27
+ env['rack.session.options'][:renew] = true
28
+ incrementor.call(env)
29
+ end)
30
+
31
+ defer_session = Rack::Lint.new(proc do |env|
32
+ env['rack.session.options'][:defer] = true
33
+ incrementor.call(env)
34
+ end)
35
+
36
+ skip_session = Rack::Lint.new(proc do |env|
37
+ env['rack.session.options'][:skip] = true
38
+ incrementor.call(env)
39
+ end)
40
+
41
+ incrementor = Rack::Lint.new(incrementor)
42
+
43
+ it 'creates a new cookie' do
44
+ redic = Rack::Session::Redic.new(incrementor)
45
+ res = Rack::MockRequest.new(redic).get(ROOT)
46
+
47
+ expect(res[Rack::SET_COOKIE]).to include("#{ session_key }=")
48
+ expect(res.body).to eq('{"counter"=>1}')
49
+ end
50
+
51
+ it 'determines session from a cookie' do
52
+ redic = Rack::Session::Redic.new(incrementor)
53
+ req = Rack::MockRequest.new(redic)
54
+ res = req.get(ROOT)
55
+
56
+ cookie = res[Rack::SET_COOKIE]
57
+
58
+ expect(req.get(ROOT, Rack::HTTP_COOKIE => cookie).body).to eq('{"counter"=>2}')
59
+ expect(req.get(ROOT, Rack::HTTP_COOKIE => cookie).body).to eq('{"counter"=>3}')
60
+ end
61
+
62
+ it 'determines session only from a cookie by default' do
63
+ redic = Rack::Session::Redic.new(incrementor)
64
+ req = Rack::MockRequest.new(redic)
65
+ res = req.get(ROOT)
66
+ sid = res[Rack::SET_COOKIE][session_match, 1]
67
+
68
+ expect(req.get("/?rack.session=#{sid}").body).to eq('{"counter"=>1}')
69
+ expect(req.get("/?rack.session=#{sid}").body).to eq('{"counter"=>1}')
70
+ end
71
+
72
+ it 'determines session from params' do
73
+ redic = Rack::Session::Redic.new(incrementor, cookie_only: false)
74
+ req = Rack::MockRequest.new(redic)
75
+ res = req.get(ROOT)
76
+ sid = res[Rack::SET_COOKIE][session_match, 1]
77
+
78
+ expect(req.get("/?rack.session=#{sid}").body).to eq('{"counter"=>2}')
79
+ expect(req.get("/?rack.session=#{sid}").body).to eq('{"counter"=>3}')
80
+ end
81
+
82
+ it 'survives nonexistant cookies' do
83
+ bad_cookie = "rack.session=#{ SecureRandom.hex(16) }"
84
+
85
+ redic = Rack::Session::Redic.new(incrementor)
86
+ res = Rack::MockRequest.new(redic).get(ROOT, Rack::HTTP_COOKIE => bad_cookie)
87
+
88
+ expect(res.body).to eq('{"counter"=>1}')
89
+
90
+ cookie = res[Rack::SET_COOKIE][session_match]
91
+ expect(cookie).not_to match(/#{ bad_cookie }/)
92
+ end
93
+
94
+ it 'maintains freshness' do
95
+ redic = Rack::Session::Redic.new(incrementor, expire_after: 3)
96
+ res = Rack::MockRequest.new(redic).get(ROOT)
97
+ expect(res.body).to include('"counter"=>1')
98
+
99
+ cookie = res[Rack::SET_COOKIE]
100
+ res = Rack::MockRequest.new(redic).get(ROOT, Rack::HTTP_COOKIE => cookie)
101
+
102
+ expect(res[Rack::SET_COOKIE]).to eq(cookie)
103
+ expect(res.body).to include('"counter"=>2')
104
+
105
+ puts 'Sleeping to expire session' if $DEBUG
106
+ sleep 4
107
+
108
+ res = Rack::MockRequest.new(redic).get(ROOT, Rack::HTTP_COOKIE => cookie)
109
+ expect(res[Rack::SET_COOKIE]).not_to eq(cookie)
110
+ expect(res.body).to include('"counter"=>1')
111
+ end
112
+
113
+ it 'does not send the same session id if it did not change' do
114
+ redic = Rack::Session::Redic.new(incrementor)
115
+ req = Rack::MockRequest.new(redic)
116
+
117
+ res0 = req.get(ROOT)
118
+ cookie = res0[Rack::SET_COOKIE][session_match]
119
+ expect(res0.body).to eq('{"counter"=>1}')
120
+
121
+ res1 = req.get(ROOT, Rack::HTTP_COOKIE => cookie)
122
+ expect(res1[Rack::SET_COOKIE]).to eq(nil)
123
+ expect(res1.body).to eq('{"counter"=>2}')
124
+
125
+ res2 = req.get(ROOT, Rack::HTTP_COOKIE => cookie)
126
+ expect(res2[Rack::SET_COOKIE]).to eq(nil)
127
+ expect(res2.body).to eq('{"counter"=>3}')
128
+ end
129
+
130
+ it 'deletes cookies with :drop option' do
131
+ redic = Rack::Session::Redic.new(incrementor)
132
+ req = Rack::MockRequest.new(redic)
133
+ drop = Rack::Utils::Context.new(redic, drop_session)
134
+ dreq = Rack::MockRequest.new(drop)
135
+
136
+ res1 = req.get(ROOT)
137
+ session = (cookie = res1[Rack::SET_COOKIE])[session_match]
138
+ expect(res1.body).to eq('{"counter"=>1}')
139
+
140
+ res2 = dreq.get(ROOT, Rack::HTTP_COOKIE => cookie)
141
+ expect(res2[Rack::SET_COOKIE]).to eq(nil)
142
+ expect(res2.body).to eq('{"counter"=>2}')
143
+
144
+ res3 = req.get(ROOT, Rack::HTTP_COOKIE => cookie)
145
+ expect(res3[Rack::SET_COOKIE][session_match]).not_to eq(session)
146
+ expect(res3.body).to eq('{"counter"=>1}')
147
+ end
148
+
149
+ it 'provides new session id with :renew option' do
150
+ redic = Rack::Session::Redic.new(incrementor)
151
+ req = Rack::MockRequest.new(redic)
152
+ renew = Rack::Utils::Context.new(redic, renew_session)
153
+ rreq = Rack::MockRequest.new(renew)
154
+
155
+ res1 = req.get(ROOT)
156
+ session = (cookie = res1[Rack::SET_COOKIE])[session_match]
157
+ expect(res1.body).to eq('{"counter"=>1}')
158
+
159
+ res2 = rreq.get(ROOT, Rack::HTTP_COOKIE => cookie)
160
+ new_cookie = res2[Rack::SET_COOKIE]
161
+ new_session = new_cookie[session_match]
162
+ expect(new_session).not_to eq(session)
163
+ expect(res2.body).to eq('{"counter"=>2}')
164
+
165
+ res3 = req.get(ROOT, Rack::HTTP_COOKIE => new_cookie)
166
+ expect(res3.body).to eq('{"counter"=>3}')
167
+
168
+ # Old cookie was deleted
169
+ res4 = req.get(ROOT, Rack::HTTP_COOKIE => cookie)
170
+ expect(res4.body).to eq('{"counter"=>1}')
171
+ end
172
+
173
+ it 'omits cookie with :defer option but still updates the state' do
174
+ redic = Rack::Session::Redic.new(incrementor)
175
+ count = Rack::Utils::Context.new(redic, incrementor)
176
+ defer = Rack::Utils::Context.new(redic, defer_session)
177
+ dreq = Rack::MockRequest.new(defer)
178
+ creq = Rack::MockRequest.new(count)
179
+
180
+ res0 = dreq.get(ROOT)
181
+ expect(res0[Rack::SET_COOKIE]).to eq(nil)
182
+ expect(res0.body).to eq('{"counter"=>1}')
183
+
184
+ res0 = creq.get(ROOT)
185
+ res1 = dreq.get(ROOT, Rack::HTTP_COOKIE => res0[Rack::SET_COOKIE])
186
+ expect(res1.body).to eq('{"counter"=>2}')
187
+ res2 = dreq.get(ROOT, Rack::HTTP_COOKIE => res0[Rack::SET_COOKIE])
188
+ expect(res2.body).to eq('{"counter"=>3}')
189
+ end
190
+
191
+ it 'omits cookie and state update with :skip option' do
192
+ redic = Rack::Session::Redic.new(incrementor)
193
+ count = Rack::Utils::Context.new(redic, incrementor)
194
+ skip = Rack::Utils::Context.new(redic, skip_session)
195
+ sreq = Rack::MockRequest.new(skip)
196
+ creq = Rack::MockRequest.new(count)
197
+
198
+ res0 = sreq.get(ROOT)
199
+ expect(res0[Rack::SET_COOKIE]).to eq(nil)
200
+ expect(res0.body).to eq('{"counter"=>1}')
201
+
202
+ res0 = creq.get(ROOT)
203
+ res1 = sreq.get(ROOT, Rack::HTTP_COOKIE => res0[Rack::SET_COOKIE])
204
+ expect(res1.body).to eq('{"counter"=>2}')
205
+ res2 = sreq.get(ROOT, Rack::HTTP_COOKIE => res0[Rack::SET_COOKIE])
206
+ expect(res2.body).to eq('{"counter"=>2}')
207
+ end
208
+
209
+ it 'updates deep hashes correctly' do
210
+ hash_check = proc do |env|
211
+ session = env['rack.session']
212
+
213
+ if session.include?('test')
214
+ session[:f][:g][:h] = :j
215
+ else
216
+ session.update a: :b, c: { d: :e }, f: { g: { h: :i } }, 'test' => true
217
+ end
218
+
219
+ [200, {}, [session.inspect]]
220
+ end
221
+
222
+ redic = Rack::Session::Redic.new(hash_check)
223
+ req = Rack::MockRequest.new(redic)
224
+
225
+ res0 = req.get(ROOT)
226
+ session_id = (cookie = res0[Rack::SET_COOKIE])[session_match, 1]
227
+ ses0 = redic.storage.get(session_id)
228
+
229
+ req.get(ROOT, Rack::HTTP_COOKIE => cookie)
230
+ ses1 = redic.storage.get(session_id)
231
+
232
+ expect(ses1).not_to eq(ses0)
233
+ end
234
+ end
@@ -0,0 +1,7 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Ensure we have this set before trying to initialize anything.
5
+ ENV['REDIS_URL'] ||= 'redis://localhost:6379'
6
+
7
+ require 'rack/session/redic'
@@ -0,0 +1,36 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ describe Rack::Session::Redic::Storage do
5
+ subject do
6
+ Rack::Session::Redic::Storage.new(nil, Marshal, ENV['REDIS_URL'])
7
+ end
8
+
9
+ it 'returns nil for empty keys' do
10
+ expect(subject.get('not-here')).to eq(nil)
11
+ end
12
+
13
+ it 'saves objects' do
14
+ object = { saved: true }
15
+ subject.set('saving', object)
16
+
17
+ expect(subject.get('saving')).to eq(object)
18
+ subject.delete('saving') # Cleanup.
19
+ end
20
+
21
+ it 'checks the existence of keys' do
22
+ subject.set('exists', false)
23
+
24
+ expect(subject.exists?('exists')).to eq(true)
25
+ end
26
+
27
+ it 'deletes objects' do
28
+ object = { deleted: true }
29
+ subject.set('deleted', object)
30
+
31
+ expect(subject.get('deleted')).to eq(object)
32
+ subject.delete('deleted')
33
+
34
+ expect(subject.get('deleted')).to eq(nil)
35
+ end
36
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-redic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Lecklider
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-03 00:00:00.000000000 Z
11
+ date: 2017-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  description: Rack::Session in Redis via Redic
42
56
  email:
43
57
  - evan@lecklider.com
@@ -46,6 +60,7 @@ extensions: []
46
60
  extra_rdoc_files: []
47
61
  files:
48
62
  - ".gitignore"
63
+ - ".rspec"
49
64
  - CODE_OF_CONDUCT.md
50
65
  - Gemfile
51
66
  - LICENSE.txt
@@ -53,6 +68,9 @@ files:
53
68
  - Rakefile
54
69
  - lib/rack/session/redic.rb
55
70
  - rack-redic.gemspec
71
+ - spec/session_redic_spec.rb
72
+ - spec/spec_helper.rb
73
+ - spec/storage_spec.rb
56
74
  homepage: https://github.com/evanleck/rack-redic
57
75
  licenses:
58
76
  - MIT
@@ -73,8 +91,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
91
  version: '0'
74
92
  requirements: []
75
93
  rubyforge_project:
76
- rubygems_version: 2.6.10
94
+ rubygems_version: 2.6.12
77
95
  signing_key:
78
96
  specification_version: 4
79
97
  summary: Rack::Session in Redis via Redic
80
- test_files: []
98
+ test_files:
99
+ - spec/session_redic_spec.rb
100
+ - spec/spec_helper.rb
101
+ - spec/storage_spec.rb