Skip to content

Instantly share code, notes, and snippets.

@jbasdf
Created January 30, 2012 21:45
Show Gist options
  • Save jbasdf/1706918 to your computer and use it in GitHub Desktop.
Save jbasdf/1706918 to your computer and use it in GitHub Desktop.
Middleware for Sessions in Goliath Options [Click the star to watch this topic]
require 'rack/utils'
require 'rack/session/abstract/id'
require 'remcached'
require 'em-synchrony/em-remcached'
module Slurper
module Rack
class Session < ::Rack::Session::Abstract::ID
include Goliath::Rack::AsyncMiddleware
def initialize(app, options={})
@app = app
@default_options = self.class::DEFAULT_OPTIONS.merge(options)
@key = @default_options.delete(:key)
@cookie_only = @default_options.delete(:cookie_only)
initialize_sid
super(app)
end
def call(env)
prepare_session(env)
super(env)
end
# Add any required session cookies
def post_process(env, status, headers, body)
headers ||= {}
status, headers, body = commit_session(env, status, headers, body)
[status, headers, body]
end
def generate_sid
exists = true
sid = ''
while exists do
sid = super
# Ensure the key doesn't already exist
memcache_connect
response = Memcached.get(key: sid)
if response[:status] == Memcached::Errors::KEY_NOT_FOUND
exists = false
end
end
sid
end
def get_session(env, sid)
session = nil
memcache_connect(env)
if sid
response = Memcached.get(key: sid)
if response[:status] == Memcached::Errors::NO_ERROR
session = unmarshal(response[:value])
else
env.logger.info("*********************************************************")
env.logger.info("Error getting session: '#{response.inspect}'")
end
end
if !session
sid ||= generate_sid
session = {}
response = Memcached.set(key: sid, value: session)
unless response[:status] == Memcached::Errors::NO_ERROR
env.logger.info("*********************************************************")
env.logger.info("Error setting up new session: '#{response.inspect}'")
end
end
[sid, session]
end
def set_session(env, sid, new_session, options)
memcache_connect(env)
set_with = {
key: sid,
value: marshal(new_session)
}
expiry = options[:expire_after]
set_with[:expiration] = expiry + 1 unless expiry.nil?
response = Memcached.set(set_with)
if response[:status] == Memcached::Errors::NO_ERROR
sid
else
env.logger.info("*********************************************************")
env.logger.info("Error setting session: '#{response.inspect}'")
nil
end
end
def destroy_session(env, sid, options)
memcache_connect(env)
Memcached.delete(key: sid)
generate_sid unless options[:drop]
end
private
def memcache_connect(env = nil)
if !Memcached.usable?
servers = @default_options[:memcache_server]
servers = [servers] unless servers.is_a?(Array)
if env
env.logger.info("--------------------------------------------------------")
env.logger.info("Connecting to memcache server: #{servers}")
env.logger.info("--------------------------------------------------------")
end
Memcached.connect(servers)
end
end
def marshal(value)
Marshal.dump(value)
end
def unmarshal(value)
return value if value.nil?
Marshal.load(value)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment