<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">I'm implementing a simpler version of the Cookie Session Store in Rails 2.0. If you know what that is, skip the next paragraph.<div><br></div><div>A cookie session store stores the session data inside cookies, on the client, and signs them using a secret string, hashed together. The user can decode the cookie easily if they know much about computers and see what's inside, but they can't alter it because they can't generate the needed hash to sign it, and the server will ignore all cookie session data that isn't signed right. It's neat, you don't need a database, no file system clutter, and I think it feels really just a lot more natural this way.</div><div><br></div><div>Trouble is, I'm trying to make it work as a drop in replacement for the camping sessions mixin so people can 'upgrade' in either direction easily, consider this code however...</div><div><br></div><div><blockquote type="cite" class=""><div><font class="Apple-style-span" color="#000000"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "><span style="color: #881350"> def</span> service(*a)</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> <span style="color: #881350">if</span> <span style="color: #c94b16">@cookies</span>.identity</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> blob, secure_hash = <span style="color: #c94b16">@cookies</span>.identity.to_s.<span style="color: #881350">split</span>(<span style="color: #760f15">':'</span>)</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> blob = <span style="color: #881350">Base64</span>.decode64(blob)</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> data = <span style="color: #881350">Marshal</span>.restore(blob)</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> data = {} <span style="color: #881350">unless</span> secure_blob_hasher(blob) == secure_hash</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> <span style="color: #881350">else</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> blob = <span style="color: #760f15">''</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> data = {}</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> <span style="color: #881350">end</span></div><p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Helvetica; min-height: 12.0px"> <br class="webkit-block-placeholder"></p><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> app = <span style="color: #881350">self</span>.<span style="color: #881350">class</span>.name.<span style="color: #881350">gsub</span>(<span style="color: #c700c2">/^(\w+)::.+$/</span>, <span style="color: #760f15">'\1'</span>)</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> <span style="color: #c94b16">@state</span> = (data[app] ||= Camping::H[])</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> hash_before = blob.hash</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> <span style="color: #881350">return</span> <span style="color: #881350">super</span>(*a)</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; color: rgb(136, 19, 80); "><span style="color: #000000"> </span>ensure</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> <span style="color: #881350">if</span> data</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> data[app] = <span style="color: #c94b16">@state</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> blob = <span style="color: #881350">Marshal</span>.dump(data)</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> <span style="color: #881350">unless</span> hash_before == blob.hash</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> secure_hash = secure_blob_hasher(blob)</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> <span style="color: #c94b16">@cookies</span>.identity = <span style="color: #881350">Base64</span>.encode64(blob).strip + <span style="color: #760f15">':'</span> + secure_hash</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> <span style="color: #881350">end</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> <span style="color: #881350">end</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Helvetica; "> <span style="color: #881350">end</span></div></font></div></blockquote><br></div><div>and there's quite a problem, check out that line, <span class="Apple-style-span" style="font-size: 10px; "><span style="color: rgb(136, 19, 80); ">return</span> <span style="color: rgb(136, 19, 80); ">super</span>(*a)<span class="Apple-style-span" style="font-size: 12px; ">, and look at the camping source, and soon enough one realises the reason this doesn't work at all is that the code inside the super is the code converting @cookies in to the <i>Set-Cookie</i> http header, so it's too late to set a cookie by the time the ensure block runs and tries to save the session.</span></span></div><div><br></div><div>What should I do? It feels dirty to copy code out of camping.rb that serializes the cookies, in effect making it do that twice every time the session data and any other cookie data changes (which wouldn't be a big deal for my app, but still seems nasty). Anyone got a better idea?</div><div><br></div><div><br></div><div>—</div><div>Jenna “Where's my oats” Fox</div></body></html>