From 9bf94f677d8e58f6c3cd089bb62d37e3687d8567 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Thu, 15 Nov 2012 02:18:53 +0100 Subject: [PATCH] [IMP] http session cleanup with gc bzr revid: al@openerp.com-20121115011853-238vzfca9ssbiyi7 --- addons/web/http.py | 53 ++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/addons/web/http.py b/addons/web/http.py index 309bcb81135..d702a5e5985 100644 --- a/addons/web/http.py +++ b/addons/web/http.py @@ -11,6 +11,7 @@ import logging import mimetypes import os import pprint +import random import sys import tempfile import threading @@ -357,26 +358,13 @@ class Controller(object): #---------------------------------------------------------- # Session context manager #---------------------------------------------------------- -STORES = {} - @contextlib.contextmanager -def session_context(request, storage_path, session_cookie='httpsessionid'): - session_store, session_lock = STORES.get(storage_path, (None, None)) - if not session_store: - session_store = werkzeug.contrib.sessions.FilesystemSessionStore( storage_path) - session_lock = threading.Lock() - STORES[storage_path] = session_store, session_lock - - sid = request.cookies.get(session_cookie) - if not sid: - sid = request.args.get('sid') - +def session_context(request, session_store, session_lock, sid): with session_lock: if sid: request.session = session_store.get(sid) else: request.session = session_store.new() - try: yield request.session finally: @@ -428,6 +416,18 @@ def session_context(request, storage_path, session_cookie='httpsessionid'): session_store.save(request.session) +def session_gc(session_store): + if random.random() < 0.001: + # we keep session one week + last_week = time.time() - 60*60*24*7 + for fname in os.listdir(session_store.path): + path = os.path.join(session_store.path, fname) + try: + if os.path.getmtime(path) < last_week: + os.unlink(path) + except OSError: + pass + #---------------------------------------------------------- # WSGI Application #---------------------------------------------------------- @@ -462,22 +462,23 @@ class Root(object): """Root WSGI application for the OpenERP Web Client. """ def __init__(self): - self.httpsession_cookie = 'httpsessionid' self.addons = {} static_dirs = self._load_addons() app = werkzeug.wsgi.SharedDataMiddleware( self.dispatch, static_dirs) self.dispatch = DisableCacheMiddleware(app) + # Setup http sessions try: username = getpass.getuser() except Exception: username = "unknown" - self.session_storage = os.path.join(tempfile.gettempdir(), "oe-sessions-" + username) - - if not os.path.exists(self.session_storage): - os.mkdir(self.session_storage, 0700) - _logger.debug('HTTP sessions stored in: %s', self.session_storage) + path = os.path.join(tempfile.gettempdir(), "oe-sessions-" + username) + if not os.path.exists(path): + os.mkdir(path, 0700) + self.session_store = werkzeug.contrib.sessions.FilesystemSessionStore(path) + self.session_lock = threading.Lock() + _logger.debug('HTTP sessions stored in: %s', path) def __call__(self, environ, start_response): """ Handle a WSGI request @@ -500,8 +501,14 @@ class Root(object): if not handler: response = werkzeug.exceptions.NotFound() else: - with session_context(request, self.session_storage, self.httpsession_cookie) as session: - result = handler( request) + sid = request.cookies.get('sid') + if not sid: + sid = request.args.get('sid') + + session_gc(self.session_store) + + with session_context(request, self.session_store, self.session_lock, sid) as session: + result = handler(request) if isinstance(result, basestring): headers=[('Content-Type', 'text/html; charset=utf-8'), ('Content-Length', len(result))] @@ -510,7 +517,7 @@ class Root(object): response = result if hasattr(response, 'set_cookie'): - response.set_cookie(self.httpsession_cookie, session.sid) + response.set_cookie('sid', session.sid) return response(environ, start_response)