redis-rack-2.1.2/0000755000004100000410000000000013632751652013602 5ustar www-datawww-dataredis-rack-2.1.2/.travis.yml0000644000004100000410000000074413632751652015720 0ustar www-datawww-datalanguage: ruby script: bundle exec rake rvm: - 2.2 - 2.3 - 2.4 - 2.5 - 2.6 - 2.7 - ruby-head - jruby-head matrix: allow_failures: - rvm: jruby-head - rvm: ruby-head deploy: provider: rubygems api_key: secure: VTosVmCdLWUGK8KyzovYri7ySfd7fACtfL8MClEBBHnI+m2cLCpmtCJ7Z1X7z9BXlj974EDaF8V9iRKzfksXIf8aaPfVQw9AW94fLJZbfSB8YGOGyNbPu9YECoZQB1aZ2lw9s/aEdfwCbmqizO/fYpG3YoPKJdm1ZJpNOFR37Xk= gem: redis-rack on: tags: true repo: redis-store/redis-rack redis-rack-2.1.2/test/0000755000004100000410000000000013632751652014561 5ustar www-datawww-dataredis-rack-2.1.2/test/rack/0000755000004100000410000000000013632751652015501 5ustar www-datawww-dataredis-rack-2.1.2/test/rack/session/0000755000004100000410000000000013632751652017164 5ustar www-datawww-dataredis-rack-2.1.2/test/rack/session/redis_test.rb0000644000004100000410000003356513632751652021672 0ustar www-datawww-datarequire 'test_helper' require 'rack/mock' require 'thread' require 'connection_pool' describe Rack::Session::Redis do session_key = Rack::Session::Redis::DEFAULT_OPTIONS[:key] session_match = /#{session_key}=([0-9a-fA-F]+);/ incrementor = lambda do |env| env["rack.session"]["counter"] ||= 0 env["rack.session"]["counter"] += 1 Rack::Response.new(env["rack.session"].inspect).to_a end drop_session = proc do |env| env['rack.session.options'][:drop] = true incrementor.call(env) end renew_session = proc do |env| env['rack.session.options'][:renew] = true incrementor.call(env) end defer_session = proc do |env| env['rack.session.options'][:defer] = true incrementor.call(env) end skip_session = proc do |env| env['rack.session.options'][:skip] = true incrementor.call(env) end # # test Redis connection # Rack::Session::Redis.new(incrementor) # # it "faults on no connection" do # lambda{ # Rack::Session::Redis.new(incrementor, :redis_server => 'nosuchserver') # }.must_raise(Exception) # end it "can create it's own pool" do session_store = Rack::Session::Redis.new(incrementor, pool_size: 5, pool_timeout: 10) conn = session_store.instance_variable_get(:@conn) conn.pool.class.must_equal ::ConnectionPool conn.pool.instance_variable_get(:@size).must_equal 5 end it "can create it's own pool using default Redis server" do session_store = Rack::Session::Redis.new(incrementor, pool_size: 5, pool_timeout: 10) session_store.with { |connection| connection.to_s.must_match(/127\.0\.0\.1:6379 against DB 0 with namespace rack:session$/) } end it "can create it's own pool using provided Redis server" do session_store = Rack::Session::Redis.new(incrementor, redis_server: 'redis://127.0.0.1:6380/1', pool_size: 5, pool_timeout: 10) session_store.with { |connection| connection.to_s.must_match(/127\.0\.0\.1:6380 against DB 1$/) } end it "can use a supplied pool" do session_store = Rack::Session::Redis.new(incrementor, pool: ::ConnectionPool.new(size: 1, timeout: 1) { ::Redis::Store::Factory.create("redis://127.0.0.1:6380/1")}) conn = session_store.instance_variable_get(:@conn) conn.pool.class.must_equal ::ConnectionPool conn.pool.instance_variable_get(:@size).must_equal 1 end it "uses the specified Redis store when provided" do store = ::Redis::Store::Factory.create('redis://127.0.0.1:6380/1') pool = Rack::Session::Redis.new(incrementor, :redis_store => store) pool.with do |p| p.to_s.must_match(/127\.0\.0\.1:6380 against DB 1$/) p.must_equal(store) end end it "uses the default Redis server and namespace when not provided" do pool = Rack::Session::Redis.new(incrementor) pool.with { |p| p.to_s.must_match(/127\.0\.0\.1:6379 against DB 0 with namespace rack:session$/) } end it "uses the specified namespace when provided" do pool = Rack::Session::Redis.new(incrementor, :redis_server => {:namespace => 'test:rack:session'}) pool.with { |p| p.to_s.must_match(/namespace test:rack:session$/) } end it "uses the specified Redis server when provided" do pool = Rack::Session::Redis.new(incrementor, :redis_server => 'redis://127.0.0.1:6380/1') pool.with { |p| p.to_s.must_match(/127\.0\.0\.1:6380 against DB 1$/) } end it "is threadsafe by default" do sesion_store = Rack::Session::Redis.new(incrementor) sesion_store.threadsafe?.must_equal(true) end it "does not store a blank session" do session_store = Rack::Session::Redis.new(incrementor) sid = session_store.generate_unique_sid({}) session_store.with { |c| c.get(sid.private_id).must_be_nil } end it "locks the store mutex" do mutex = Mutex.new mutex.expects(:lock).once sesion_store = Rack::Session::Redis.new(incrementor) sesion_store.instance_variable_set(:@mutex, mutex) was_yielded = false request = Minitest::Mock.new request.expect(:multithread?, true) sesion_store.with_lock(request) { was_yielded = true} was_yielded.must_equal(true) end describe "threadsafe disabled" do it "can have the global lock disabled" do sesion_store = Rack::Session::Redis.new(incrementor, :threadsafe => false) sesion_store.threadsafe?.must_equal(false) end it "does not lock the store mutex" do mutex = Mutex.new mutex.expects(:lock).never sesion_store = Rack::Session::Redis.new(incrementor, :threadsafe => false) sesion_store.instance_variable_set(:@mutex, mutex) was_yielded = false request = Minitest::Mock.new request.expect(:multithread?, true) sesion_store.with_lock(request) { was_yielded = true} was_yielded.must_equal(true) end end it "creates a new cookie" do with_pool_management(incrementor) do |pool| res = Rack::MockRequest.new(pool).get("/") res["Set-Cookie"].must_include("#{session_key}=") res.body.must_equal('{"counter"=>1}') end end it "determines session from a cookie" do with_pool_management(incrementor) do |pool| req = Rack::MockRequest.new(pool) res = req.get("/") cookie = res["Set-Cookie"] req.get("/", "HTTP_COOKIE" => cookie). body.must_equal('{"counter"=>2}') req.get("/", "HTTP_COOKIE" => cookie). body.must_equal('{"counter"=>3}') end end it "determines session only from a cookie by default" do with_pool_management(incrementor) do |pool| req = Rack::MockRequest.new(pool) res = req.get("/") sid = res["Set-Cookie"][session_match, 1] req.get("/?rack.session=#{sid}"). body.must_equal('{"counter"=>1}') req.get("/?rack.session=#{sid}"). body.must_equal('{"counter"=>1}') end end it "determines session from params" do with_pool_management(incrementor, :cookie_only => false) do |pool| req = Rack::MockRequest.new(pool) res = req.get("/") sid = res["Set-Cookie"][session_match, 1] req.get("/?rack.session=#{sid}"). body.must_equal('{"counter"=>2}') req.get("/?rack.session=#{sid}"). body.must_equal('{"counter"=>3}') end end it "survives nonexistant cookies" do bad_cookie = "rack.session=blarghfasel" with_pool_management(incrementor) do |pool| res = Rack::MockRequest.new(pool). get("/", "HTTP_COOKIE" => bad_cookie) res.body.must_equal('{"counter"=>1}') cookie = res["Set-Cookie"][session_match] cookie.wont_match(/#{bad_cookie}/) end end it "maintains freshness" do with_pool_management(incrementor, :expire_after => 3) do |pool| res = Rack::MockRequest.new(pool).get('/') res.body.must_include('"counter"=>1') cookie = res["Set-Cookie"] sid = cookie[session_match, 1] res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie) res["Set-Cookie"][session_match, 1].must_equal(sid) res.body.must_include('"counter"=>2') puts 'Sleeping to expire session' if $DEBUG sleep 4 res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie) res["Set-Cookie"][session_match, 1].wont_equal(sid) res.body.must_include('"counter"=>1') end end it "does not send the same session id if it did not change" do with_pool_management(incrementor) do |pool| req = Rack::MockRequest.new(pool) res0 = req.get("/") cookie = res0["Set-Cookie"] res0.body.must_equal('{"counter"=>1}') res1 = req.get("/", "HTTP_COOKIE" => cookie) res1["Set-Cookie"].must_be_nil res1.body.must_equal('{"counter"=>2}') res2 = req.get("/", "HTTP_COOKIE" => cookie) res2["Set-Cookie"].must_be_nil res2.body.must_equal('{"counter"=>3}') end end it "deletes cookies with :drop option" do with_pool_management(incrementor) do |pool| req = Rack::MockRequest.new(pool) drop = Rack::Utils::Context.new(pool, drop_session) dreq = Rack::MockRequest.new(drop) res1 = req.get("/") session = (cookie = res1["Set-Cookie"])[session_match] res1.body.must_equal('{"counter"=>1}') res2 = dreq.get("/", "HTTP_COOKIE" => cookie) res2["Set-Cookie"].must_be_nil res2.body.must_equal('{"counter"=>2}') res3 = req.get("/", "HTTP_COOKIE" => cookie) res3["Set-Cookie"][session_match].wont_equal(session) res3.body.must_equal('{"counter"=>1}') end end it "provides new session id with :renew option" do with_pool_management(incrementor) do |pool| req = Rack::MockRequest.new(pool) renew = Rack::Utils::Context.new(pool, renew_session) rreq = Rack::MockRequest.new(renew) res1 = req.get("/") session = (cookie = res1["Set-Cookie"])[session_match] res1.body.must_equal('{"counter"=>1}') res2 = rreq.get("/", "HTTP_COOKIE" => cookie) new_cookie = res2["Set-Cookie"] new_session = new_cookie[session_match] new_session.wont_equal(session) res2.body.must_equal('{"counter"=>2}') res3 = req.get("/", "HTTP_COOKIE" => new_cookie) res3.body.must_equal('{"counter"=>3}') # Old cookie was deleted res4 = req.get("/", "HTTP_COOKIE" => cookie) res4.body.must_equal('{"counter"=>1}') end end it "omits cookie with :defer option" do with_pool_management(incrementor) do |pool| defer = Rack::Utils::Context.new(pool, defer_session) dreq = Rack::MockRequest.new(defer) res0 = dreq.get("/") res0["Set-Cookie"].must_be_nil res0.body.must_equal('{"counter"=>1}') end end it "does not hit with :skip option" do with_pool_management(incrementor) do |session_store| skip = Rack::Utils::Context.new(session_store, skip_session) sreq = Rack::MockRequest.new(skip) res0 = sreq.get("/") res0.body.must_equal('{"counter"=>1}') end end it "updates deep hashes correctly" do hash_check = proc do |env| session = env['rack.session'] unless session.include? 'test' session.update :a => :b, :c => { :d => :e }, :f => { :g => { :h => :i} }, 'test' => true else session[:f][:g][:h] = :j end [200, {}, [session.inspect]] end with_pool_management(hash_check) do |pool| req = Rack::MockRequest.new(pool) res0 = req.get("/") session_id = (cookie = res0["Set-Cookie"])[session_match, 1] sid = Rack::Session::SessionId.new(session_id) ses0 = pool.with { |c| c.get(sid.private_id) } req.get("/", "HTTP_COOKIE" => cookie) ses1 = pool.with { |c| c.get(sid.private_id) } ses1.wont_equal(ses0) end end # anyone know how to do this better? it "cleanly merges sessions when multithreaded" do unless $DEBUG 1.must_equal(1) # fake assertion to appease the mighty bacon next end warn 'Running multithread test for Session::Redis' with_pool_management(incrementor) do |pool| req = Rack::MockRequest.new(pool) res = req.get('/') res.body.must_equal('{"counter"=>1}') cookie = res["Set-Cookie"] session_id = cookie[session_match, 1] sid = Rack::Session::SessionId.new(session_id) delta_incrementor = lambda do |env| # emulate disconjoinment of threading env['rack.session'] = env['rack.session'].dup Thread.stop env['rack.session'][(Time.now.usec*rand).to_i] = true incrementor.call(env) end tses = Rack::Utils::Context.new pool, delta_incrementor treq = Rack::MockRequest.new(tses) tnum = rand(7).to_i+5 r = Array.new(tnum) do Thread.new(treq) do |run| run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true) end end.reverse.map{|t| t.run.join.value } r.each do |request| request['Set-Cookie'].must_equal(cookie) request.body.must_include('"counter"=>2') end session = pool.with { |c| c.get(sid.private_id) } session.size.must_equal(tnum+1) # counter session['counter'].must_equal(2) # meeeh tnum = rand(7).to_i+5 r = Array.new(tnum) do |i| app = Rack::Utils::Context.new pool, time_delta req = Rack::MockRequest.new app Thread.new(req) do |run| run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true) end end.reverse.map{|t| t.run.join.value } r.each do |request| request['Set-Cookie'].must_equal(cookie) request.body.must_include('"counter"=>3') end session = pool.with { |c| c.get(sid.private_id) } session.size.must_equal(tnum+1) session['counter'].must_equal(3) drop_counter = proc do |env| env['rack.session'].delete 'counter' env['rack.session']['foo'] = 'bar' [200, {'Content-Type'=>'text/plain'}, env['rack.session'].inspect] end tses = Rack::Utils::Context.new pool, drop_counter treq = Rack::MockRequest.new(tses) tnum = rand(7).to_i+5 r = Array.new(tnum) do Thread.new(treq) do |run| run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true) end end.reverse.map{|t| t.run.join.value } r.each do |request| request['Set-Cookie'].must_equal(cookie) request.body.must_include('"foo"=>"bar"') end session = pool.with { |c| c.get(sid.private_id) } session.size.must_equal(r.size+1) session['counter'].must_be_nil session['foo'].must_equal('bar') end end private def with_pool_management(*args) yield simple(*args) yield pooled(*args) yield external_pooled(*args) end def simple(app, options = {}) Rack::Session::Redis.new(app, options) end def pooled(app, options = {}) Rack::Session::Redis.new(app, options) Rack::Session::Redis.new(app, options.merge(pool_size: 5, pool_timeout: 10)) end def external_pooled(app, options = {}) Rack::Session::Redis.new(app, options.merge(pool: ::ConnectionPool.new(size: 1, timeout: 1) { ::Redis::Store::Factory.create("redis://127.0.0.1:6380/1") })) end end redis-rack-2.1.2/test/redis/0000755000004100000410000000000013632751652015667 5ustar www-datawww-dataredis-rack-2.1.2/test/redis/rack/0000755000004100000410000000000013632751652016607 5ustar www-datawww-dataredis-rack-2.1.2/test/redis/rack/connection_test.rb0000644000004100000410000000513413632751652022335 0ustar www-datawww-datarequire 'test_helper' require 'connection_pool' require 'redis/rack/connection' class Redis module Rack describe Connection do def setup @defaults = { host: 'localhost' } end it "can create it's own pool" do conn = Connection.new @defaults.merge(pool_size: 5, pool_timeout: 10) conn.pooled?.must_equal true conn.pool.class.must_equal ConnectionPool conn.pool.instance_variable_get(:@size).must_equal 5 end it "can create it's own pool using default Redis server" do conn = Connection.new @defaults.merge(pool_size: 5, pool_timeout: 10) conn.pooled?.must_equal true conn.with do |connection| connection.to_s.must_match(/127\.0\.0\.1:6379 against DB 0$/) end end it "can create it's own pool using provided Redis server" do conn = Connection.new(redis_server: 'redis://127.0.0.1:6380/1', pool_size: 5, pool_timeout: 10) conn.pooled?.must_equal true conn.with do |connection| connection.to_s.must_match(/127\.0\.0\.1:6380 against DB 1$/) end end it "can use a supplied pool" do pool = ConnectionPool.new size: 1, timeout: 1 do ::Redis::Store::Factory.create('redis://127.0.0.1:6380/1') end conn = Connection.new pool: pool conn.pooled?.must_equal true conn.pool.class.must_equal ConnectionPool conn.pool.instance_variable_get(:@size).must_equal 1 end it "uses the specified Redis store when provided" do store = ::Redis::Store::Factory.create('redis://127.0.0.1:6380/1') conn = Connection.new(redis_store: store) conn.pooled?.must_equal false conn.store.to_s.must_match(/127\.0\.0\.1:6380 against DB 1$/) conn.store.must_equal(store) end it "throws an error when provided Redis store is not the expected type" do assert_raises ArgumentError do Connection.new(redis_store: ::Redis.new) end end it "uses the specified Redis server when provided" do conn = Connection.new(redis_server: 'redis://127.0.0.1:6380/1') conn.pooled?.must_equal false conn.store.to_s.must_match(/127\.0\.0\.1:6380 against DB 1$/) end it "does not include nil options for the connection pool" do conn = Connection.new conn.pool_options.must_be_empty conn = Connection.new(pool_size: nil) conn.pool_options.must_be_empty conn = Connection.new(pool_timeout: nil) conn.pool_options.must_be_empty end end end end redis-rack-2.1.2/test/test_helper.rb0000644000004100000410000000016513632751652017426 0ustar www-datawww-datarequire 'bundler/setup' require 'minitest/autorun' require 'mocha/setup' require 'rack' require 'rack/session/redis' redis-rack-2.1.2/CODEOWNERS0000644000004100000410000000001113632751652015165 0ustar www-datawww-data* @tubbo redis-rack-2.1.2/README.md0000644000004100000410000000414013632751652015060 0ustar www-datawww-data# Redis session store for Rack __`redis-rack`__ provides a Redis-backed session store for __Rack__. See the main [redis-store readme] for general guidelines. **NOTE:** This is not [redis-rack-cache][], the library for using Redis as a backend store for the `Rack::Cache` HTTP cache. All this gem does is store the Rack session within Redis. [![Build Status](https://secure.travis-ci.org/redis-store/redis-rack.png?branch=master)](http://travis-ci.org/redis-store/redis-rack?branch=master) [![Code Climate](https://codeclimate.com/github/redis-store/redis-store.png)](https://codeclimate.com/github/redis-store/redis-rack) [![Gem Version](https://badge.fury.io/rb/redis-rack.png)](http://badge.fury.io/rb/redis-rack) ## Installation Install with Bundler by adding the following to Gemfile: ```ruby gem 'redis-rack' ``` Then, run: ```shell $ bundle install ``` Or, you can install it manually using RubyGems: ```shell $ gem install redis-rack ``` ## Usage If you are using redis-store with Rails, consider using the [redis-rails gem](https://github.com/redis-store/redis-rails) instead. For standalone usage: ```ruby # config.ru require 'rack' require 'rack/session/redis' use Rack::Session::Redis # Alternatively you can specify options to use: use Rack::Session::Redis, :redis_server => "redis://redis:6379/0", :expires_in => 3600 # Seconds. If you are using ActiveSupport you can use 1.hour ``` ## Development To install this gem for development purposes: ```shell $ gem install bundler # note: you don't need to do this if you already have it installed $ git clone git://github.com/redis-store/redis-rack.git $ cd redis-rack $ bundle install ``` ## Running tests To run tests: ```shell $ bundle exec rake ``` If you are on **Snow Leopard** you have to run the following command to build this software: ```shell $ env ARCHFLAGS="-arch x86_64" bundle exec rake ``` ## Copyright 2009 - 2013 Luca Guidi - [http://lucaguidi.com](http://lucaguidi.com), released under the MIT license [redis-rack-cache]: https://github.com/redis-store/redis-rack-cache [redis-store readme]: https://github.com/redis-store/redis-store redis-rack-2.1.2/bin/0000755000004100000410000000000013632751652014352 5ustar www-datawww-dataredis-rack-2.1.2/bin/appraisal0000755000004100000410000000063113632751652016254 0ustar www-datawww-data#!/usr/bin/env ruby # frozen_string_literal: true # # This file was generated by Bundler. # # The application 'appraisal' is installed as part of a gem, and # this file is here to facilitate running it. # require "pathname" ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath) require "rubygems" require "bundler/setup" load Gem.bin_path("appraisal", "appraisal") redis-rack-2.1.2/bin/rake0000755000004100000410000000061213632751652015221 0ustar www-datawww-data#!/usr/bin/env ruby # frozen_string_literal: true # # This file was generated by Bundler. # # The application 'rake' is installed as part of a gem, and # this file is here to facilitate running it. # require "pathname" ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath) require "rubygems" require "bundler/setup" load Gem.bin_path("rake", "rake") redis-rack-2.1.2/CHANGELOG.md0000644000004100000410000001447113632751652015422 0ustar www-datawww-datav2.1.0 (2020-01-13) -------------------------------------------------------------------------------- * Update version to v2.1.0 final Tom Scott * Test against most recent versions of Ruby Tom Scott * Update gemspec to remove rubyforge_project It is deprecated or removed already Original warning message: Gem::Specification#rubyforge_project= is deprecated with no replacement. It will be removed on or after 2019-12-01. PikachuEXE * back tests to original state Alexey Vasiliev * Fix redis-rack for rack 2.0.8, small improvements Alexey Vasiliev * Fix redis-rack for rack 2.0.8, fix generate_unique_sid Alexey Vasiliev * Fix redis-rack for rack 2.0.8 Alexey Vasiliev * v2.1.0.pre: Update Rack Session API, drop support for Rack 1.0 Tom Scott v2.0.6 -------------------------------------------------------------------------------- * v2.0.6: Prevent Connection Pool from passing nil options Tom Scott * Make bundler dependency more permissive to support future ruby versions Tom Scott * Drop support for Rack v1 Tom Scott * Update Rack::Session API Compatibility The latest version of Rack [deprecated subclassing Rack::Session::ID](https://github.com/rack/rack/blob/master/lib/rack/session/abstract/id.rb#L412-L419), replacing it instead with `Rack::Session::Persisted`. Update the method implementations in this gem to support the new API. Shoutouts to @onk for actually writing this code, we're pulling it in from his fork. Tom Scott * Automatically assign issues to @tubbo when they are created Tom Scott * Automatically release to RubyGems when new tags are pushed to GitHub Tom Scott * Raise Error when `:redis_store` is Incorrect Type Passing an object that isn't a `Redis::Store` into the session storage configuration can cause errors when methods are called with more arguments than the default Redis client can handle. These additional arguments are used by `Rack::Session::Redis` to configure the key namespace and TTL globally in the main configuration, and pass them down to `Redis::Store` to be appended to the key. An `ArgumentError` will now be thrown when a `:redis_store` is of a type that isn't a `Redis::Store` (or a subclass thereof). Resolves #46 Tom Scott * Add code owners Tom Scott * Do not provide nil values for missing connection pool options Fixes #44 Jake Goulding v2.0.5 -------------------------------------------------------------------------------- * v2.0.5 release Tom Scott * add spec to validate blank sessions are not stored in redis mstruve * dont store a blank session in redis mstruve * Add documentation for options Daniel M Barlow v2.0.4 -------------------------------------------------------------------------------- * Release 2.0.4 Tom Scott * Remove .ruby-version Tom Scott * Remove rake, appraisal from gemspec executables The contents of the bin directory are binstubs to assist development. They are not intended to be shipped with the gem itself. This commit updates the gemspec to ensure that they are not exposed to rubygems as executables for redis-rack, which will fix conflicts with the legitimate rake and appraisal executables provided by those other gems. Matt Brictson v2.0.3 -------------------------------------------------------------------------------- * v2.0.3: Avoid mutex locking with global option Tom Scott * Restore default_options in #generate_unique_sid Tom Scott * Refactor connection_pool code Adds a `Redis::Rack::Connection` object for handling the instantiation of a `Redis::Store` or a `ConnectionPool` if pool configuration is given. Restores the purpose of `Rack::Session::Redis` to only implement the session ID abstract API provided by Rack. Tom Scott * Rename :use_global_lock option to :threadsafe to match Rails Garrett Thornburg * Use mocha mocks to assert the mutex is never locked Garrett Thornburg * Allow redis-store v1.4 Shane O'Grady * Create a :use_global_lock option that avoids the global lock Garrett Thornburg * Rake task for running all tests on all gem versions Tom Scott * Install Appraisal so we can test against multiple versions of Rack Tom Scott v2.0.2 -------------------------------------------------------------------------------- * v2.0.2: Resolve regression forcing Rack 2.x and above Tom Scott v2.0.1 -------------------------------------------------------------------------------- * v2.0.1: Relax gem dependencies Tom Scott * smoothen redis-store dependency Mathieu Jobin * Drop support for Rubinius 1.9 mode 1.9.x is EOL in MRI Ruby Land, and Rubinius 1.9 mode isn't really used much anymore. This should make the builds pass again. Tom Scott * Update README.md (#20) Nicolas * Remove jruby 1.9 mode from the build matrix Tom Scott * Remove test because why Tom Scott v2.0.0 -------------------------------------------------------------------------------- * v2.0: Drop support for Ruby below 2.2 (thanks @connorshea) Fixes #17, major shoutouts to @connorshea for getting this off the ground. This also edits the CI config to drop support for older Ruby versions. Tom Scott * Fix gem dependency versions Tom Scott * v2.0.0.pre Add support for Rails 5 and Rack 2. Tom Scott * v2.0.0: Upgrade to Rack 2.0 This release includes some backwards-incompatible changes that pertain to Rails' upgrade to Rack 2.x. Tom Scott * Update README Tom Scott * Fix readme Tom Scott * travis.yml add Ruby 2.3.0 shiro16 * add 2.1 and 2.2 rubies to travis Marc Roberts * Remove support for Ruby 1.9 Marc Roberts * Loosen dependancy on Rack to allow 1.5 and 2.x Rails 5 beta requires Rack 2.x and this gem is unusable unless can use Rack 2.x Marc Roberts * Update README.md Ryan Bigg * add support for ConnectionPool Roman Usherenko * Introduce redis_store option (closes #1) Kurakin Alexander * Atomically lock session id and implement skip support. W. Andrew Loe III v1.5.0 ------ * Enable CI Luca Guidi * Update README.md Luca Guidi * Moved back from jodosha/redis-store Luca Guidi * Moved Luca Guidi redis-rack-2.1.2/.gitignore0000644000004100000410000000010713632751652015570 0ustar www-datawww-dataGemfile.lock *.gem tmp/ stdout gemfiles/vendor gemfiles/*.gemfile.lock redis-rack-2.1.2/Rakefile0000644000004100000410000000040013632751652015241 0ustar www-datawww-datarequire 'bundler/setup' require 'rake' require 'bundler/gem_tasks' require 'redis-store/testing/tasks' task :all do Dir["gemfiles/*.gemfile"].reject { |p| p =~ /\.lock\Z/ }.each do |gemfile| sh "BUNDLE_GEMFILE=#{gemfile} bundle exec rake" end end redis-rack-2.1.2/lib/0000755000004100000410000000000013632751652014350 5ustar www-datawww-dataredis-rack-2.1.2/lib/rack/0000755000004100000410000000000013632751652015270 5ustar www-datawww-dataredis-rack-2.1.2/lib/rack/session/0000755000004100000410000000000013632751652016753 5ustar www-datawww-dataredis-rack-2.1.2/lib/rack/session/redis.rb0000644000004100000410000000431713632751652020413 0ustar www-datawww-datarequire 'rack/session/abstract/id' require 'redis-store' require 'thread' require 'redis/rack/connection' module Rack module Session class Redis < Abstract::PersistedSecure attr_reader :mutex DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge( :redis_server => 'redis://127.0.0.1:6379/0/rack:session' ) def initialize(app, options = {}) super @mutex = Mutex.new @conn = ::Redis::Rack::Connection.new(@default_options) end def generate_unique_sid(session) return generate_sid if session.empty? loop do sid = generate_sid first = with do |c| [*c.setnx(sid.private_id, session, @default_options)].first end break sid if [1, true].include?(first) end end def find_session(req, sid) if req.session.options[:skip] [generate_sid, {}] else with_lock(req, [nil, {}]) do unless sid and session = get_session_with_fallback(sid) session = {} sid = generate_unique_sid(session) end [sid, session] end end end def write_session(req, sid, new_session, options) with_lock(req, false) do with { |c| c.set sid.private_id, new_session, options } sid end end def delete_session(req, sid, options) with_lock(req) do with do |c| c.del(sid.public_id) c.del(sid.private_id) end generate_sid unless options[:drop] end end def threadsafe? @default_options.fetch(:threadsafe, true) end def with_lock(req, default=nil) @mutex.lock if req.multithread? && threadsafe? yield rescue Errno::ECONNREFUSED if $VERBOSE warn "#{self} is unable to find Redis server." warn $!.inspect end default ensure @mutex.unlock if @mutex.locked? end def with(&block) @conn.with(&block) end private def get_session_with_fallback(sid) with { |c| c.get(sid.private_id) || c.get(sid.public_id) } end end end end redis-rack-2.1.2/lib/redis/0000755000004100000410000000000013632751652015456 5ustar www-datawww-dataredis-rack-2.1.2/lib/redis/rack/0000755000004100000410000000000013632751652016376 5ustar www-datawww-dataredis-rack-2.1.2/lib/redis/rack/version.rb0000644000004100000410000000007213632751652020407 0ustar www-datawww-dataclass Redis module Rack VERSION = '2.1.2' end end redis-rack-2.1.2/lib/redis/rack/connection.rb0000644000004100000410000000215613632751652021066 0ustar www-datawww-dataclass Redis module Rack class Connection def initialize(options = {}) @options = options @store = options[:redis_store] @pool = options[:pool] if @pool && !@pool.is_a?(ConnectionPool) raise ArgumentError, "pool must be an instance of ConnectionPool" end if @store && !@store.is_a?(Redis::Store) raise ArgumentError, "redis_store must be an instance of Redis::Store (currently #{@store.class.name})" end end def with(&block) if pooled? pool.with(&block) else block.call(store) end end def pooled? [:pool, :pool_size, :pool_timeout].any? { |key| @options.key?(key) } end def pool @pool ||= ConnectionPool.new(pool_options) { store } if pooled? end def store @store ||= Redis::Store::Factory.create(@options[:redis_server]) end def pool_options { size: @options[:pool_size], timeout: @options[:pool_timeout] }.reject { |key, value| value.nil? }.to_h end end end end redis-rack-2.1.2/lib/redis-rack.rb0000644000004100000410000000012013632751652016712 0ustar www-datawww-datarequire 'redis-store' require 'redis/rack/version' require 'rack/session/redis' redis-rack-2.1.2/Gemfile0000644000004100000410000000017213632751652015075 0ustar www-datawww-datasource 'https://rubygems.org' gemspec gem 'redis-store-testing', github: 'redis-store/testing' gem "appraisal", "~> 2.2" redis-rack-2.1.2/.ruby-version0000644000004100000410000000000613632751652016243 0ustar www-datawww-data2.6.2 redis-rack-2.1.2/.github/0000755000004100000410000000000013632751652015142 5ustar www-datawww-dataredis-rack-2.1.2/.github/auto-assign-issues.yml0000644000004100000410000000002513632751652021425 0ustar www-datawww-dataassignees: - tubbo redis-rack-2.1.2/redis-rack.gemspec0000644000004100000410000000200613632751652017171 0ustar www-datawww-data# -*- encoding: utf-8 -*- $:.push File.expand_path('../lib', __FILE__) require 'redis/rack/version' Gem::Specification.new do |s| s.name = 'redis-rack' s.version = Redis::Rack::VERSION s.authors = ['Luca Guidi'] s.email = ['me@lucaguidi.com'] s.homepage = 'http://redis-store.org/redis-rack' s.summary = %q{Redis Store for Rack} s.description = %q{Redis Store for Rack applications} s.license = 'MIT' s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = [] s.require_paths = ["lib"] s.add_runtime_dependency 'redis-store', ['< 2', '>= 1.2'] s.add_runtime_dependency 'rack', '>= 2.0.8', '< 3' s.add_development_dependency 'rake', '~> 10' s.add_development_dependency 'bundler', '> 1', '< 3' s.add_development_dependency 'mocha', '~> 0.14.0' s.add_development_dependency 'minitest', '~> 5' s.add_development_dependency 'connection_pool', '~> 1.2.0' end redis-rack-2.1.2/MIT-LICENSE0000644000004100000410000000204513632751652015237 0ustar www-datawww-dataCopyright (c) 2009 - 2013 Luca Guidi Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.