Skip to content

Issue with the SESSION_REDIS config option #8696

@mutantsan

Description

@mutantsan

In our documentation we state, that the SESSION_TYPE could be redis.

We also use the SESSION_REDIS config option, without mentioning it. But we're using it wrong. According to the code, we will pass the string if specified, instead of a Redis class instance.

class CKANRedisSessionInterface(RedisSessionInterface):
    """Flask-Session redis-based sessions with CKAN's Redis connection.

    Parent class connects to Redis instance running on localhost:6379. This
    class initializes session with the connection to the Redis instance
    configured by `ckan.redis.url` option.

    """

    def __init__(self, app: CKANApp):
        app.config.setdefault("SESSION_REDIS", connect_to_redis())
        return super().__init__(
            app,
            app.config["SESSION_REDIS"], <---------------
            app.config["SESSION_KEY_PREFIX"],
            app.config["SESSION_USE_SIGNER"],
            app.config["SESSION_PERMANENT"]
        )

Steps to reproduce

Set the SESSION_TYPE to redis and SESSION_REDIS to some URL. You'll see the warning RuntimeWarning: No valid Redis instance provided, attempting to create a new instance on localhost with default settings.

If you have a running redis on localhost with a default port, Flask will automatically connect to it. Otherwise, there will be a connection error.

Expected behavior

We have two options:

  1. Tell users we will use the ckan.redis.url config option to connect to redis for a Flask session. And do not use the SESSION_REDIS in code.
  2. Allow the use of a different Redis connection for the session. In this case, we will need to do something like this:
    Replace this:
app.config.setdefault("SESSION_REDIS", connect_to_redis())

With something like this:

app.config["SESSION_REDIS"] = connect_to_redis(app.config.get("SESSION_REDIS"))

And rewrite the connect_to_redis function like that:

def connect_to_redis(url: str | None = None) -> Redis:
    '''
    (Lazily) connect to Redis.

    The connection is set up but not actually established. The latter
    happens automatically once the connection is used.

    :param url: The URL of the Redis instance to connect to.
        If not provided, the URL will be read from the ``ckan.redis.url``
        configuration option.
    :type url: str | None

    :returns: A lazy Redis connection.
    :rtype: ``redis.Redis``

    .. seealso:: :py:func:`is_redis_available`
    '''
    global _connection_pool
    if _connection_pool is None:
        url = url or config.get('ckan.redis.url')
        log.debug(u'Connecting to Redis at {}'.format(url))
        _connection_pool = ConnectionPool.from_url(url)
    return Redis(connection_pool=_connection_pool)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions