Files
odoo_source/odoo/addons/test_http/utils.py
T
Julien Castiaux 04e972660b [IMP] core: don't save visitor default session
Every request comes with a session, a dictionary that is persisted on
the filesystem and that saves various information such as the user
cart on the ecommerce.

When a user simply visits the website, a default session is created and
saved on disk, this bloats the filestore with many sessions. Creating
the session on-the-fly is cheaper than loading it from the filesystem.
With this work the default session is not saved on disk anymore unless
explicitly asked via `session.touch()`.

An exception to the statement "creating the session on-the-fly is
cheaper" is geoip, the ip geolocalization is not cheap. In this work,
geoip have been moved from http_routing/request.session.geoip to a
lazy property core/request.geoip. When requested the info is persisted
on the session. Like other keys from the default session, geoip will not
be persisted unless there is non-default stuff in the session.

Because the CSRF-TOKEN is based on the session-id, it is important the
session-id stays the same across multiples requests even when the
session is not persisted on disk. Even when a session is not persisted
on disk, the session-id cookie is still set so that the next session
created on-the-fly uses the same session-id.

Technical note regarding the session, it has been decided to drop the
session-snapshot protocol and to reintroduce a "modified" flag. It has
been decided not to use werkzeug's session (which natively comes with a
"modified" flag) and to keep our own session object. We decided to
extend MutableMapping instead of dict; using MutableMapping we only
have to override __setitem__ and __detitem__; using dict we would had to
override update()/pop()/... too.

Task: 2789035
Part-of: odoo/odoo#86015
2022-04-05 14:13:54 +02:00

75 lines
1.9 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from html.parser import HTMLParser
from odoo.http import FilesystemSessionStore
from odoo.tools._vendor.sessions import SessionStore
class MemoryGeoipResolver:
def resolve(self, ip):
return {}
class MemorySessionStore(SessionStore):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.store = {}
def get(self, sid):
session = self.store.get(sid)
if not session:
session = self.new()
return session
def save(self, session):
self.store[session.sid] = session
def delete(self, session):
self.store.pop(session.sid, None)
def rotate(self, session, env):
FilesystemSessionStore.rotate(self, session, env)
def vacuum(self):
return
# pylint: disable=W0223(abstract-method)
class HtmlTokenizer(HTMLParser):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.tokens = []
@classmethod
def _attrs_to_str(cls, attrs):
out = []
for key, value in attrs:
out.append(f"{key}={value!r}" if value else key)
return " ".join(out)
def handle_starttag(self, tag, attrs):
self.tokens.append(f"<{tag} {self._attrs_to_str(attrs)}>")
def handle_endtag(self, tag):
self.tokens.append(f"</{tag}>")
def handle_startendtag(self, tag, attrs):
# HTML5 <img> instead of XHTML <img/>
self.handle_starttag(tag, attrs)
def handle_data(self, data):
data = data.strip()
if data:
self.tokens.append(data)
@classmethod
def tokenize(cls, source_str):
"""
Parse the source html into a list of tokens. Only tags and
tags data are conserved, other elements such as comments are
discarded.
"""
tokenizer = cls()
tokenizer.feed(source_str)
return tokenizer.tokens