All Projects → steinitzu → fastapi-etag

steinitzu / fastapi-etag

Licence: MIT license
Convenience library for working with etags in fastapi

Programming Languages

python
139335 projects - #7 most used programming language

Projects that are alternatives of or similar to fastapi-etag

fast-api-sqlalchemy-template
Dockerized web application on FastAPI, sqlalchemy1.4, PostgreSQL
Stars: ✭ 25 (+31.58%)
Mutual labels:  asyncio, fastapi
hypercorn-fastapi-docker
Docker image with Hypercorn for FastAPI apps in Python 3.7, 3.8, 3.9. Ready for HTTP2 and HTTPS
Stars: ✭ 18 (-5.26%)
Mutual labels:  asyncio, fastapi
fastapi-users
Ready-to-use and customizable users management for FastAPI
Stars: ✭ 1,920 (+10005.26%)
Mutual labels:  asyncio, fastapi
ultrafetch
Node-based fetch backed with an RFC-7234 compliant filesystem cache.
Stars: ✭ 30 (+57.89%)
Mutual labels:  etag, http-cache
asgi-caches
Server-side HTTP caching for ASGI applications, inspired by Django's cache framework
Stars: ✭ 18 (-5.26%)
Mutual labels:  caching, http-cache
fastapi-framework
A FastAPI Framework for things like Database, Redis, Logging, JWT Authentication, Rate Limits and Sessions
Stars: ✭ 26 (+36.84%)
Mutual labels:  asyncio, fastapi
fastapi-sqlalchemy-1.4-async
https://rogulski.it/blog/sqlalchemy-14-async-orm-with-fastapi/
Stars: ✭ 17 (-10.53%)
Mutual labels:  asyncio, fastapi
fastapi-azure-auth
Easy and secure implementation of Azure AD for your FastAPI APIs 🔒 B2C, single- and multi-tenant support.
Stars: ✭ 174 (+815.79%)
Mutual labels:  asyncio, fastapi
cashews
Cache with async power
Stars: ✭ 204 (+973.68%)
Mutual labels:  caching, fastapi
Nuster
A high performance HTTP proxy cache server and RESTful NoSQL cache server based on HAProxy
Stars: ✭ 1,825 (+9505.26%)
Mutual labels:  caching, http-cache
fastapi-boilerplate
FastAPI boilerplate for real world production
Stars: ✭ 145 (+663.16%)
Mutual labels:  asyncio, fastapi
HibiAPI
一个实现了多种常用站点的易用化API的程序 / A program that implements easy-to-use APIs for a variety of commonly used sites.
Stars: ✭ 427 (+2147.37%)
Mutual labels:  asyncio, fastapi
Fastapi
FastAPI framework, high performance, easy to learn, fast to code, ready for production
Stars: ✭ 39,588 (+208257.89%)
Mutual labels:  asyncio, fastapi
cachecontrol
Minimal HTTP cache management library in Scala
Stars: ✭ 13 (-31.58%)
Mutual labels:  caching, http-cache
timvt
PostGIS based Vector Tile server.
Stars: ✭ 113 (+494.74%)
Mutual labels:  asyncio, fastapi
aioredis-cluster
Redis Cluster support extension for aioredis
Stars: ✭ 21 (+10.53%)
Mutual labels:  asyncio
hook-slinger
A generic service to send, retry, and manage webhooks.
Stars: ✭ 88 (+363.16%)
Mutual labels:  fastapi
async armor
Graceful drop-in replacement for asyncio.shield
Stars: ✭ 15 (-21.05%)
Mutual labels:  asyncio
callosum
An RPC Transport Library for asyncio
Stars: ✭ 17 (-10.53%)
Mutual labels:  asyncio
fastapi-saas-base
Fast API SAAS Base App
Stars: ✭ 47 (+147.37%)
Mutual labels:  fastapi

fastapi-etag

Quickstart

Basic etag support for FastAPI, allowing you to benefit from conditional caching in web browsers and reverse-proxy caching layers.

This does not generate etags that are a hash of the response content, but instead lets you pass in a custom etag generating function per endpoint that is called before executing the route function.
This lets you bypass expensive API calls when client includes a matching etag in the If-None-Match header, in this case your endpoint is never called, instead returning a 304 response telling the client nothing has changed.

The etag logis is implemented with a fastapi dependency that you can add to your routes or entire routers.

Here's how you use it:

# app.py

from fastapi import FastAPI
from starlette.requests import Request
from fastapi_etag import Etag, add_exception_handler

app = FastAPI()
add_exception_handler(app)


async def get_hello_etag(request: Request):
    return "etagfor" + request.path_params["name"]


@app.get("/hello/{name}", dependencies=[Depends(Etag(get_hello_etag))])
async def hello(name: str):
    return {"hello": name}

Run this example with uvicorn: uvicorn --port 8090 app:app

Let's break it down:

add_exception_handler(app)

The dependency raises a special CacheHit exception to exit early when there's a an etag match, this adds a standard exception handler to the app to generate a correct 304 response from the exception.

async def get_hello_etag(request: Request):
    name = request.path_params.get("name")
    return f"etagfor{name}"

This is the function that generates the etag for your endpoint.
It can do anything you want, it could for example return a hash of a last modified timestamp in your database.
It can be either a normal function or an async function.
Only requirement is that it accepts one argument (request) and that it returns either a string (the etag) or None (in which case no etag header is added)

@app.get("/hello/{name}", dependencies=[Depends(Etag(get_hello_etag))])
def hello(name: str):
	...

The Etag dependency is called like any fastapi dependency. It always adds the etag returned by your etag gen function to the response.
If client passes a matching etag in the If-None-Match header, it will raise a CacheHit exception which triggers a 304 response before calling your endpoint.

Now try it with curl:

curl -i "http://localhost:8090/hello/bob"
HTTP/1.1 200 OK
date: Mon, 30 Dec 2019 21:55:43 GMT
server: uvicorn
content-length: 15
content-type: application/json
etag: W/"etagforbob"

{"hello":"bob"}

Etag header is added

Now including the etag in If-None-Match header (mimicking a web browser):

curl -i -X GET "http://localhost:8090/hello/bob" -H "If-None-Match: W/\"etagforbob\""
HTTP/1.1 304 Not Modified
date: Mon, 30 Dec 2019 21:57:37 GMT
server: uvicorn
etag: W/"etagforbob"

It now returns no content, only the 304 telling us nothing has changed.

Add response headers

If you want to add some extra response headers to the 304 and regular response, you can add the extra_headers argument with a dict of headers:

@app.get(
    "/hello/{name}",
    dependencies=[
        Depends(
            Etag(
                get_hello_etag,
                extra_headers={"Cache-Control": "public, max-age: 30"},
            )
        )
    ],
)
def hello(name: str):
	...

This will add the cache-control header on all responses from the endpoint.

Contributing

See CONTRIBUTING.md

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].