rack-redic 1.4.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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