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
Simple FastAPI Example : Blog API using FastAPI : Beginner Friendly

fastapi_blog FastAPI : Simple Blog API with CRUD operation Steps to run the project: git clone https://github.com/mrAvi07/fastapi_blog.git cd fastapi-

Avinash Alanjkar 1 Oct 08, 2022
A RESTful API for creating and monitoring resource components of a hypothetical build system. Built with FastAPI and pydantic. Complete with testing and CI.

diskspace-monitor-CRUD Background The build system is part of a large environment with a multitude of different components. Many of the components hav

Nick Hopewell 67 Dec 14, 2022
✨️🐍 SPARQL endpoint built with RDFLib to serve machine learning models, or any other logic implemented in Python

✨ SPARQL endpoint for RDFLib rdflib-endpoint is a SPARQL endpoint based on a RDFLib Graph to easily serve machine learning models, or any other logic

Vincent Emonet 27 Dec 19, 2022
Flood Detection with Google Earth Engine

ee-fastapi: Flood Detection System A ee-fastapi is a simple FastAPI web application for performing flood detection using Google Earth Engine in the ba

Cesar Aybar 69 Jan 06, 2023
μŠ€νƒ€νŠΈμ—… 개발자 μ±„μš©

μŠ€νƒ€νŠΈμ—… 개발자 μ±„μš© ε€§ λ°•λžŒνšŒ Seed ~ Series B에 μžˆλŠ” μŠ€νƒ€νŠΈμ—…μ„ μœ„ν•œ μ±„μš©μ •λ³΄ νŽ˜μ΄μ§€μž…λ‹ˆλ‹€. Back-end, Frontend, Mobile λ“± 개발자λ₯Ό λŒ€μƒμœΌλ‘œ μ§„ν–‰ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. ν•΄λ‹Ή μŠ€νƒ€νŠΈμ—…μ— μ’…μ‚¬ν•˜μ‹œλŠ” λΆ„λΏλ§Œ μ•„λ‹ˆλΌ μ±„μš© κ΄€λ ¨ 정보λ₯Ό μ•Œκ³  κ³„μ‹œλ‹€λ©΄

JuHyun Lee 58 Dec 14, 2022
REST API with FastAPI and PostgreSQL

REST API with FastAPI and PostgreSQL To have the same data in db: create table CLIENT_DATA (id SERIAL PRIMARY KEY, fullname VARCHAR(50) NOT NULL,email

Luis QuiΓ±ones Requelme 1 Nov 11, 2021
FastAPI Auth Starter Project

This is a template for FastAPI that comes with authentication preconfigured.

Oluwaseyifunmi Oyefeso 6 Nov 13, 2022
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
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
A FastAPI Framework for things like Database, Redis, Logging, JWT Authentication and Rate Limits

A FastAPI Framework for things like Database, Redis, Logging, JWT Authentication and Rate Limits Install You can install this Library with: pip instal

Tert0 33 Nov 28, 2022
A FastAPI Middleware of joerick/pyinstrument to check your service performance.

fastapi_profiler A FastAPI Middleware of joerick/pyinstrument to check your service performance. πŸ“£ Info A FastAPI Middleware of pyinstrument to check

LeoSun 107 Jan 05, 2023
A simple example of deploying FastAPI as a Zeit Serverless Function

FastAPI Zeit Now Deploy a FastAPI app as a Zeit Serverless Function. This repo deploys the FastAPI SQL Databases Tutorial to demonstrate how a FastAPI

Paul Weidner 26 Dec 21, 2022
FastAPI application and service structure for a more maintainable codebase

Abstracting FastAPI Services See this article for more information: https://camillovisini.com/article/abstracting-fastapi-services/ Poetry poetry inst

Camillo Visini 309 Jan 04, 2023
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
SuperSaaSFastAPI - Python SaaS Boilerplate for building Software-as-Service (SAAS) apps with FastAPI, Vue.js & Tailwind

Python SaaS Boilerplate for building Software-as-Service (SAAS) apps with FastAP

Rudy Bekker 31 Jan 10, 2023
FastAPI Project Template

The base to start an openapi project featuring: SQLModel, Typer, FastAPI, JWT Token Auth, Interactive Shell, Management Commands.

A.Freud 4 Dec 05, 2022
Keycloack plugin for FastApi.

FastAPI Keycloack Keycloack plugin for FastApi. Your aplication receives the claims decoded from the access token. Usage Run keycloak on port 8080 and

Elber 4 Jun 24, 2022
This project shows how to serve an ONNX-optimized image classification model as a web service with FastAPI, Docker, and Kubernetes.

Deploying ML models with FastAPI, Docker, and Kubernetes By: Sayak Paul and Chansung Park This project shows how to serve an ONNX-optimized image clas

Sayak Paul 104 Dec 23, 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
FastAPI IPyKernel Sandbox

FastAPI IPyKernel Sandbox This repository is a light-weight FastAPI project that is meant to provide a wrapper around IPyKernel interactions. It is in

Nick Wold 2 Oct 25, 2021