rack-redic 1.4.2 → 2.0.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
  SHA256:
3
- metadata.gz: 858c6435585b418d0bf83041a2bc47a149af5f01e762e93626abf1f796cf1dde
4
- data.tar.gz: 45342e5a439c2ef133cf3cca12a6466c4eb4a59043bfbf43d193db624bb9cbbf
3
+ metadata.gz: 3ab018c4006841a49c2b74041226bb3ecc65421eaf982d5888ad243bae99ba2a
4
+ data.tar.gz: d5f1f5674fc74790ed25010f0e0e04f4a612f87553adb3820d547702da4278ef
5
5
  SHA512:
6
- metadata.gz: 3714511e22ab32a161a19109aa764240902ee7b6f65fe5b3e4625477a28ef02e07ec63ea40599d88552a1af47319a0913f153ade190eba974e2111e745174c0f
7
- data.tar.gz: 49e4025623ce5734539767f44e9ba147693a07211f2200e2dc10b97f7f4ad735d42826fe3275f2c1a515abcd592f9469c5d92d326a9f16943bda68564e625236
6
+ metadata.gz: 9ebe8381cab1210746b77c9a881aa84c4410756317a0cdbc5b1233387f97ed145fd4b22ec47e750b5a0884bd4418d4f1389a3f8d24f63dbf9cd219fe7f79b8b9
7
+ data.tar.gz: 9e936e59d7e1ab45e22b8dba35124d098bdd03ef0ece23aeef82c9db60e26d5b24e98ccbcfe7715ac47f5480ebc3465085fd612bd6bf76c3a0be0ffaae528369
data/README.org ADDED
@@ -0,0 +1,105 @@
1
+ * Rack::Session::Redic
2
+
3
+ =Rack::Session::Redic= provides simple cookie based session management. Session
4
+ data is stored in [[http://redis.io][Redis]] via the [[https://github.com/amakawa/redic][Redic]] gem. The corresponding session key is
5
+ maintained in the cookie.
6
+
7
+ Options include:
8
+
9
+ - =:marshaller= - You may optionally supply the class/module you would
10
+ like to use when marshalling objects in and out of Redis. All that is
11
+ required is that this class respond to the =load= and =dump= methods,
12
+ returning the session hash and a string respectively.
13
+ - =:url= - Additionally, you may pass in the URL for your Redis server.
14
+ The default URL is fetched from the =ENV= as =REDIS_URL= in keeping
15
+ with Heroku and others' practices.
16
+ - =:expire_after= - Finally, expiration will be passed to the Redis
17
+ server via the 'EX' option on 'SET'. Expiration should be in seconds,
18
+ just like Rack's default handling of the =:expire_after= option. This
19
+ option will refresh the expiration set in Redis with each request.
20
+
21
+ Any other options will get passed to =Rack::Session::Abstract::Persisted=.
22
+
23
+ ** Installation
24
+
25
+ Add this line to your application's Gemfile or gems.rb file:
26
+
27
+ #+begin_src ruby
28
+ gem 'rack-redic', require: 'rack/session/redic'
29
+ #+end_src
30
+
31
+ And then execute:
32
+
33
+ #+begin_src sh
34
+ bundle
35
+ #+end_src
36
+
37
+ Or install it yourself as:
38
+
39
+ #+begin_src sh
40
+ gem install rack-redic
41
+ #+end_src
42
+
43
+ ** Usage
44
+
45
+ Anywhere in your Rack application just add:
46
+
47
+ #+begin_src ruby
48
+ # Most basic usage.
49
+ use Rack::Session::Redic
50
+
51
+ # Optionally pass in a marshaller.
52
+ use Rack::Session::Redic, marshaller: Oj
53
+
54
+ # And/or pass in the URL of your Redis server.
55
+ use Rack::Session::Redic, marshaller: Oj, url: 'redis://host:port'
56
+
57
+ # And/or pass in the expiration. (1_800 is 30 minutes in seconds)
58
+ use Rack::Session::Redic, marshaller: Oj, url: 'redis://host:port', expire_after: 1_800
59
+ #+end_src
60
+
61
+ ** Custom Marshallers
62
+
63
+ Since the class/module passed as =:marshaller= only needs to respond to the
64
+ methods =load= and =dump=, you can create any kind of marshaller you would like.
65
+ I've included examples for MessagePack and Oj here as reference.
66
+
67
+ *** [[https://github.com/msgpack/msgpack-ruby][MessagePack]]
68
+
69
+ #+begin_src ruby
70
+ require 'msgpack'
71
+
72
+ MessagePack::DefaultFactory.register_type(0x00, Symbol)
73
+
74
+ module MessagePackMarshaller
75
+ def self.dump(object)
76
+ MessagePack.pack(object)
77
+ end
78
+
79
+ def self.load(string)
80
+ MessagePack.unpack(string)
81
+ end
82
+ end
83
+ #+end_src
84
+
85
+ Then, while adding it your Rack application.
86
+
87
+ #+BEGIN_SRC ruby
88
+ use Rack::Session::Redic, marshaller: MessagePackMarshaller
89
+ #+END_SRC
90
+
91
+ *NOTE:* MessagePack [[https://github.com/msgpack/msgpack-ruby#serializing-and-deserializing-symbols][serializes symbols as strings by default]] so I suggest
92
+ customizing that behavior per their instructions. You can [[https://github.com/msgpack/msgpack/blob/master/spec.md#types-extension-type][read more about
93
+ MessagePack's extension formats here]].
94
+
95
+ *** [[https://github.com/ohler55/oj][Oj]]
96
+
97
+ Oj responds to =load= and =dump= by default so there's no adapter module needed.
98
+
99
+ #+begin_src ruby
100
+ use Rack::Session::Redic, marshaller: Oj
101
+ #+end_src
102
+
103
+ ** License
104
+
105
+ The gem is available as open source under the terms of the [[http://opensource.org/licenses/MIT][MIT License]].
@@ -25,6 +25,8 @@ module Rack
25
25
  #
26
26
  # Any other options will get passed to Rack::Session::Abstract::Persisted.
27
27
  class Redic < Abstract::Persisted
28
+ HASH = {}.freeze
29
+
28
30
  # Redis commands.
29
31
  DELETE = 'DEL'
30
32
  EX = 'EX'
@@ -41,13 +43,12 @@ module Rack
41
43
  # @return [Redic]
42
44
  attr_reader :storage
43
45
 
44
- def initialize(app, options = {})
45
- super
46
+ def initialize(app, options = HASH)
47
+ super(app, options)
46
48
 
47
49
  @expires = options[:expire_after]
48
- @marshaller = options.fetch(:marshaller) { Marshal }
49
- @mutex = Mutex.new
50
- @storage = ::Redic.new(options.fetch(:url) { ENV.fetch(REDIS_URL) })
50
+ @marshaller = options.fetch(:marshaller, Marshal)
51
+ @storage = ::Redic.new(options.fetch(:url, ENV.fetch(REDIS_URL)))
51
52
  end
52
53
 
53
54
  # Generate a session ID that doesn't already exist.
@@ -66,33 +67,28 @@ module Rack
66
67
 
67
68
  # Find the session (or generate a blank one).
68
69
  def find_session(_req, session_id)
69
- @mutex.synchronize do
70
- unless session_id && (session = deserialize(@storage.call(GET, session_id)))
71
- session_id, session = generate_sid, {} # rubocop:disable Style/ParallelAssignment
72
- end
73
-
74
- [session_id, session]
70
+ unless session_id && (session = deserialize(@storage.call(GET, session_id)))
71
+ session_id, session = generate_sid, {} # rubocop:disable Style/ParallelAssignment
75
72
  end
73
+
74
+ [session_id, session]
76
75
  end
77
76
 
78
77
  # Write the session.
79
- def write_session(_req, session_id, new_session, _options)
80
- arguments = [SET, session_id, serialize(new_session)]
78
+ def write_session(_req, session_id, session_data, _options)
79
+ arguments = [SET, session_id, serialize(session_data)]
81
80
  arguments.push(EX, @expires) if @expires
82
81
 
83
- @mutex.synchronize do
84
- @storage.call(*arguments)
82
+ @storage.call(*arguments)
85
83
 
86
- session_id
87
- end
84
+ session_id
88
85
  end
89
86
 
90
87
  # Kill the session.
91
88
  def delete_session(_req, session_id, options)
92
- @mutex.synchronize do
93
- @storage.call(DELETE, session_id)
94
- generate_sid unless options[:drop]
95
- end
89
+ @storage.call(DELETE, session_id)
90
+
91
+ generate_sid unless options[:drop]
96
92
  end
97
93
 
98
94
  private
@@ -115,7 +111,7 @@ module Rack
115
111
  @marshaller.load(string) if string
116
112
 
117
113
  # In the case that loading fails, return a nil.
118
- rescue # rubocop:disable Lint/RescueStandardError
114
+ rescue # rubocop:disable Style/RescueStandardError
119
115
  nil
120
116
  end
121
117
  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: 1.4.2
4
+ version: 2.0.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: 2018-10-12 00:00:00.000000000 Z
11
+ date: 2021-06-23 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: bundler
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
  - !ruby/object:Gem::Dependency
42
56
  name: minitest
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +66,20 @@ dependencies:
52
66
  - - ">="
53
67
  - !ruby/object:Gem::Version
54
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: rubocop
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +94,62 @@ dependencies:
66
94
  - - ">="
67
95
  - !ruby/object:Gem::Version
68
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-minitest
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-packaging
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop-performance
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop-rake
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
69
153
  description: Rack::Session in Redis via Redic
70
154
  email:
71
155
  - evan@lecklider.com
@@ -73,24 +157,15 @@ executables: []
73
157
  extensions: []
74
158
  extra_rdoc_files: []
75
159
  files:
76
- - ".editorconfig"
77
- - ".gitignore"
78
- - ".rubocop.yml"
79
- - CODE_OF_CONDUCT.md
80
160
  - LICENSE.txt
81
- - Makefile
82
- - README.md
83
- - Rakefile
84
- - gems.rb
161
+ - README.org
85
162
  - lib/rack/session/redic.rb
86
- - rack-redic.gemspec
87
- - test/all.rb
88
- - test/helper.rb
89
- - test/session_redic_test.rb
90
163
  homepage: https://github.com/evanleck/rack-redic
91
164
  licenses:
92
165
  - MIT
93
- metadata: {}
166
+ metadata:
167
+ bug_tracker_uri: https://github.com/evanleck/rack-redic/issues
168
+ source_code_uri: https://github.com/evanleck/rack-redic
94
169
  post_install_message:
95
170
  rdoc_options: []
96
171
  require_paths:
@@ -99,19 +174,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
99
174
  requirements:
100
175
  - - ">="
101
176
  - !ruby/object:Gem::Version
102
- version: '0'
177
+ version: 2.5.0
103
178
  required_rubygems_version: !ruby/object:Gem::Requirement
104
179
  requirements:
105
180
  - - ">="
106
181
  - !ruby/object:Gem::Version
107
182
  version: '0'
108
183
  requirements: []
109
- rubyforge_project:
110
- rubygems_version: 2.7.7
184
+ rubygems_version: 3.2.15
111
185
  signing_key:
112
186
  specification_version: 4
113
187
  summary: Rack::Session in Redis via Redic
114
- test_files:
115
- - test/all.rb
116
- - test/helper.rb
117
- - test/session_redic_test.rb
188
+ test_files: []
data/.editorconfig DELETED
@@ -1,24 +0,0 @@
1
- # http://EditorConfig.org
2
- # This is the top most config file.
3
- root = true
4
-
5
- # All files
6
- [*]
7
-
8
- # Unix-style newlines with a newline ending every file
9
- end_of_line = lf
10
- insert_final_newline = true
11
-
12
- # Character set
13
- charset = utf-8
14
-
15
- # Trim extra whitespace.
16
- trim_trailing_whitespace = true
17
-
18
- # Soft tabs and 2 spaces.
19
- indent_style = space
20
- indent_size = 2
21
-
22
- # Makefiles use tabs
23
- [Makefile]
24
- indent_style = tab
data/.gitignore DELETED
@@ -1,10 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /gems.locked
5
- /_yardoc/
6
- /coverage/
7
- /doc/
8
- /pkg/
9
- /spec/reports/
10
- /tmp/
data/.rubocop.yml DELETED
@@ -1,55 +0,0 @@
1
- # http://rubocop.readthedocs.io
2
- # https://github.com/bbatsov/rubocop/blob/master/config/enabled.yml
3
- AllCops:
4
- DisplayCopNames: true
5
- DisplayStyleGuide: true
6
- ExtraDetails: true
7
- TargetRubyVersion: 2.4
8
-
9
- Layout/AlignParameters:
10
- EnforcedStyle: with_fixed_indentation
11
-
12
- Layout/EmptyLineAfterMagicComment:
13
- Enabled: false
14
-
15
- Layout/IndentHash:
16
- EnforcedStyle: consistent
17
-
18
- Layout/MultilineOperationIndentation:
19
- EnforcedStyle: indented
20
-
21
- Layout/SpaceInsideStringInterpolation:
22
- EnforcedStyle: space
23
-
24
- Metrics/AbcSize:
25
- Enabled: false
26
-
27
- Metrics/BlockLength:
28
- Enabled: false
29
-
30
- Metrics/ClassLength:
31
- Enabled: false
32
-
33
- Metrics/CyclomaticComplexity:
34
- Enabled: false
35
-
36
- Metrics/LineLength:
37
- Enabled: false
38
-
39
- Metrics/MethodLength:
40
- Enabled: false
41
-
42
- Metrics/ModuleLength:
43
- Enabled: false
44
-
45
- Metrics/PerceivedComplexity:
46
- Enabled: false
47
-
48
- # Style/Documentation:
49
- # Enabled: false
50
-
51
- Style/IfUnlessModifier:
52
- Enabled: false
53
-
54
- Style/Next:
55
- MinBodyLength: 8
data/CODE_OF_CONDUCT.md DELETED
@@ -1,49 +0,0 @@
1
- # Contributor Code of Conduct
2
-
3
- As contributors and maintainers of this project, and in the interest of
4
- fostering an open and welcoming community, we pledge to respect all people who
5
- contribute through reporting issues, posting feature requests, updating
6
- documentation, submitting pull requests or patches, and other activities.
7
-
8
- We are committed to making participation in this project a harassment-free
9
- experience for everyone, regardless of level of experience, gender, gender
10
- identity and expression, sexual orientation, disability, personal appearance,
11
- body size, race, ethnicity, age, religion, or nationality.
12
-
13
- Examples of unacceptable behavior by participants include:
14
-
15
- * The use of sexualized language or imagery
16
- * Personal attacks
17
- * Trolling or insulting/derogatory comments
18
- * Public or private harassment
19
- * Publishing other's private information, such as physical or electronic
20
- addresses, without explicit permission
21
- * Other unethical or unprofessional conduct
22
-
23
- Project maintainers have the right and responsibility to remove, edit, or
24
- reject comments, commits, code, wiki edits, issues, and other contributions
25
- that are not aligned to this Code of Conduct, or to ban temporarily or
26
- permanently any contributor for other behaviors that they deem inappropriate,
27
- threatening, offensive, or harmful.
28
-
29
- By adopting this Code of Conduct, project maintainers commit themselves to
30
- fairly and consistently applying these principles to every aspect of managing
31
- this project. Project maintainers who do not follow or enforce the Code of
32
- Conduct may be permanently removed from the project team.
33
-
34
- This code of conduct applies both within project spaces and in public spaces
35
- when an individual is representing the project or its community.
36
-
37
- Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
- reported by contacting a project maintainer at evan@lecklider.com. All
39
- complaints will be reviewed and investigated and will result in a response that
40
- is deemed necessary and appropriate to the circumstances. Maintainers are
41
- obligated to maintain confidentiality with regard to the reporter of an
42
- incident.
43
-
44
- This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
- version 1.3.0, available at
46
- [http://contributor-covenant.org/version/1/3/0/][version]
47
-
48
- [homepage]: http://contributor-covenant.org
49
- [version]: http://contributor-covenant.org/version/1/3/0/
data/Makefile DELETED
@@ -1,18 +0,0 @@
1
- .DEFAULT_GOAL := test
2
- .PHONY: test
3
- .SILENT: test
4
-
5
- BE := bundle exec
6
-
7
- # Run our test suite.
8
- #
9
- # To test an individual file, pass the "file" argument like so:
10
- #
11
- # make test file=test/storage_test.rb
12
- #
13
- test:
14
- ifeq ($(origin file), undefined)
15
- $(BE) ruby -r ./test/helper.rb test/all.rb
16
- else
17
- $(BE) ruby -r ./test/helper.rb $(file)
18
- endif
data/README.md DELETED
@@ -1,97 +0,0 @@
1
- # Rack::Session::Redic
2
-
3
- `Rack::Session::Redic` provides simple cookie based session management. Session data is stored in [Redis](http://redis.io) via the [Redic](https://github.com/amakawa/redic) gem. The corresponding session key is maintained in the cookie.
4
-
5
- Options include:
6
-
7
- - `:marshaller` - You may optionally supply the class/module you would like to use when marshalling objects in and out of Redis. All that is required is that this class respond to the `load` and `dump` methods, returning the session hash and a string respectively.
8
- - `:url` - Addtionally, you may pass in the URL for your Redis server. The default URL is fetched from the `ENV` as `REDIS_URL` in keeping with Heroku and others' practices.
9
- - `:expire_after` - Finally, expiration will be passed to the Redis server via the 'EX' option on 'SET'. Expiration should be in seconds, just like Rack's default handling of the `:expire_after` option. This option will refresh the expiration set in Redis with each request.
10
-
11
- Any other options will get passed to `Rack::Session::Abstract::Persisted`.
12
-
13
-
14
- ## Installation
15
-
16
- Add this line to your application's Gemfile or gems.rb file:
17
-
18
- ```ruby
19
- gem 'rack-redic', require: 'rack/session/redic'
20
- ```
21
-
22
- And then execute:
23
-
24
- $ bundle
25
-
26
- Or install it yourself as:
27
-
28
- $ gem install rack-redic
29
-
30
-
31
- ## Usage
32
-
33
- Anywhere in your Rack application just add:
34
-
35
- ```ruby
36
- # Most basic usage.
37
- use Rack::Session::Redic
38
-
39
- # Optionally pass in a marshaller.
40
- use Rack::Session::Redic, marshaller: Oj
41
-
42
- # And/or pass in the URL of your Redis server.
43
- use Rack::Session::Redic, marshaller: Oj, url: 'redis://host:port'
44
-
45
- # And/or pass in the expiration. (1_800 is 30 minutes in seconds)
46
- use Rack::Session::Redic, marshaller: Oj, url: 'redis://host:port', expire_after: 1_800
47
- ```
48
-
49
- ### Custom Marshallers
50
-
51
- Since the class/module passed as `:marshaller` only needs to respond to the methods `load` and `dump`, you can create any kind of marshaller you would like. I've included examples for MessagePack and Oj here as reference.
52
-
53
- #### [MessagePack](https://github.com/msgpack/msgpack-ruby)
54
-
55
- ```ruby
56
- require 'msgpack'
57
-
58
- MessagePack::DefaultFactory.register_type(0x00, Symbol)
59
-
60
- module MessagePackMarshaller
61
- def dump(object)
62
- MessagePack.pack(object)
63
- end
64
- module_function :dump
65
-
66
- def load(string)
67
- MessagePack.unpack(string)
68
- end
69
- module_function :load
70
- end
71
- ```
72
-
73
- Then, while adding it your Rack application.
74
-
75
- ```ruby
76
- use Rack::Session::Redic, marshaller: MessagePackMarshaller
77
- ```
78
-
79
- **NOTE:** MessagePack [serializes symbols as strings by default](https://github.com/msgpack/msgpack-ruby#serializing-and-deserializing-symbols) so I suggest customizing that behavior per their instructions. You can [read more about MessagePack's extension formats here](https://github.com/msgpack/msgpack/blob/master/spec.md#types-extension-type).
80
-
81
- #### [Oj](https://github.com/ohler55/oj)
82
-
83
- Oj responds to `load` and `dump` by default so there's no adapter module needed.
84
-
85
- ```ruby
86
- use Rack::Session::Redic, marshaller: Oj
87
- ```
88
-
89
-
90
- ## Contributing
91
-
92
- Bug reports and pull requests are welcome on GitHub at [https://github.com/evanleck/rack-redic](https://github.com/evanleck/rack-redic). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
93
-
94
-
95
- ## License
96
-
97
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile DELETED
@@ -1,2 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'bundler/gem_tasks'
data/gems.rb DELETED
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
- source 'https://rubygems.org'
3
-
4
- # Load gem dependencies.
5
- gemspec
data/rack-redic.gemspec DELETED
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
- Gem::Specification.new do |spec|
3
- spec.name = 'rack-redic'
4
- spec.version = '1.4.2'
5
- spec.authors = ['Evan Lecklider']
6
- spec.email = ['evan@lecklider.com']
7
-
8
- spec.summary = 'Rack::Session in Redis via Redic'
9
- spec.description = 'Rack::Session in Redis via Redic'
10
- spec.homepage = 'https://github.com/evanleck/rack-redic'
11
- spec.license = 'MIT'
12
- spec.files = `git ls-files`.split("\n")
13
- spec.test_files = spec.files.grep(/^test/)
14
-
15
- spec.add_dependency 'rack'
16
- spec.add_dependency 'redic'
17
-
18
- spec.add_development_dependency 'minitest'
19
- spec.add_development_dependency 'rubocop'
20
- end
data/test/all.rb DELETED
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative 'helper'
3
-
4
- # Require all test files.
5
- Dir.glob('test/*.rb').each(&method(:require))
data/test/helper.rb DELETED
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Add our project folder to the root of our load path.
4
- $LOAD_PATH.unshift File.expand_path('..', __dir__)
5
-
6
- # Ensure we have this set before trying to initialize anything.
7
- ENV['REDIS_URL'] ||= 'redis://localhost:6379'
8
-
9
- # Require our core library.
10
- require 'lib/rack/session/redic'
11
-
12
- # Kick off the tests.
13
- require 'minitest/autorun'
@@ -1,233 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rack/lint'
3
- require 'rack/mock'
4
-
5
- # These tests are unceremoniously copied and modified from
6
- # https://github.com/rack/rack/blob/master/test/spec_session_memcache.rb.
7
- describe Rack::Session::Redic do
8
- ROOT = '/'
9
-
10
- session_key = Rack::Session::Abstract::Persisted::DEFAULT_OPTIONS[:key]
11
- session_match = /#{ session_key }=([0-9a-fA-F]+);/
12
-
13
- incrementor = lambda do |env|
14
- env['rack.session']['counter'] ||= 0
15
- env['rack.session']['counter'] += 1
16
-
17
- Rack::Response.new(env['rack.session'].inspect).to_a
18
- end
19
-
20
- drop_session = Rack::Lint.new(proc do |env|
21
- env['rack.session.options'][:drop] = true
22
- incrementor.call(env)
23
- end)
24
-
25
- renew_session = Rack::Lint.new(proc do |env|
26
- env['rack.session.options'][:renew] = true
27
- incrementor.call(env)
28
- end)
29
-
30
- defer_session = Rack::Lint.new(proc do |env|
31
- env['rack.session.options'][:defer] = true
32
- incrementor.call(env)
33
- end)
34
-
35
- skip_session = Rack::Lint.new(proc do |env|
36
- env['rack.session.options'][:skip] = true
37
- incrementor.call(env)
38
- end)
39
-
40
- incrementor = Rack::Lint.new(incrementor)
41
-
42
- it 'creates a new cookie' do
43
- redic = Rack::Session::Redic.new(incrementor)
44
- response = Rack::MockRequest.new(redic).get(ROOT)
45
-
46
- assert_includes response[Rack::SET_COOKIE], "#{ session_key }="
47
- assert_equal response.body, '{"counter"=>1}'
48
- end
49
-
50
- it 'determines session from a cookie' do
51
- redic = Rack::Session::Redic.new(incrementor)
52
- request = Rack::MockRequest.new(redic)
53
- response = request.get(ROOT)
54
-
55
- cookie = response[Rack::SET_COOKIE]
56
-
57
- assert_equal request.get(ROOT, Rack::HTTP_COOKIE => cookie).body, '{"counter"=>2}'
58
- assert_equal request.get(ROOT, Rack::HTTP_COOKIE => cookie).body, '{"counter"=>3}'
59
- end
60
-
61
- it 'determines session only from a cookie by default' do
62
- redic = Rack::Session::Redic.new(incrementor)
63
- request = Rack::MockRequest.new(redic)
64
- response = request.get(ROOT)
65
- sid = response[Rack::SET_COOKIE][session_match, 1]
66
-
67
- assert_equal request.get("/?rack.session=#{ sid }").body, '{"counter"=>1}'
68
- assert_equal request.get("/?rack.session=#{ sid }").body, '{"counter"=>1}'
69
- end
70
-
71
- it 'determines session from params' do
72
- redic = Rack::Session::Redic.new(incrementor, cookie_only: false)
73
- request = Rack::MockRequest.new(redic)
74
- response = request.get(ROOT)
75
- sid = response[Rack::SET_COOKIE][session_match, 1]
76
-
77
- assert_equal request.get("/?rack.session=#{ sid }").body, '{"counter"=>2}'
78
- assert_equal request.get("/?rack.session=#{ sid }").body, '{"counter"=>3}'
79
- end
80
-
81
- it 'survives nonexistant cookies' do
82
- bad_cookie = "rack.session=#{ SecureRandom.hex(16) }"
83
-
84
- redic = Rack::Session::Redic.new(incrementor)
85
- response = Rack::MockRequest.new(redic).get(ROOT, Rack::HTTP_COOKIE => bad_cookie)
86
-
87
- assert_equal response.body, '{"counter"=>1}'
88
-
89
- cookie = response[Rack::SET_COOKIE][session_match]
90
- refute_match(/#{ bad_cookie }/, cookie)
91
- end
92
-
93
- it 'maintains freshness' do
94
- redic = Rack::Session::Redic.new(incrementor, expire_after: 3)
95
- response = Rack::MockRequest.new(redic).get(ROOT)
96
- assert_includes response.body, '"counter"=>1'
97
-
98
- cookie = response[Rack::SET_COOKIE]
99
- response = Rack::MockRequest.new(redic).get(ROOT, Rack::HTTP_COOKIE => cookie)
100
-
101
- assert_equal response[Rack::SET_COOKIE], cookie
102
- assert_includes response.body, '"counter"=>2'
103
-
104
- puts 'Sleeping to expire session' if $DEBUG
105
- sleep 4
106
-
107
- response = Rack::MockRequest.new(redic).get(ROOT, Rack::HTTP_COOKIE => cookie)
108
- refute_equal response[Rack::SET_COOKIE], cookie
109
- assert_includes response.body, '"counter"=>1'
110
- end
111
-
112
- it 'does not send the same session id if it did not change' do
113
- redic = Rack::Session::Redic.new(incrementor)
114
- request = Rack::MockRequest.new(redic)
115
-
116
- res0 = request.get(ROOT)
117
- cookie = res0[Rack::SET_COOKIE][session_match]
118
- assert_equal res0.body, '{"counter"=>1}'
119
-
120
- res1 = request.get(ROOT, Rack::HTTP_COOKIE => cookie)
121
- assert_nil res1[Rack::SET_COOKIE]
122
- assert_equal res1.body, '{"counter"=>2}'
123
-
124
- res2 = request.get(ROOT, Rack::HTTP_COOKIE => cookie)
125
- assert_nil res2[Rack::SET_COOKIE]
126
- assert_equal res2.body, '{"counter"=>3}'
127
- end
128
-
129
- it 'deletes cookies with :drop option' do
130
- redic = Rack::Session::Redic.new(incrementor)
131
- request = Rack::MockRequest.new(redic)
132
- drop = Rack::Utils::Context.new(redic, drop_session)
133
- dreq = Rack::MockRequest.new(drop)
134
-
135
- res1 = request.get(ROOT)
136
- session = (cookie = res1[Rack::SET_COOKIE])[session_match]
137
- assert_equal res1.body, '{"counter"=>1}'
138
-
139
- res2 = dreq.get(ROOT, Rack::HTTP_COOKIE => cookie)
140
- assert_nil res2[Rack::SET_COOKIE]
141
- assert_equal res2.body, '{"counter"=>2}'
142
-
143
- res3 = request.get(ROOT, Rack::HTTP_COOKIE => cookie)
144
- refute_equal res3[Rack::SET_COOKIE][session_match], session
145
- assert_equal res3.body, '{"counter"=>1}'
146
- end
147
-
148
- it 'provides new session id with :renew option' do
149
- redic = Rack::Session::Redic.new(incrementor)
150
- request = Rack::MockRequest.new(redic)
151
- renew = Rack::Utils::Context.new(redic, renew_session)
152
- renew_request = Rack::MockRequest.new(renew)
153
-
154
- res1 = request.get(ROOT)
155
- session = (cookie = res1[Rack::SET_COOKIE])[session_match]
156
- assert_equal res1.body, '{"counter"=>1}'
157
-
158
- res2 = renew_request.get(ROOT, Rack::HTTP_COOKIE => cookie)
159
- new_cookie = res2[Rack::SET_COOKIE]
160
- new_session = new_cookie[session_match]
161
- refute_equal new_session, session
162
- assert_equal res2.body, '{"counter"=>2}'
163
-
164
- res3 = request.get(ROOT, Rack::HTTP_COOKIE => new_cookie)
165
- assert_equal res3.body, '{"counter"=>3}'
166
-
167
- # Old cookie was deleted
168
- res4 = request.get(ROOT, Rack::HTTP_COOKIE => cookie)
169
- assert_equal res4.body, '{"counter"=>1}'
170
- end
171
-
172
- it 'omits cookie with :defer option but still updates the state' do
173
- redic = Rack::Session::Redic.new(incrementor)
174
- count = Rack::Utils::Context.new(redic, incrementor)
175
- defer = Rack::Utils::Context.new(redic, defer_session)
176
- defer_request = Rack::MockRequest.new(defer)
177
- count_request = Rack::MockRequest.new(count)
178
-
179
- res0 = defer_request.get(ROOT)
180
- assert_nil res0[Rack::SET_COOKIE]
181
- assert_equal res0.body, '{"counter"=>1}'
182
-
183
- res0 = count_request.get(ROOT)
184
- res1 = defer_request.get(ROOT, Rack::HTTP_COOKIE => res0[Rack::SET_COOKIE])
185
- assert_equal res1.body, '{"counter"=>2}'
186
- res2 = defer_request.get(ROOT, Rack::HTTP_COOKIE => res0[Rack::SET_COOKIE])
187
- assert_equal res2.body, '{"counter"=>3}'
188
- end
189
-
190
- it 'omits cookie and state update with :skip option' do
191
- redic = Rack::Session::Redic.new(incrementor)
192
- count = Rack::Utils::Context.new(redic, incrementor)
193
- skip = Rack::Utils::Context.new(redic, skip_session)
194
- skip_request = Rack::MockRequest.new(skip)
195
- count_request = Rack::MockRequest.new(count)
196
-
197
- res0 = skip_request.get(ROOT)
198
- assert_nil res0[Rack::SET_COOKIE]
199
- assert_equal res0.body, '{"counter"=>1}'
200
-
201
- res0 = count_request.get(ROOT)
202
- res1 = skip_request.get(ROOT, Rack::HTTP_COOKIE => res0[Rack::SET_COOKIE])
203
- assert_equal res1.body, '{"counter"=>2}'
204
- res2 = skip_request.get(ROOT, Rack::HTTP_COOKIE => res0[Rack::SET_COOKIE])
205
- assert_equal res2.body, '{"counter"=>2}'
206
- end
207
-
208
- it 'updates deep hashes correctly' do
209
- hash_check = proc do |env|
210
- session = env['rack.session']
211
-
212
- if session.include?('test')
213
- session[:f][:g][:h] = :j
214
- else
215
- session.update a: :b, c: { d: :e }, f: { g: { h: :i } }, 'test' => true
216
- end
217
-
218
- [200, {}, [session.inspect]]
219
- end
220
-
221
- redic = Rack::Session::Redic.new(hash_check)
222
- request = Rack::MockRequest.new(redic)
223
-
224
- res0 = request.get(ROOT)
225
- session_id = (cookie = res0[Rack::SET_COOKIE])[session_match, 1]
226
- ses0 = redic.storage.call('GET', session_id)
227
-
228
- request.get(ROOT, Rack::HTTP_COOKIE => cookie)
229
- ses1 = redic.storage.call('GET', session_id)
230
-
231
- refute_equal ses1, ses0
232
- end
233
- end