Skip to content

Commit

Permalink
Update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-oleshkevich authored Apr 16, 2024
1 parent af1c557 commit 2793105
Showing 1 changed file with 36 additions and 36 deletions.
72 changes: 36 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ Use `redis` extra for [Redis support](#redis).

## Quick start

See example application in [`examples/`](examples) directory of this repository.
See the example application in [`examples/`](examples) directory of this repository.

## Usage

1. Add `starsessions.SessionMiddleware` to your application to enable session support,
2. Configure session store and pass it to the middleware,
3. Load session in your view/middleware by calling `load_session(connection)` utility.
2. Configure the session store and pass it to the middleware,
3. Load the session in your view/middleware by calling `load_session(connection)` utility.

```python
from starlette.applications import Starlette
Expand Down Expand Up @@ -89,19 +89,19 @@ async def index_view(request):
request.session['key'] = 'value'
```

However, if you try to access uninitialized session, `SessionNotLoaded` exception will be raised.
However, if you try to access an uninitialized session, `SessionNotLoaded` exception will be raised.

```python
async def index_view(request):
request.session['key'] = 'value' # raises SessionNotLoaded
```

You can automatically load session by using `SessionAutoloadMiddleware` middleware.
You can automatically load a session by using `SessionAutoloadMiddleware` middleware.

### Session autoload

For performance reasons session is not autoloaded by default. Sometimes it is annoying to call `load_session` too often.
We provide `SessionAutoloadMiddleware` to reduce amount of boilerplate code by autoloading session for you.
For performance reasons, the session is not autoloaded by default. Sometimes it is annoying to call `load_session` too often.
We provide `SessionAutoloadMiddleware` class to reduce the boilerplate code by autoloading the session for you.

There are two options: always autoload or autoload for specific paths only.
Here are examples:
Expand Down Expand Up @@ -140,17 +140,17 @@ middleware = [

### Rolling sessions

The default behavior of `SessionMiddleware` is to expire cookie after `lifetime` seconds after it was set.
For example, if you create a session with `lifetime=3600` then the session will be terminated exactly in 3600 seconds.
Sometimes this may not be what you need, so we provide alternate expiration strategy - rolling sessions.
The default behavior of `SessionMiddleware` is to expire the cookie after `lifetime` seconds after it was set.
For example, if you create a session with `lifetime=3600`, the session will be terminated exactly in 3600 seconds.
Sometimes this may not be what you need, so we provide an alternate expiration strategy - rolling sessions.

When rolling sessions in use, the cookie expiration time will be extended by `lifetime` value on every response.
Let's see how it works on example. First, on the first response you create a new session with `lifetime=3600`,
then user does another request and session gets extended by another 3600 seconds and so on.
This approach is useful when you want to have short-timed sessions but don't want them to interrupt in the middle of
user's operation. With rolling strategy, session cookie will be expired only after some period of user's inactivity.
When rolling sessions are activated, the cookie expiration time will be extended by `lifetime` value on every response.
Let's see how it works for example. First, on the first response you create a new session with `lifetime=3600`,
then the user does another request, and the session gets extended by another 3600 seconds, and so on.
This approach is useful when you want to use short-timed sessions but don't want them to interrupt in the middle of
the user's operation. With the rolling strategy, a session cookie will expire only after some period of the user's inactivity.

To enable rolling strategy set `rolling=True`.
To enable the rolling strategy set `rolling=True`.

```python
from starlette.middleware import Middleware
Expand All @@ -161,13 +161,13 @@ middleware = [
]
```

The snippet above demonstrates an example setup where session will be dropped after 300 seconds (5 minutes) of
The snippet above demonstrates an example setup where the session will be dropped after 300 seconds (5 minutes) of
inactivity, but will be automatically extended by another 5 minutes while the user is online.

### Cookie path

You can pass `cookie_path` argument to bind session cookie to specific URLs. For example, to activate session cookie
only for admin area, use `cookie_path="/admin"` middleware argument.
You can pass `cookie_path` argument to bind the session cookies to specific URLs. For example, to activate a session cookie
only for the admin area, use `cookie_path="/admin"` middleware argument.

```python
from starlette.middleware import Middleware
Expand All @@ -178,7 +178,7 @@ middleware = [
]
```

All other URLs not matching value of `cookie_path` will not receive cookie thus session will be unavailable.
All other URLs not matching the value of `cookie_path` will not receive cookies thus session will be unavailable.

### Cookie domain

Expand All @@ -193,13 +193,13 @@ middleware = [
]
```

> Note, this makes session cookie available for subdomains too.
> Note, this makes session cookies available for subdomains too.
> For example, when you set `cookie_domain=example.com` then session cookie will be available on subdomains
> like `app.example.com`.
### Session-only cookies

If you want session cookie to automatically remove from tbe browser when tab closes then set `lifetime` to `0`.
If you want the session cookie to be automatically removed from the browser when the tab closes set `lifetime` to `0`.
> Note, this depends on browser implementation!
```python
Expand All @@ -217,7 +217,7 @@ middleware = [

Class: `starsessions.InMemoryStore`

Simply stores data in memory. The data is cleared after server restart. Mostly for use with unit tests.
Simply stores data in memory. The data is cleared after the server restart. Mostly for use with unit tests.

### CookieStore

Expand All @@ -229,7 +229,7 @@ Stores session data in a signed cookie on the client.

Class: `starsessions.stores.redis.RedisStore`

Stores session data in a Redis server. The store accepts either connection URL or an instance of `Redis`.
Stores session data in a Redis server. The store accepts either a connection URL or an instance of `Redis`.

> Requires [redis-py](https://github.com/redis/redis-py),
> use `pip install starsessions[redis]` or `poetry add starsessions[redis]`
Expand Down Expand Up @@ -272,7 +272,7 @@ store = RedisStore(url='redis://localhost', prefix=make_prefix)
#### Key expiration

The library automatically manages key expiration, usually you have nothing to do with it.
But for cases when `lifetime=0` we don't know when the session will over, and we have to heuristically calculate TTL
But for cases when `lifetime=0` we don't know when the session will be over, and we have to heuristically calculate TTL,
otherwise the data will remain in Redis forever. At this moment, we just set 30 days TTL. You can change it by
setting `gc_ttl` value on the store.

Expand All @@ -287,7 +287,7 @@ store = RedisStore(url='redis://localhost', gc_ttl=3600) # max 1 hour
Creating new stores is quite simple. All you need is to extend `starsessions.SessionStore`
class and implement abstract methods.

Here is an example of how we can create a memory-based session store. Note, it is important that `write` method
Here is an example of how we can create a memory-based session store. Note, that it is important that `write` method
returns session ID as a string value.

```python
Expand All @@ -296,18 +296,18 @@ from typing import Dict
from starsessions import SessionStore


# instance of class which manages session persistence
# instance of class that manages session persistence

class InMemoryStore(SessionStore):
def __init__(self):
self._storage = {}

async def read(self, session_id: str, lifetime: int) -> Dict:
async def read(self, session_id: str, lifetime: int) -> bytes:
""" Read session data from a data source using session_id. """
return self._storage.get(session_id, {})

async def write(self, session_id: str, data: Dict, lifetime: int, ttl: int) -> str:
""" Write session data into data source and return session id. """
async def write(self, session_id: str, data: bytes, lifetime: int, ttl: int) -> str:
""" Write session data into the data source and return session ID. """
self._storage[session_id] = data
return session_id

Expand All @@ -322,11 +322,11 @@ class InMemoryStore(SessionStore):
### lifetime and ttl

The `write` accepts two special arguments: `lifetime` and `ttl`.
The difference is that `lifetime` is a total session duration (set by the middleware)
and `ttl` is a remaining session time. After `ttl` seconds the data can be safely deleted from the storage.
The difference is that `lifetime` is the total session duration (set by the middleware)
and `ttl` is the remaining session time. After `ttl` seconds the data can be safely deleted from the storage.

> Your custom backend has to correctly handle setups when `lifetime = 0`.
In such cases you don't have exact expiration value, and you have to find a way how to extend session TTL at the storage
> Your custom backend has to correctly handle cases when `lifetime = 0`.
In such cases, you don't have an exact expiration value, and you would have to find a way to extend session TTL on the storage
side, if any.

## Serializers
Expand Down Expand Up @@ -359,11 +359,11 @@ middleware = [

## Session termination

The middleware will remove session data and cookie if session has no data. Use `request.session.clear` to empty data.
The middleware will remove session data and cookies if the session has no data. Use `request.session.clear` to empty data.

## Regenerating session ID

Sometimes you need a new session ID to avoid session fixation attacks (for example, after successful signs in).
Sometimes you need a new session ID to avoid session fixation attacks (for example, after successful signs-in).
For that, use `starsessions.session.regenerate_session_id(connection)` utility.

```python
Expand Down

0 comments on commit 2793105

Please sign in to comment.