|
6 | 6 | logger = logging.getLogger(__name__) |
7 | 7 |
|
8 | 8 | _REDIS_SCHEMES = frozenset({"redis", "rediss"}) |
| 9 | +_REDIS_UNIX_SCHEMES = frozenset({"redis+unix", "valkey+unix"}) |
| 10 | +_SHARED_SESSION_SCHEMES = _REDIS_SCHEMES | _REDIS_UNIX_SCHEMES |
| 11 | + |
| 12 | + |
| 13 | +def shared_session_store_supported(storage_uri): |
| 14 | + """Return True when the URI can back sessions across Gunicorn workers.""" |
| 15 | + return urlparse(storage_uri).scheme in _SHARED_SESSION_SCHEMES |
| 16 | + |
| 17 | + |
| 18 | +def _normalize_redis_url(storage_uri): |
| 19 | + """Match limits' redis+unix handling so redis.from_url accepts the URI.""" |
| 20 | + scheme = urlparse(storage_uri).scheme |
| 21 | + if scheme in _REDIS_UNIX_SCHEMES: |
| 22 | + prefix = scheme.split("+", 1)[0] |
| 23 | + return storage_uri.replace(f"{prefix}+unix", "unix", 1) |
| 24 | + return storage_uri |
9 | 25 | _REVOKE_SESSION_SCRIPT = """ |
10 | 26 | local active = redis.call("GET", KEYS[1]) |
11 | 27 | if active == ARGV[1] then |
@@ -67,7 +83,7 @@ def __init__(self, storage_uri): |
67 | 83 |
|
68 | 84 | self._redis_error = redis.exceptions.RedisError |
69 | 85 | self._client = redis.from_url( |
70 | | - storage_uri, |
| 86 | + _normalize_redis_url(storage_uri), |
71 | 87 | socket_timeout=2, |
72 | 88 | socket_connect_timeout=2, |
73 | 89 | ) |
@@ -141,6 +157,6 @@ def revoke(self, username, token): |
141 | 157 |
|
142 | 158 | def create_session_store(storage_uri): |
143 | 159 | scheme = urlparse(storage_uri).scheme |
144 | | - if scheme in _REDIS_SCHEMES: |
| 160 | + if scheme in _SHARED_SESSION_SCHEMES: |
145 | 161 | return RedisSessionStore(storage_uri) |
146 | 162 | return MemorySessionStore() |
0 commit comments