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
fastapi-admin2 is an upgraded fastapi-admin, that supports ORM dialects, true Dependency Injection and extendability

FastAPI2 Admin Introduction fastapi-admin2 is an upgraded fastapi-admin, that supports ORM dialects, true Dependency Injection and extendability. Now

Glib 14 Dec 05, 2022
Cookiecutter API for creating Custom Skills for Azure Search using Python and Docker

cookiecutter-spacy-fastapi Python cookiecutter API for quick deployments of spaCy models with FastAPI Azure Search The API interface is compatible wit

Microsoft 379 Jan 03, 2023
Feature rich robust FastAPI template.

Flexible and Lightweight general-purpose template for FastAPI. Usage ⚠️ Git, Python and Poetry must be installed and accessible ⚠️ Poetry version must

Pavel Kirilin 588 Jan 04, 2023
Practice-python is a simple Fast api project for dealing with modern rest api technologies.

Practice Python Practice-python is a simple Fast api project for dealing with modern rest api technologies. Deployment with docker Go to the project r

0 Sep 19, 2022
A simple Blogging Backend app created with Fast API

This is a simple blogging app backend built with FastAPI. This project is created to simulate a real CRUD blogging system. It is built to be used by s

Owusu Kelvin Clark 13 Mar 24, 2022
A web application using [FastAPI + streamlit + Docker] Neural Style Transfer (NST) refers to a class of software algorithms that manipulate digital images

Neural Style Transfer Web App - [FastAPI + streamlit + Docker] NST - application based on the Perceptual Losses for Real-Time Style Transfer and Super

Roman Spiridonov 3 Dec 05, 2022
Complete Fundamental to Expert Codes of FastAPI for creating API's

FastAPI FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3 based on standard Python type hints. The key featu

Pranav Anand 1 Nov 28, 2021
Prometheus integration for Starlette.

Starlette Prometheus Introduction Prometheus integration for Starlette. Requirements Python 3.6+ Starlette 0.9+ Installation $ pip install starlette-p

José Antonio Perdiguero 229 Dec 21, 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
Simple web app example serving a PyTorch model using streamlit and FastAPI

streamlit-fastapi-model-serving Simple example of usage of streamlit and FastAPI for ML model serving described on this blogpost and PyConES 2020 vide

Davide Fiocco 291 Jan 06, 2023
Ready-to-use and customizable users management for FastAPI

FastAPI Users Ready-to-use and customizable users management for FastAPI Documentation: https://fastapi-users.github.io/fastapi-users/ Source Code: ht

FastAPI Users 2.3k Dec 30, 2022
This code generator creates FastAPI app from an openapi file.

fastapi-code-generator This code generator creates FastAPI app from an openapi file. This project is an experimental phase. fastapi-code-generator use

Koudai Aono 632 Jan 05, 2023
Docker image with Uvicorn managed by Gunicorn for high-performance FastAPI web applications in Python 3.6 and above with performance auto-tuning. Optionally with Alpine Linux.

Supported tags and respective Dockerfile links python3.8, latest (Dockerfile) python3.7, (Dockerfile) python3.6 (Dockerfile) python3.8-slim (Dockerfil

Sebastián Ramírez 2.1k Dec 31, 2022
Generate modern Python clients from OpenAPI

openapi-python-client Generate modern Python clients from OpenAPI 3.x documents. This generator does not support OpenAPI 2.x FKA Swagger. If you need

Triax Technologies 558 Jan 07, 2023
implementation of deta base for FastAPIUsers

FastAPI Users - Database adapter for Deta Base Ready-to-use and customizable users management for FastAPI Documentation: https://fastapi-users.github.

2 Aug 15, 2022
Hyperlinks for pydantic models

Hyperlinks for pydantic models In a typical web application relationships between resources are modeled by primary and foreign keys in a database (int

Jaakko Moisio 10 Apr 18, 2022
A FastAPI Plug-In to support authentication authorization using the Microsoft Authentication Library (MSAL)

FastAPI/MSAL - MSAL (Microsoft Authentication Library) plugin for FastAPI FastAPI - https://github.com/tiangolo/fastapi FastAPI is a modern, fast (hig

Dudi Levy 15 Jul 20, 2022
FastAPI with async for generating QR codes and bolt11 for Lightning Addresses

sendsats An API for getting QR codes and Bolt11 Invoices from Lightning Addresses. Share anywhere; as a link for tips on a twitter profile, or via mes

Bitkarrot 12 Jan 07, 2023
Qwerkey is a social media platform for connecting and learning more about mechanical keyboards built on React and Redux in the frontend and Flask in the backend on top of a PostgreSQL database.

Flask React Project This is the backend for the Flask React project. Getting started Clone this repository (only this branch) git clone https://github

Peter Mai 22 Dec 20, 2022