6

I'm trying to use redirects and sessions in Sinatra to pass some data around the site. Here's a simplified example, using PrettyPrint for debugging:

require 'pp'

require 'rubygems'
require 'sinatra'

enable :sessions

get '/' do
  session[:foo] = '12345'

  puts 'session1'
  pp session

  redirect to('/redir')
end

get '/redir' do
  puts 'session2'
  pp session
  'hello world'
end

Looking at Thin's output, I see:

>> Listening on 0.0.0.0:4567, CTRL+C to stop
session1
{"session_id"=>
  "ea587d8afdcb2ada64f9b17cdd1fbae7b192dee5dfc2999ff9d323f1528f6a0f",
 "foo"=>"12345"}
127.0.0.1 - - [19/Jul/2011 10:33:24] "GET / HTTP/1.1" 302 - 0.0042
session2
{}
127.0.0.1 - - [19/Jul/2011 10:33:24] "GET /redir HTTP/1.1" 200 11 0.0004

Everything I've seen in the docs suggests that this should work fine. In fact, I never get any session data for /redir, even if I request it directly, and the session persists as you'd expect on subsequent requests for /.

Thoughts?

Mike Craig
  • 1,677
  • 1
  • 13
  • 22
  • Sinatra sessions are using cookies. Did you try monitoring your HTTP headers (with Firebug, for example) to make sure cookies are going in and out? Also look at this one http://stackoverflow.com/questions/5631862/problem-with-sinatra-and-session-variables-which-are-not-being-set and this one http://stackoverflow.com/questions/5693528/how-to-use-sinatra-session – Pavel Veller Jul 19 '11 at 16:49

3 Answers3

12

FWIW, I'm not clear on why this is, but once I moved my Sinatra app to a multi-instance environment, I started having a ton of issues with the session disappearing.

In the end, I found using this syntax worked, whereas the simple 'enable :sessions' or 'set :sessions, true' did not:

use Rack::Session::Cookie, :key => 'rack.session',
                           :path => '/',
                           :secret => 'your_secret'
Tom Lianza
  • 4,012
  • 4
  • 41
  • 50
3

The reason why the format posted by Tom Lianza worked is because by default Sinatra uses

set :session_secret, SecureRandom.hex(64) To select a random secret and since there exists multiple environments, each one will use a different secret resulting in a contradicting cookies. Of course it should be added as an environment variable or Config file that isn't checked into an SVC.

Related Sinatra issue

2

It seems as though the session hash is not loaded until a session variable is referenced. So, for example, you get the expected result if you change the redirect handler to:

get '/redir' do
  puts 'session2'
  puts session[:foo]
  pp session
  'hello world'
end

I guess Sinatra is using the session directly from Rack. A quick peek at the source shows that the session hash is lazily loaded when the [] method (and others) are invoked:

https://github.com/rack/rack/blob/master/lib/rack/session/abstract/id.rb

Steve
  • 15,606
  • 3
  • 44
  • 39
  • That works, but it turns out the "proper" way to access members of the session hash is to use `session[:foo].inspect`. – Mike Craig Jul 21 '11 at 14:22