Code Monkey home page Code Monkey logo

fastapi_returns_inferring_router's Introduction

Combines InferringRouter from fastapi-utils and Result from returns so that both primary (200) and additional response types can be inferred from the path operation type signature.

Install as user:

pip install git+https://github.com/amacfie/fastapi_returns_inferring_router

Install as developer:

pip install --editable .

How to use

from typing import Literal

from pydantic import BaseModel
from returns.result import Result, Success, Failure
import fastapi

from fastapi_returns_inferring_router import ReturnsInferringRouter


class ForbiddenBecauseOfUser(BaseModel):
    def status_code(*args):
        return 403

    msg: Literal["Forbidden because of user"] = "Forbidden because of user"


class ForbiddenBecauseOfKey(BaseModel):
    def status_code(*args):
        return 403

    msg: Literal["Forbidden because of key"] = "Forbidden because of key"


app = fastapi.FastAPI()

# two params are added to APIRouter
# * get_status_code
#   pass a function that can take either a return type or return value and
#   returns the HTTP status code you wish to use it for
# * merge_with_existing_responses
#   if there's already a responses parameter, if this parameter is True we
#   add to it, otherwise we don't touch it
r = ReturnsInferringRouter(
    get_status_code=lambda x: x.status_code(),
    merge_with_existing_responses=True,
)

# compatible with InferringRouter from fastapi-utils
@r.get("/foo/{bar}")
def foo(bar: str) -> str:
    return bar + "b"


# use the Returns library to write a function with a return type of Result.
# the success type becomes the 200 response type
# any failure types are also added as response types under the status code
# given by get_status_code.
# here we have two types with the same status code so the schema for 403 will
# be the union of the two types.
# currently, as with InferringRouter, only stuff that gets encoded as JSON
# is supported, e.g. having FileResponse as a return type won't work well.
# see https://github.com/amacfie/fastapi_returns_inferring_router/issues/2
@r.get("/baz/{bar}")
def baz(bar: str) -> Result[str, ForbiddenBecauseOfKey | ForbiddenBecauseOfUser]:
    if ...:
        return Failure(ForbiddenBecauseOfKey())
    elif ...:
        return Failure(ForbiddenBecauseOfUser())
    else:
        return Success(bar + "b")


app.include_router(r)

Generated schema (paste to https://editor.swagger.io/ for nicer view):

{
  "openapi": "3.0.2",
  "info": {
    "title": "FastAPI",
    "version": "0.1.0"
  },
  "paths": {
    "/foo/{bar}": {
      "get": {
        "summary": "Foo",
        "operationId": "foo_foo__bar__get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "title": "Bar",
              "type": "string"
            },
            "name": "bar",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "title": "Response Foo Foo  Bar  Get",
                  "type": "string"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/baz/{bar}": {
      "get": {
        "summary": "Baz",
        "operationId": "baz_baz__bar__get",
        "parameters": [
          {
            "required": true,
            "schema": {
              "title": "Bar",
              "type": "string"
            },
            "name": "bar",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "title": "Response Baz Baz  Bar  Get",
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "title": "Response 403 Baz Baz  Bar  Get",
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/ForbiddenBecauseOfKey"
                    },
                    {
                      "$ref": "#/components/schemas/ForbiddenBecauseOfUser"
                    }
                  ]
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ForbiddenBecauseOfKey": {
        "title": "ForbiddenBecauseOfKey",
        "type": "object",
        "properties": {
          "msg": {
            "title": "Msg",
            "enum": [
              "Forbidden because of key"
            ],
            "type": "string",
            "default": "Forbidden because of key"
          }
        }
      },
      "ForbiddenBecauseOfUser": {
        "title": "ForbiddenBecauseOfUser",
        "type": "object",
        "properties": {
          "msg": {
            "title": "Msg",
            "enum": [
              "Forbidden because of user"
            ],
            "type": "string",
            "default": "Forbidden because of user"
          }
        }
      },
      "HTTPValidationError": {
        "title": "HTTPValidationError",
        "type": "object",
        "properties": {
          "detail": {
            "title": "Detail",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            }
          }
        }
      },
      "ValidationError": {
        "title": "ValidationError",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "type": "object",
        "properties": {
          "loc": {
            "title": "Location",
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            }
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        }
      }
    }
  }
}

fastapi_returns_inferring_router's People

Contributors

amacfie avatar

Watchers

 avatar  avatar

fastapi_returns_inferring_router's Issues

Support problem details

https://datatracker.ietf.org/doc/draft-ietf-httpapi-rfc7807bis/

  • new response content type -- fastapi can only do one content type per status code so we'd want to make the use of application/problem+json optional and if it's enabled then raise an error if merging with existing responses that have a different content type (and actually we should be checking for existing content types anyway)
  • maybe fastapi itself will integrate with it somehow
  • write ABC error model

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.