Remove itsdangerous dependency
Summary
I've always disliked installing itsdangerous dependency just for basic SessionMiddleware functionality. The itsdangerous has lots of features but the amount of functionality needed by starlette is minimal. I decided to prepare starlette-optimized TimestampSigner implementation that has several benefits:
- No dependency, better UX
- Simple, no-fuss implementation
- Uses SHA-256/128 HMAC instead of SHA-1 HMAC
- Smaller signed tokens
- Faster
Checklist
- [x] I understand that this PR may be closed in case there was no previous discussion. (This doesn't apply to typos!)
- [x] I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
- [x] I've updated the documentation accordingly.
I also prepared a small benchmark script:
uv run --with itsdangerous python benchmark_signing.py
Input: {'user_id': 12345, 'username': 'alice', 'roles': ['admin', 'user']}
itsdangerous:
eyJ1c2VyX2lkIjogMTIzNDUsICJ1c2VybmFtZSI6ICJhbGljZSIsICJyb2xlcyI6IFsiYWRtaW4iLCAidXNlciJdfQ==.aQroow.EK2o0veXJdxMfN724EJaqjwjsQo
starlette.signing:
eyJ1c2VyX2lkIjogMTIzNDUsICJ1c2VybmFtZSI6ICJhbGljZSIsICJyb2xlcyI6IFsiYWRtaW4iLCAidXNlciJdfQBpCuijLtC0_yYQrfToZiZsjFCBzA_
Size: 127b → 119b (6.3% smaller)
Sign: 4.26 μs → 2.58 μs (1.65x faster)
Unsign (valid): 6.61 μs → 3.98 μs (1.66x faster)
Unsign (invalid): 2.47 μs → 0.07 μs (33.60x faster)
This change will invalidate existing sessions. If it's a big enough issue, I can patch it to attempt the itsdangerous dependency import, and when successful, attempt itsdangerous unsign after starlette.signing failure. I don't know if that's worth the added complexity.
PS. The starlette.signing ending marker, in addition to speeding up pre-validation, can be used to easily support multiple token encoding versions if there's ever a need for it.