Skip to content

fix: base64 body encoding and client close in cache layer - #41

Open
emiliano-go wants to merge 2 commits into
redis:mainfrom
emiliano-go:fix/cache-audit-findings
Open

emiliano-go wants to merge 2 commits into
redis:mainfrom
emiliano-go:fix/cache-audit-findings

Conversation

@emiliano-go

@emiliano-go emiliano-go commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes two cache layer issues: lossy binary body encoding and connection leak on shutdown.

Changes

Binary-safe body encoding

_write_cache_entry stored response bodies using decode(errors="replace"). This silently corrupts binary responses (images, protobuf, msgpack). The replacement character makes round-trip lossy.

Now uses base64 encoding with an "encoding" field in the cache entry. The read path checks for this field. Entries without it use the legacy str/encode path for backward compatibility.

Close client on pool state clear

_PoolState.clear() set _async_client = None without calling aclose(). This leaks the connection pool on shutdown.

Now clear() is async and calls aclose() before resetting state. The lifespan handler awaits it.

Files changed

  • src/redis_fastapi/cache.py: base64 encode body in write path, decode in read path based on encoding field
  • src/redis_fastapi/deps.py: make _PoolState.clear() async, call aclose()
  • src/redis_fastapi/lifespan.py: await ps.clear()
  • tests/unit/test_adversarial.py: 3 new tests, update existing _PoolState test to async

Test results

nox passes across Python 3.10-3.14. 407 tests, 93.42% coverage.

Related

- M1: Use base64 encoding for response body in cache entries instead of
  lossy decode(errors='replace'), with backward-compatible read path
- L5: Make _PoolState.clear() async and close the AsyncRedis client
  before resetting state to prevent connection leaks
- H4: Widen except clause from (json.JSONDecodeError, KeyError) to
  Exception in cache-hit path
- Add tests for base64 round-trip, pool client close, and update
  existing _PoolState test to async
@codecov-commenter

codecov-commenter commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.50000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 96.75%. Comparing base (06005dd) to head (4bf04d9).

Files with missing lines Patch % Lines
src/redis_fastapi/cache.py 75.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #41      +/-   ##
==========================================
- Coverage   96.81%   96.75%   -0.07%     
==========================================
  Files          12       12              
  Lines        1257     1262       +5     
==========================================
+ Hits         1217     1221       +4     
- Misses         40       41       +1     
Flag Coverage Δ
integration 77.89% <87.50%> (+<0.01%) ⬆️
unit 93.42% <87.50%> (-0.06%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

- Add test_build_hit_response_decodes_base64_body to directly exercise
  the base64 decode path in _build_hit_response (line 313)
- Add test_build_hit_response_304_not_modified to cover the 304 path
- Resolves codecov missing coverage on PR redis#41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants