Created
January 30, 2012 21:45
-
-
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]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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