Wow, great catch! This is definitely a bug. I guess this should go to
GitHub issues, yes.

This is actually an issue where Camping and Rack::Session::Cookie fight:

At the first request, sessions.state is set in ::Cookie after Camping
has done its magic.

At the second request, Camping loads @state from @env['rack.state'],
the app changes the session, but @cookie['sessions.state'] stays
intact. Camping's #to_a then sets the cookies again in the response:

      @cookies.each do |k, v|
        v = {:value => v, :path => self / "/"} if String === v
        r.set_cookie(k, v)
      end

Which means that it sets a sessions.state-cookie at /sessions/. Then
::Cookies kicks in and figures out that the sessions have changed and
sets a new cookie, but this time at /. (This also has the effect that
Camping copies all the cookies at / into /sessions/)

At the third request, Rack chooses cookies "such that those with more
specific Path attributes precede those with less specific", and the
cookie at /sessions/ wins.

Your fix won't unfornately work because @root is only available inside
a request/controller.

I think we need to do two things:
* Make sure Camping only sets cookies when they've changed.
* Figure out a way to set :path to SCRIPT_NAME. If so, this should
only be an option, as you might also want to mount two apps and have
them share the sessions (aka :path => '/').

I'm not quite sure how we should add that option, though. We could
switch Camping::Session to be a middleware, but this means all apps
will have to change "include Camping::Session" to "use
Camping::Session". It's maybe not such a big deal? We should at least
do these kind of changes *before* the release of 2.0.

Some examples:

# Middleware
use Camping::Session, :secret => "foo", :shared => true

# Subclass
include Camping::Session::Shared
secret "foo"

# New method
include Camping::Session
secret "foo"
shared_cookie!

# Merge #secret and #shared_cookie! together
include Camping::Session
session_options :secret => "foo", :shared => true


I think I actually prefer the middleware-version. It's short and
concise and can be extended with more options if needed.

What do you think?


//Magnus Holm



On Sun, Oct 18, 2009 at 19:59, Jonathan Hickford
<jonathan.hickford+camp...@gmail.com> wrote:
> Hi all,
>
> Not sure where best to raise this (github issues?) but I'm seeing an
> issue with the cookie sessions in camping 2.0 using rack.  If I mount
> an app such as the example blog or the sessions test app at any url
> that is not the root session information is lost in some cases.  Same
> thing happens if I use the built in Camping server.
>
> For example if I mount the blog app using rackup at '/blog' I'm unable
> to log in.  If I mount the sessions test app the information added on
> the second page is lost when it reaches page three.  Looking at the
> cookies in the browser I can see two state cookies set with the paths
> '/' and '/blog/'.
>
> I'm guessing this is to do with Rack::Session::Cookie in session.rb,
> which will default to use :path => '/' in all cases.  If I explicitly
> add :path => '/blog/' there it starts working as expected.  Some more
> detailed outputs here (this will run from /test)
> http://pastebin.com/m6c13a4aa
>
> Is that me doing something crazy there (I'm not expert!) or is that a
> bug?  If that's an issue I think the below change to session.rb fixes
> it, passing in the apps @root into the path Rack's session cookie
> middleware.  I can push that somewhere if we reckon that's a fix?
>
> - app.use Rack::Session::Cookie, :key => key, :secret => secret
> + app.use Rack::Session::Cookie, :key => key, :secret => secret, :path => 
> @root
>
> Regards,
>
> Jon
> _______________________________________________
> Camping-list mailing list
> Camping-list@rubyforge.org
> http://rubyforge.org/mailman/listinfo/camping-list
>
_______________________________________________
Camping-list mailing list
Camping-list@rubyforge.org
http://rubyforge.org/mailman/listinfo/camping-list

Reply via email to