api versioning for fastapi web applications

Overview

fastapi-versioning

api versioning for fastapi web applications

Installation

pip install fastapi-versioning

Examples

from fastapi import FastAPI
from fastapi_versioning import VersionedFastAPI, version

app = FastAPI(title="My App")


@app.get("/")
@version(1, 0)
def greet_with_hello():
    return "Hello"


@app.get("/")
@version(1, 1)
def greet_with_hi():
    return "Hi"


app = VersionedFastAPI(app)
)

this will generate two endpoints:

/v1_0/greet
/v1_1/greet

as well as:

/docs
/v1_0/docs
/v1_1/docs
/v1_0/openapi.json
/v1_1/openapi.json

Try it out:

pip install pipenv
pipenv install --dev
pipenv run uvicorn example.app:app

Usage without minor version

from fastapi import FastAPI
from fastapi_versioning import VersionedFastAPI, version

app = FastAPI(title='My App')

@app.get('/greet')
@version(1)
def greet():
  return 'Hello'

@app.get('/greet')
@version(2)
def greet():
  return 'Hi'

app = VersionedFastAPI(app,
    version_format='{major}',
    prefix_format='/v{major}')

this will generate two endpoints:

/v1/greet
/v2/greet

as well as:

/docs
/v1/docs
/v2/docs
/v1/openapi.json
/v2/openapi.json

Extra FastAPI constructor arguments

It's important to note that only the title from the original FastAPI will be provided to the VersionedAPI app. If you have any middleware, event handlers etc these arguments will also need to be provided to the VersionedAPI function call, as in the example below

from fastapi import FastAPI, Request
from fastapi_versioning import VersionedFastAPI, version
from starlette.middleware import Middleware
from starlette.middleware.sessions import SessionMiddleware

app = FastAPI(
    title='My App',
    description='Greet uses with a nice message',
    middleware=[
        Middleware(SessionMiddleware, secret_key='mysecretkey')
    ]
)

@app.get('/greet')
@version(1)
def greet(request: Request):
    request.session['last_version_used'] = 1
    return 'Hello'

@app.get('/greet')
@version(2)
def greet(request: Request):
    request.session['last_version_used'] = 2
    return 'Hi'

@app.get('/version')
def last_version(request: Request):
    return f'Your last greeting was sent from version {request.session["last_version_used"]}'

app = VersionedFastAPI(app,
    version_format='{major}',
    prefix_format='/v{major}',
    description='Greet users with a nice message',
    middleware=[
        Middleware(SessionMiddleware, secret_key='mysecretkey')
    ]
)
Comments
  • Replaced deprecated openapi_prefix for root_path.

    Replaced deprecated openapi_prefix for root_path.

    Fixes the following annoying warning:

    "openapi_prefix" has been deprecated in favor of "root_path", which follows more closely the ASGI standard, is simpler, and more automatic. Check the docs at https://fastapi.tiangolo.com/advanced/sub-applications/
    

    Fixes #13.

    opened by synchronizing 5
  • root_path is not propagated to versioned apps properly, breaking openapi docs

    root_path is not propagated to versioned apps properly, breaking openapi docs

    My app is behind some proxy so it's url is smth like http://abc.cd/some/path/v1_0/ to support it properly I'm adding root_path="/some/path", and in general everything is working ok as in most cases this param is just ignored, except openapidocs, where it's used to generate path to openapi.json:

    http://abc.cd/some/path/v1_0/docs

        const ui = SwaggerUIBundle({
            url: '/v1_0/openapi.json',
    

    should be:

        const ui = SwaggerUIBundle({
            url: '/some/path/v1_0/openapi.json',
    
    opened by kosz85 4
  • :sparkles: Reflect attributes in version decorator

    :sparkles: Reflect attributes in version decorator

    Rewriting the decorator using functools.wraps() allows for tab completion and correctly reflecting of attributes and signature of wrapped function.

    Closes #11.

    opened by HacKanCuBa 4
  • Support for a single method to handle multiple versions

    Support for a single method to handle multiple versions

    Currently, if we are to support multiple versions of an API with many endpoints, we need to duplicate each endpoint (even if logic does not change for every endpoint) in order to be backward compatible.

    An array of values could be passed to @version() to allow a single method to support multiple versions. Example:

    Current:

    def handle_home() -> str:
        return "You are home."
    
    @app.get("/home")
    @version(1, 0)
    def home() -> str:
        return handle_home()
    
    @app.get("/home")
    @version(1, 1)
    def home() -> str:
        return handle_home()
    
    @app.get("/home")
    @version(1, 2)
    def home() -> str:
        return handle_home()
    

    Suggested:

    @app.get("/home")
    @version([1, 0], [1, 1], [1, 2])
    def home() -> str:
        return "You are home"
    
    opened by c-tanner 3
  • Description from tags metadata not shown in OpenAPI docs

    Description from tags metadata not shown in OpenAPI docs

    First of all, thank you so much for this extension, saved us a lot of additional unnecessary work!

    Bug description Looks like description from tags metadata is not loaded/visible on OpenAPI docs, even if I pass it directly to VersionedFastAPI constructor. name is loaded, but description not. I haven't checked externalDocs attribute yet.

    To Reproduce Here is the part of the code from my main.py:

    tags_metadata = [
        {"name": "products", "description": "Operations with products and product types."},
        {"name": "cameras", "description": "Operations with cameras."}
    ]
    
    app = FastAPI(title="My App")
    
    app.include_router(product_router.router)
    app.include_router(camera_router.router)
    
    @app.get("/")
    @version(1, 0)
    def root():
        return {"message": "Hello World!"}
    
    app = VersionedFastAPI(app, openapi_tags=tags_metadata)
    

    ... and in the product_router.py, I have defined:

    router = APIRouter(prefix="/products", tags=["products"])
    

    ... and the same way in camera_router.py.

    Expected behavior How it should look like, is described here: FastAPI-Metadata. When I turn off fastapi-versioning, everything works like expected.

    Environment

    • Docker version: 19.03.13
    • FastAPI version: 0.62.0 (built with official FastAPI Docker image and manually updated fastapi)
    • fastapi-versioning version: 0.5.0

    Thanks!

    opened by Acerinth 3
  • feat: add customisable default versioning functionality

    feat: add customisable default versioning functionality

    • we are implementing FastAPI to replace an existing API of ours which currently sits at version 2
    • we want the ability to make the default version in fastapi-versioning customisable, as opposed to always defaulting to (1, 0)
    • this PR implements this!
    opened by gtlambert 3
  • Type checking

    Type checking

    Hi,

    Thanks for this project. Shouldn't it be version_route_mapping: Dict[Tuple[int, int], List[APIRoute]] = defaultdict(list) instead of:

    https://github.com/DeanWay/fastapi-versioning/blob/3db32d809caa70217700902a31eb8093d0d647cf/fastapi_versioning/versioning.py#L37

    opened by joel314 2
  • Warning:

    Warning: "openapi_prefix" has been deprecated in favor of "root_path"

    First of all thank you for your work on the module! I really like what you are doing and its working great.

    Describe the bug During startup of the API a warning message is shown (likely due to a change in FastAPI): "openapi_prefix" has been deprecated in favor of "root_path", which follows more closely the ASGI standard, is simpler, and more automatic. Check the docs at https://fastapi.tiangolo.com/advanced/sub-applications-proxy/ Might be a simple change here ?

    To Reproduce Minimal example:

    #example.py
    import uvicorn
    from fastapi import Depends, FastAPI
    from fastapi_versioning import version, VersionedFastAPI
    
    app = FastAPI()
    
    @app.get(path='/example')
    @version(1, 0)
    def example():
        return 'test'
    
    app = VersionedFastAPI(app) #here the warning is shown
    
    if __name__ == "__main__":
        uvicorn.run("example:app",host="127.0.0.1",port=8000,reload=True,debug=True)
    

    Warning message: Anmerkung 2020-07-07 144511

    Not related to the bug I was happy to find that module is even doing more than you write in the readme: If a route is only specified in version v1_0 and not overwritten by a new version it is also available in newer endpoints (e.g. v2_0). For me this seems worth mentioning in the readme 👍

    opened by p-rinnert 2
  • Use functools.wraps for decorator

    Use functools.wraps for decorator

    Implement functools.wraps in the version decorator to avoid breaking tab completion and breaking wrapped function signature:

    https://github.com/DeanWay/fastapi-versioning/blob/875863c0a312e4d30ecbb351abc3e145fa203b62/fastapi_versioning/versioning.py#L12

    opened by HacKanCuBa 2
  • Support bound methods

    Support bound methods

    In cases where FastAPI routes are defined as bound methods on a Class, attribute assignment for the method requires .__func__._api_version to access the underlying function.

    opened by tijptjik 2
  • Avoid defining own dunder property(s)

    Avoid defining own dunder property(s)

    Is your feature request related to a problem? Please describe. In code used dunder property __api_version__ for function.

    Describe the solution you'd like Just set the _api_version.

    Describe alternatives you've considered This looks more pythonic, than your idea.

    opened by prostomarkeloff 2
  • Maintained Fork Inquiry

    Maintained Fork Inquiry

    Are there a good number of people interested in this still? Could potentially fork this and address some of the issues here based off how many people would want that. I see it hasn't been maintained in over a year.

    opened by TheJumpyWizard 3
  • Additional arguments of FastAPI() not working, such as swagger_ui_parameters or description

    Additional arguments of FastAPI() not working, such as swagger_ui_parameters or description

    Describe the bug Some arguments of FastAPI() won't work

    To Reproduce Use argument swagger_ui_parameters={"docExpansion": "none"} and check that it won't work in the versioning, as it won't collapse the tabs.

    Expected behavior I expect all arguments of FastAPI() to work.

    Additional context I already did a PR with a quick fix. PR #71

    opened by PabloRuizCuevas 1
  • Supported kargs in versioned documentation

    Supported kargs in versioned documentation

    Till now some arguments of FastAPI where not working, like:

        description="Core API",
        swagger_ui_parameters={"docExpansion": "none"},
    

    This issue is yet fixed

    opened by PabloRuizCuevas 5
  • Docs URL is served even when set to None

    Docs URL is served even when set to None

    Describe the bug Even with docs_url set to None, the docs are still served. Per the FastAPI documentation, the app should no longer serve docs with this option set.

    You can disable it by setting docs_url=None. https://fastapi.tiangolo.com/tutorial/metadata/#docs-urls

    def docs_url_kwargs() -> dict:
        return  {
            "openapi_url": None,
            "docs_url": None,
            "redoc_url": None,
        }
    
    application = FastAPI(
        title='Example FastApi',
        description='Nice',
        **docs_url_kwargs(),
    )
    application = VersionedFastAPI(
        application,
        version_format="{major}",
        prefix_format="/v{major}/api/",
        description='version',
        enable_latest=True,
        **docs_url_kwargs(),
    )
    
    

    To Reproduce Set docs_url=None when instantiating the FastAPI app and VersionedFastAPI but still see the docs served at /docs.

    Expected behavior Expecting docs to no longer be served (for production use case).

    Additional details Issue may be here: https://github.com/DeanWay/fastapi-versioning/blob/18d480f5bb067088f157f235a673cb4c65ec77d5/fastapi_versioning/versioning.py#L68-L73

    opened by jshields 1
  • remove

    remove "latest" keyword from url path for the latest version API?

    Is your feature request related to a problem? Please describe. This is a question regarding #35. I am curious about why you would want the keyword "latest" to be in the path, because it feels more natural that /api/endpoint serve the latest version of the API by default.

    Describe the solution you'd like If that is clear, i guess we can remove the keyword "latest" from the prefix in versioning.py, line 76, so anything from the default API direct to the latest API. Reference source code link:

    modification:

    if enable_latest:
            prefix = "/"
    ......
    

    Alternative option The above question is actually from the concern whether I could set some version of API to be a generic API like... suppose you have v1, v2, and v3 APIs where all have /items endpoint, and you want v2 to be accessible by default path like /items ( /items redirect to /v2/items )

    Additional context I would mainly want to know the decision behind the usage of the keyword; #35 describes the reason, but it's not really convincing to me and if the concern here is about serving the latest version to client, generic API call without any version, keyword, etc would be better for users and also for restfulness too.

    opened by qmffkem 2
Releases(0.8.0)
Owner
Dean Way
Dean Way
MS Graph API authentication example with Fast API

MS Graph API authentication example with Fast API What it is & does This is a simple python service/webapp, using FastAPI with server side rendering,

Andrew Hart 4 Aug 11, 2022
A Sample App to Demonstrate React Native and FastAPI Integration

React Native - Service Integration with FastAPI Backend. A Sample App to Demonstrate React Native and FastAPI Integration UI Based on NativeBase toolk

YongKi Kim 4 Nov 17, 2022
Simple example of FastAPI + Celery + Triton for benchmarking

You can see the previous work from: https://github.com/Curt-Park/producer-consumer-fastapi-celery https://github.com/Curt-Park/triton-inference-server

Jinwoo Park (Curt) 37 Dec 29, 2022
Prometheus exporter for metrics from the MyAudi API

Prometheus Audi Exporter This Prometheus exporter exports metrics that it fetches from the MyAudi API. Usage Checkout submodules Install dependencies

Dieter Maes 7 Dec 19, 2022
京东图片点击验证码识别

京东图片验证码识别 本项目是@yqchilde 大佬的 JDMemberCloseAccount 识别图形验证码(#45)思路验证,若你也有思路可以提交Issue和PR也可以在 @yqchilde 的 TG群 找到我 声明 本脚本只是为了学习研究使用 本脚本除了采集处理验证码图片没有其他任何功能,也

AntonVanke 37 Dec 22, 2022
Sample-fastapi - A sample app using Fastapi that you can deploy on App Platform

Getting Started We provide a sample app using Fastapi that you can deploy on App

Erhan BÜTE 2 Jan 17, 2022
MQTT FastAPI Wrapper With Python

mqtt-fastapi-wrapper Quick start Create mosquitto.conf with the following content: ➜ /tmp cat mosquitto.conf persistence false allow_anonymous true

Vitalii Kulanov 3 May 09, 2022
Town / City geolocations with FastAPI & Mongo

geolocations-api United Kingdom Town / City geolocations with FastAPI & Mongo Build container To build a custom image or extend the api run the follow

Joe Gasewicz 3 Jan 26, 2022
FastAPI simple cache

FastAPI Cache Implements simple lightweight cache system as dependencies in FastAPI. Installation pip install fastapi-cache Usage example from fastapi

Ivan Sushkov 188 Dec 29, 2022
A kedro-plugin to serve Kedro Pipelines as API

General informations Software repository Latest release Total downloads Pypi Code health Branch Tests Coverage Links Documentation Deployment Activity

Yolan Honoré-Rougé 12 Jul 15, 2022
This repository contains learning resources for Python Fast API Framework and Docker

This repository contains learning resources for Python Fast API Framework and Docker, Build High Performing Apps With Python BootCamp by Lux Academy and Data Science East Africa.

Harun Mbaabu Mwenda 23 Nov 20, 2022
Docker Sample Project - FastAPI + NGINX

Docker Sample Project - FastAPI + NGINX Run FastAPI and Nginx using Docker container Installation Make sure Docker is installed on your local machine

1 Feb 11, 2022
Hook Slinger acts as a simple service that lets you send, retry, and manage event-triggered POST requests, aka webhooks

Hook Slinger acts as a simple service that lets you send, retry, and manage event-triggered POST requests, aka webhooks. It provides a fully self-contained docker image that is easy to orchestrate, m

Redowan Delowar 96 Jan 02, 2023
api versioning for fastapi web applications

fastapi-versioning api versioning for fastapi web applications Installation pip install fastapi-versioning Examples from fastapi import FastAPI from f

Dean Way 472 Jan 02, 2023
FastAPI with Docker and Traefik

Dockerizing FastAPI with Postgres, Uvicorn, and Traefik Want to learn how to build this? Check out the post. Want to use this project? Development Bui

51 Jan 06, 2023
The template for building scalable web APIs based on FastAPI, Tortoise ORM and other.

FastAPI and Tortoise ORM. Powerful but simple template for web APIs w/ FastAPI (as web framework) and Tortoise-ORM (for working via database without h

prostomarkeloff 95 Jan 08, 2023
API Simples com python utilizando a biblioteca FastApi

api-fastapi-python API Simples com python utilizando a biblioteca FastApi Para rodar esse script são necessárias duas bibliotecas: Fastapi: Comando de

Leonardo Grava 0 Apr 29, 2022
Pagination support for flask

flask-paginate Pagination support for flask framework (study from will_paginate). It supports several css frameworks. It requires Python2.6+ as string

Lix Xu 264 Nov 07, 2022
:rocket: CLI tool for FastAPI. Generating new FastAPI projects & boilerplates made easy.

Project generator and manager for FastAPI. Source Code: View it on Github Features 🚀 Creates customizable project boilerplate. Creates customizable a

Yagiz Degirmenci 1k Jan 02, 2023
A set of demo of deploying a Machine Learning Model in production using various methods

Machine Learning Model in Production This git is for those who have concern about serving your machine learning model to production. Overview The tuto

Vo Van Tu 53 Sep 14, 2022