Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to set the session middleware when enabling sessions #1161

Merged
merged 4 commits into from
Aug 9, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 5 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1380,11 +1380,12 @@ end
Note that `enable :sessions` actually stores all data in a cookie. This
might not always be what you want (storing lots of data will increase your
traffic, for instance). You can use any Rack session middleware: in order to
do so, do **not** call `enable :sessions`, but instead pull in your
middleware of choice as you would any other middleware:
do so, do **not** call `enable :sessions`, but instead call `set
:sessions` with your middleware of choice passed in as the value for
`:session_store` along with any other options:

```ruby
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the use example still works I'd like to show both (since both should be supported).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call 👍

use Rack::Session::Pool, :expire_after => 2592000
set :sessions, :session_store => Rack::Session::Pool, :expire_after => 2592000

get '/' do
"value = " << session[:value].inspect
Expand Down Expand Up @@ -2098,14 +2099,7 @@ set :protection, :except => [:path_traversal, :session_hijacking]
```

By default, Sinatra will only set up session based protection if `:sessions`
has been enabled. Sometimes you want to set up sessions on your own, though. In
that case you can get it to set up session based protections by passing the
`:session` option:

```ruby
use Rack::Session::Pool
set :protection, :session => true
```
has been enabled.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick "have been enabled".

Also, this is still true if you use the middleware option.

I don't want to ignore that use-case as many applications probably are doing it that way, and likely read it from here.

We should consider the README a kind of spec, because many applications rely on the behavior they learned from it, so we can't simply remove it without notice.

IMO this would mean having different sections under the "Using Sessions" chapter. Likely, we would start out with enable :session, like we do here including the note about defaulting to a cookie store. Followed by a section on "Choosing your own session middleware", which outlines both use-cases you've identified above.

As well, the section below this "Available settings" might also need to be updated wrt the "sessions" option. WDYT?

tl;dr I'm happy to support both cases independently.

Copy link
Member Author

@jkowens jkowens Aug 4, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. To enable session based protection using the middleware option the following code would need to be used though (as described in #1038):

 disable :protection
 use Rack::Session::Pool
 use Rack::Protection

or

use Rack::Session::Pool
use ::Rack::Protection::RemoteToken
use ::Rack::Protection::SessionHijacking

The code sample used before was incorrect, it didn't work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about to provide a regression test (if there aren't any) to ensure this behavior works?


### Available Settings

Expand Down
3 changes: 2 additions & 1 deletion lib/sinatra/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1709,7 +1709,8 @@ def setup_sessions(builder)
options = {}
options[:secret] = session_secret if session_secret?
options.merge! sessions.to_hash if sessions.respond_to? :to_hash
builder.use Rack::Session::Cookie, options
session_store = options.delete(:session_store) { Rack::Session::Cookie }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be concerned about mutating the options hash at this point?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I see an issue with it, since the original sessions hash is preserved.

builder.use session_store, options
end

def detect_rack_handler
Expand Down
8 changes: 8 additions & 0 deletions test/settings_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,14 @@ def use(middleware, *)
end
end

it 'sets up RemoteToken if sessions are enabled with a custom session store' do
MiddlewareTracker.track do
Sinatra.new { set :sessions, :session_store => Rack::Session::Pool }.new
assert_include MiddlewareTracker.used, Rack::Session::Pool
assert_include MiddlewareTracker.used, Rack::Protection::RemoteToken
end
end

it 'does not set up RemoteToken if sessions are disabled' do
MiddlewareTracker.track do
Sinatra.new.new
Expand Down