require 'moneta' require 'rack/utils' module Rack # A Rack middleware that was made to reuse all moneta transformers # on the cookie hash. # # @example config.ru # # Add Rack::MonetaCookies somewhere in your rack stack # use Rack::MonetaCookies # # run lambda { |env| [200, {}, []] } # # But this doesn't do much # # @example config.ru # # Give it some options # use Rack::MonetaCookies, domain: 'example.com', path: '/path' # # @example config.ru # # Pass it a block like the one passed to Moneta.build # use Rack::MonetaCookies do # use :Transformer, key: :prefix, prefix: 'moneta.' # adapter :Cookie # end # # run lambda { |env| # req = Rack::Request.new(env) # req.cookies #=> is now a Moneta store! # env['rack.request.cookie_hash'] #=> is now a Moneta store! # req.cookies['key'] #=> retrieves 'moneta.key' # req.cookies['key'] = 'value' #=> sets 'moneta.key' # req.cookies.delete('key') #=> removes 'moneta.key' # [200, {}, []] # } # # @api public class MonetaCookies def initialize(app, options = {}, &block) @app, @pool = app, [] if block raise ArgumentError, 'Use either block or options' unless options.empty? @builder = Moneta::Builder.new(&block) else @builder = Moneta::Builder.new { adapter :Cookie, options } end end def call(env) stores = @pool.pop || @builder.build env['rack.moneta_cookies'] = env['rack.request.cookie_hash'] = stores.last env['rack.request.cookie_string'] = env['HTTP_COOKIE'] stores.first.reset(Rack::Utils.parse_query(env['HTTP_COOKIE'])) status, headers, body = @app.call(env) stores.first.cookies.each do |key, cookie| if cookie == nil Rack::Utils.delete_cookie_header!(headers, key) else Rack::Utils.set_cookie_header!(headers, key, cookie) end end @pool << stores [status, headers, body] end end end