middleware.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import warnings
  2. try:
  3. from paste.registry import StackedObjectProxy
  4. beaker_session = StackedObjectProxy(name="Beaker Session")
  5. beaker_cache = StackedObjectProxy(name="Cache Manager")
  6. except:
  7. beaker_cache = None
  8. beaker_session = None
  9. from beaker.cache import CacheManager
  10. from beaker.session import Session, SessionObject
  11. from beaker.util import coerce_cache_params, coerce_session_params, \
  12. parse_cache_config_options
  13. class CacheMiddleware(object):
  14. cache = beaker_cache
  15. def __init__(self, app, config=None, environ_key='beaker.cache', **kwargs):
  16. """Initialize the Cache Middleware
  17. The Cache middleware will make a Cache instance available
  18. every request under the ``environ['beaker.cache']`` key by
  19. default. The location in environ can be changed by setting
  20. ``environ_key``.
  21. ``config``
  22. dict All settings should be prefixed by 'cache.'. This
  23. method of passing variables is intended for Paste and other
  24. setups that accumulate multiple component settings in a
  25. single dictionary. If config contains *no cache. prefixed
  26. args*, then *all* of the config options will be used to
  27. intialize the Cache objects.
  28. ``environ_key``
  29. Location where the Cache instance will keyed in the WSGI
  30. environ
  31. ``**kwargs``
  32. All keyword arguments are assumed to be cache settings and
  33. will override any settings found in ``config``
  34. """
  35. self.app = app
  36. config = config or {}
  37. self.options = {}
  38. # Update the options with the parsed config
  39. self.options.update(parse_cache_config_options(config))
  40. # Add any options from kwargs, but leave out the defaults this
  41. # time
  42. self.options.update(
  43. parse_cache_config_options(kwargs, include_defaults=False))
  44. # Assume all keys are intended for cache if none are prefixed with
  45. # 'cache.'
  46. if not self.options and config:
  47. self.options = config
  48. self.options.update(kwargs)
  49. self.cache_manager = CacheManager(**self.options)
  50. self.environ_key = environ_key
  51. def __call__(self, environ, start_response):
  52. if environ.get('paste.registry'):
  53. if environ['paste.registry'].reglist:
  54. environ['paste.registry'].register(self.cache,
  55. self.cache_manager)
  56. environ[self.environ_key] = self.cache_manager
  57. return self.app(environ, start_response)
  58. class SessionMiddleware(object):
  59. session = beaker_session
  60. def __init__(self, wrap_app, config=None, environ_key='beaker.session',
  61. **kwargs):
  62. """Initialize the Session Middleware
  63. The Session middleware will make a lazy session instance
  64. available every request under the ``environ['beaker.session']``
  65. key by default. The location in environ can be changed by
  66. setting ``environ_key``.
  67. ``config``
  68. dict All settings should be prefixed by 'session.'. This
  69. method of passing variables is intended for Paste and other
  70. setups that accumulate multiple component settings in a
  71. single dictionary. If config contains *no cache. prefixed
  72. args*, then *all* of the config options will be used to
  73. intialize the Cache objects.
  74. ``environ_key``
  75. Location where the Session instance will keyed in the WSGI
  76. environ
  77. ``**kwargs``
  78. All keyword arguments are assumed to be session settings and
  79. will override any settings found in ``config``
  80. """
  81. config = config or {}
  82. # Load up the default params
  83. self.options = dict(invalidate_corrupt=True, type=None,
  84. data_dir=None, key='beaker.session.id',
  85. timeout=None, secret=None, log_file=None)
  86. # Pull out any config args meant for beaker session. if there are any
  87. for dct in [config, kwargs]:
  88. for key, val in dct.iteritems():
  89. if key.startswith('beaker.session.'):
  90. self.options[key[15:]] = val
  91. if key.startswith('session.'):
  92. self.options[key[8:]] = val
  93. if key.startswith('session_'):
  94. warnings.warn('Session options should start with session. '
  95. 'instead of session_.', DeprecationWarning, 2)
  96. self.options[key[8:]] = val
  97. # Coerce and validate session params
  98. coerce_session_params(self.options)
  99. # Assume all keys are intended for cache if none are prefixed with
  100. # 'cache.'
  101. if not self.options and config:
  102. self.options = config
  103. self.options.update(kwargs)
  104. self.wrap_app = wrap_app
  105. self.environ_key = environ_key
  106. def __call__(self, environ, start_response):
  107. session = SessionObject(environ, **self.options)
  108. if environ.get('paste.registry'):
  109. if environ['paste.registry'].reglist:
  110. environ['paste.registry'].register(self.session, session)
  111. environ[self.environ_key] = session
  112. environ['beaker.get_session'] = self._get_session
  113. def session_start_response(status, headers, exc_info = None):
  114. if session.accessed():
  115. session.persist()
  116. if session.__dict__['_headers']['set_cookie']:
  117. cookie = session.__dict__['_headers']['cookie_out']
  118. if cookie:
  119. headers.append(('Set-cookie', cookie))
  120. return start_response(status, headers, exc_info)
  121. return self.wrap_app(environ, session_start_response)
  122. def _get_session(self):
  123. return Session({}, use_cookies=False, **self.options)
  124. def session_filter_factory(global_conf, **kwargs):
  125. def filter(app):
  126. return SessionMiddleware(app, global_conf, **kwargs)
  127. return filter
  128. def session_filter_app_factory(app, global_conf, **kwargs):
  129. return SessionMiddleware(app, global_conf, **kwargs)