{"id":16853374,"url":"https://github.com/karpetrosyan/hishel","last_synced_at":"2026-02-05T17:01:26.979Z","repository":{"id":181403566,"uuid":"666701506","full_name":"karpetrosyan/hishel","owner":"karpetrosyan","description":" Elegant HTTP Caching for Python","archived":false,"fork":false,"pushed_at":"2026-01-10T12:41:14.000Z","size":4925,"stargazers_count":348,"open_issues_count":20,"forks_count":42,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-01-11T03:52:35.555Z","etag":null,"topics":["caching","http","http-cache","httpcore-cache","httpcore-caching","httpx-cache","httpx-caching","python","web","web-cache","web-caching"],"latest_commit_sha":null,"homepage":"https://hishel.com/dev","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/karpetrosyan.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"docs/contributing.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-07-15T09:36:52.000Z","updated_at":"2026-01-08T23:54:33.000Z","dependencies_parsed_at":"2023-07-15T11:43:57.142Z","dependency_job_id":"7b110fc2-06b5-44c1-944b-33df63bf98a2","html_url":"https://github.com/karpetrosyan/hishel","commit_stats":{"total_commits":331,"total_committers":19,"mean_commits":17.42105263157895,"dds":0.3927492447129909,"last_synced_commit":"6047a6a8e65b067fdeb824fd29fb04447cb3715a"},"previous_names":["karosis88/hishel"],"tags_count":54,"template":false,"template_full_name":null,"purl":"pkg:github/karpetrosyan/hishel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karpetrosyan%2Fhishel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karpetrosyan%2Fhishel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karpetrosyan%2Fhishel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karpetrosyan%2Fhishel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/karpetrosyan","download_url":"https://codeload.github.com/karpetrosyan/hishel/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karpetrosyan%2Fhishel/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29126040,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T14:05:12.718Z","status":"ssl_error","status_checked_at":"2026-02-05T14:03:53.078Z","response_time":65,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["caching","http","http-cache","httpcore-cache","httpcore-caching","httpx-cache","httpx-caching","python","web","web-cache","web-caching"],"created_at":"2024-10-13T13:51:39.150Z","updated_at":"2026-02-05T17:01:26.971Z","avatar_url":"https://github.com/karpetrosyan.png","language":"Python","funding_links":["https://buymeacoffee.com/karpetrosyan"],"categories":["Python"],"sub_categories":[],"readme":"\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"Hishel Logo\" width=\"350\" src=\"https://raw.githubusercontent.com/karpetrosyan/hishel/master/docs/static/Shelkopryad_350x250_yellow.png#gh-dark-mode-only\"\u003e\n  \u003cimg alt=\"Hishel Logo\" width=\"350\" src=\"https://raw.githubusercontent.com/karpetrosyan/hishel/master/docs/static/Shelkopryad_350x250_black.png#gh-light-mode-only\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eHishel\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eElegant HTTP Caching for Python\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://pypi.org/project/hishel\"\u003e\n    \u003cimg src=\"https://img.shields.io/pypi/v/hishel.svg\" alt=\"PyPI version\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://pypi.org/project/hishel\"\u003e\n    \u003cimg src=\"https://img.shields.io/pypi/pyversions/hishel.svg\" alt=\"Python versions\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/karpetrosyan/hishel/blob/master/LICENSE\"\u003e\n    \u003cimg src=\"https://img.shields.io/pypi/l/hishel\" alt=\"License\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://coveralls.io/github/karpetrosyan/hishel\"\u003e\n    \u003cimg src=\"https://img.shields.io/coverallsCoverage/github/karpetrosyan/hishel\" alt=\"Coverage\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://static.pepy.tech/badge/hishel/month\"\u003e\n    \u003cimg src=\"https://static.pepy.tech/badge/hishel/month\" alt=\"Downloads\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n**Hishel** (հիշել, *to remember* in Armenian) is a modern HTTP caching library for Python that implements [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111.html) specifications. It provides seamless caching integration for popular HTTP clients with minimal code changes.\n\n## ✨ Features\n\n- 🎯 **RFC 9111 Compliant** - Fully compliant with the latest HTTP caching specification\n- 🔌 **Easy Integration** - Drop-in support for HTTPX, Requests, ASGI, FastAPI, and BlackSheep\n- 💾 **Flexible Storage** - SQLite backend with more coming soon\n- ⚡ **High Performance** - Efficient caching with minimal overhead\n- 🔄 **Async \u0026 Sync** - Full support for both synchronous and asynchronous workflows\n- 🎨 **Type Safe** - Fully typed with comprehensive type hints\n- 🧪 **Well Tested** - Extensive test coverage and battle-tested\n- 🎛️ **Configurable** - Fine-grained control over caching behavior with flexible policies\n- 💨 **Memory Efficient** - Streaming support prevents loading large payloads into memory\n- 🌐 **Universal** - Works with any ASGI application (Starlette, Litestar, BlackSheep, etc.)\n- 🎯 **GraphQL Support** - Cache GraphQL queries with body-sensitive content caching\n\n## 📦 Installation\n\n```bash\npip install hishel\n```\n\n### Optional Dependencies\n\nInstall with specific integration support:\n\n```bash\npip install hishel[httpx]      # For HTTPX support\npip install hishel[requests]   # For Requests support\npip install hishel[fastapi]    # For FastAPI support (includes ASGI)\n```\n\nOr install multiple:\n\n```bash\npip install hishel[httpx,requests,fastapi]\n```\n\n\u003e [!NOTE]\n\u003e ASGI middleware has no extra dependencies - it's included in the base installation.\n \n## 🚀 Quick Start\n\n### With HTTPX\n\n**Synchronous:**\n\n```python\nfrom hishel.httpx import SyncCacheClient\n\nclient = SyncCacheClient()\n\n# First request - fetches from origin\nresponse = client.get(\"https://api.example.com/data\")\nprint(response.extensions[\"hishel_from_cache\"])  # False\n\n# Second request - served from cache\nresponse = client.get(\"https://api.example.com/data\")\nprint(response.extensions[\"hishel_from_cache\"])  # True\n```\n\n**Asynchronous:**\n\n```python\nfrom hishel.httpx import AsyncCacheClient\n\nasync with AsyncCacheClient() as client:\n    # First request - fetches from origin\n    response = await client.get(\"https://api.example.com/data\")\n    print(response.extensions[\"hishel_from_cache\"])  # False\n    \n    # Second request - served from cache\n    response = await client.get(\"https://api.example.com/data\")\n    print(response.extensions[\"hishel_from_cache\"])  # True\n```\n\n### With Requests\n\n```python\nimport requests\nfrom hishel.requests import CacheAdapter\n\nsession = requests.Session()\nsession.mount(\"https://\", CacheAdapter())\nsession.mount(\"http://\", CacheAdapter())\n\n# First request - fetches from origin\nresponse = session.get(\"https://api.example.com/data\")\n\n# Second request - served from cache\nresponse = session.get(\"https://api.example.com/data\")\nprint(response.headers.get(\"X-Hishel-From-Cache\"))  # \"True\"\n```\n\n### With ASGI Applications\n\nAdd caching middleware to any ASGI application:\n\n```python\nfrom hishel.asgi import ASGICacheMiddleware\n\n# Wrap your ASGI app\napp = ASGICacheMiddleware(app)\n\n# Or configure with options\nfrom hishel import AsyncSqliteStorage, CacheOptions, SpecificationPolicy\n\napp = ASGICacheMiddleware(\n    app,\n    storage=AsyncSqliteStorage(),\n    policy=SpecificationPolicy(\n      cache_options=CacheOptions(shared=True)\n    ),\n)\n```\n\n### With FastAPI\n\nAdd Cache-Control headers using the `cache()` dependency:\n\n```python\nfrom fastapi import FastAPI\nfrom hishel.fastapi import cache\n\napp = FastAPI()\n\n@app.get(\"/api/data\", dependencies=[cache(max_age=300, public=True)])\nasync def get_data():\n    # Cache-Control: public, max-age=300\n    return {\"data\": \"cached for 5 minutes\"}\n  \n# Optionally wrap with ASGI middleware for local caching according to specified rules\nfrom hishel.asgi import ASGICacheMiddleware\nfrom hishel import AsyncSqliteStorage\n\napp = ASGICacheMiddleware(app, storage=AsyncSqliteStorage())\n```\n\n### With BlackSheep\n\nUse BlackSheep's native `cache_control` decorator with Hishel's ASGI middleware:\n\n```python\nfrom blacksheep import Application, get\nfrom blacksheep.server.headers.cache import cache_control\n\napp = Application()\n\n@get(\"/api/data\")\n@cache_control(max_age=300, public=True)\nasync def get_data():\n    # Cache-Control: public, max-age=300\n    return {\"data\": \"cached for 5 minutes\"}\n```\n\n## 🎛️ Advanced Configuration\n\n### Caching Policies\n\nHishel supports two types of caching policies:\n\n**SpecificationPolicy** - RFC 9111 compliant HTTP caching (default):\n\n```python\nfrom hishel import CacheOptions, SpecificationPolicy\nfrom hishel.httpx import SyncCacheClient\n\nclient = SyncCacheClient(\n    policy=SpecificationPolicy(\n        cache_options=CacheOptions(\n            shared=False,                              # Use as private cache (browser-like)\n            supported_methods=[\"GET\", \"HEAD\", \"POST\"], # Cache GET, HEAD, and POST\n            allow_stale=True                           # Allow serving stale responses\n        )\n    )\n)\n```\n\n**FilterPolicy** - Custom filtering logic for fine-grained control:\n\n```python\nfrom hishel import FilterPolicy, BaseFilter, Request\nfrom hishel.httpx import AsyncCacheClient\n\nclass CacheOnlyAPIRequests(BaseFilter[Request]):\n    def needs_body(self) -\u003e bool:\n        return False\n    \n    def apply(self, item: Request, body: bytes | None) -\u003e bool:\n        return \"/api/\" in str(item.url)\n\nclient = AsyncCacheClient(\n    policy=FilterPolicy(\n        request_filters=[CacheOnlyAPIRequests()]\n    )\n)\n```\n\n[Learn more about policies →](https://hishel.com/dev/policies/)\n\n### Custom Storage Backend\n\n```python\nfrom hishel import SyncSqliteStorage\nfrom hishel.httpx import SyncCacheClient\n\nstorage = SyncSqliteStorage(\n    database_path=\"my_cache.db\",\n    default_ttl=7200.0,           # Cache entries expire after 2 hours\n    refresh_ttl_on_access=True    # Reset TTL when accessing cached entries\n)\n\nclient = SyncCacheClient(storage=storage)\n```\n\n### GraphQL and Body-Sensitive Caching\n\nCache GraphQL queries and other POST requests by including the request body in the cache key.\n\n**Using per-request header:**\n\n```python\nfrom hishel import FilterPolicy\nfrom hishel.httpx import SyncCacheClient\n\nclient = SyncCacheClient(\n    policy=FilterPolicy()\n)\n\n# Cache GraphQL queries - different queries get different cache entries\ngraphql_query = \"\"\"\n    query GetUser($id: ID!) {\n        user(id: $id) {\n            name\n            email\n        }\n    }\n\"\"\"\n\nresponse = client.post(\n    \"https://api.example.com/graphql\",\n    json={\"query\": graphql_query, \"variables\": {\"id\": \"123\"}},\n    headers={\"X-Hishel-Body-Key\": \"true\"}  # Enable body-based caching\n)\n\n# Different query will be cached separately\nresponse = client.post(\n    \"https://api.example.com/graphql\",\n    json={\"query\": graphql_query, \"variables\": {\"id\": \"456\"}},\n    headers={\"X-Hishel-Body-Key\": \"true\"}\n)\n```\n\n**Using global configuration:**\n\n```python\nfrom hishel.httpx import SyncCacheClient\nfrom hishel import FilterPolicy\n\n# Enable body-based caching for all requests\nclient = SyncCacheClient(policy=FilterPolicy(use_body_key=True))\n\n# All POST requests automatically include body in cache key\nresponse = client.post(\n    \"https://api.example.com/graphql\",\n    json={\"query\": graphql_query, \"variables\": {\"id\": \"123\"}}\n)\n```\n\n## 🏗️ Architecture\n\nHishel uses a **sans-I/O state machine** architecture that separates HTTP caching logic from I/O operations:\n\n- ✅ **Correct** - Fully RFC 9111 compliant\n- ✅ **Testable** - Easy to test without network dependencies\n- ✅ **Flexible** - Works with any HTTP client or server\n- ✅ **Type Safe** - Clear state transitions with full type hints\n\n## 🔮 Roadmap\n\nWe're actively working on:\n\n- 🎯 Performance optimizations\n- 🎯 More integrations\n- 🎯 Partial responses support\n\n## 📚 Documentation\n\nComprehensive documentation is available at [https://hishel.com/dev](https://hishel.com/dev)\n\n- [Getting Started](https://hishel.com)\n- [HTTPX Integration](https://hishel.com/dev/integrations/httpx)\n- [Requests Integration](https://hishel.com/dev/integrations/requests)\n- [ASGI Integration](https://hishel.com/dev/asgi)\n- [FastAPI Integration](https://hishel.com/dev/fastapi)\n- [BlackSheep Integration](https://hishel.com/dev/integrations/blacksheep)\n- [GraphQL Integration](https://hishel.com/dev/integrations/graphql)\n- [Storage Backends](https://hishel.com/dev/storages)\n- [Request/Response Metadata](https://hishel.com/dev/metadata)\n- [RFC 9111 Specification](https://hishel.com/dev/specification)\n\n## 🤝 Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.\n\nSee our [Contributing Guide](https://hishel.com/dev/contributing) for more details.\n\n## 📄 License\n\nThis project is licensed under the BSD-3-Clause License - see the [LICENSE](LICENSE) file for details.\n\n## 💖 Support\n\nIf you find Hishel useful, please consider:\n\n- ⭐ Starring the repository\n- 🐛 Reporting bugs and issues\n- 💡 Suggesting new features\n- 📖 Improving documentation\n- ☕ [Buying me a coffee](https://buymeacoffee.com/karpetrosyan)\n\n## 🙏 Acknowledgments\n\nHishel is inspired by and builds upon the excellent work in the Python HTTP ecosystem, particularly:\n\n- [HTTPX](https://github.com/encode/httpx) - A next-generation HTTP client for Python\n- [Requests](https://github.com/psf/requests) - The classic HTTP library for Python\n- [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111.html) - HTTP Caching specification\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eMade with ❤️ by \u003ca href=\"https://github.com/karpetrosyan\"\u003eKar Petrosyan\u003c/a\u003e\u003c/strong\u003e\n\u003c/p\u003e\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarpetrosyan%2Fhishel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkarpetrosyan%2Fhishel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarpetrosyan%2Fhishel/lists"}