JSON-RPC server based on fastapi

Overview

Description

JSON-RPC server based on fastapi:

https://fastapi.tiangolo.com

Motivation

Autogenerated OpenAPI and Swagger (thanks to fastapi) for JSON-RPC!!!

Installation

pip install fastapi-jsonrpc

Documentation

Read FastAPI documentation and see usage examples bellow

Simple usage example

pip install uvicorn

example1.py

import fastapi_jsonrpc as jsonrpc
from pydantic import BaseModel
from fastapi import Body


app = jsonrpc.API()

api_v1 = jsonrpc.Entrypoint('/api/v1/jsonrpc')


class MyError(jsonrpc.BaseError):
    CODE = 5000
    MESSAGE = 'My error'

    class DataModel(BaseModel):
        details: str


@api_v1.method(errors=[MyError])
def echo(
    data: str = Body(..., example='123'),
) -> str:
    if data == 'error':
        raise MyError(data={'details': 'error'})
    else:
        return data


app.bind_entrypoint(api_v1)


if __name__ == '__main__':
    import uvicorn
    uvicorn.run('example1:app', port=5000, debug=True, access_log=False)

Go to:

http://127.0.0.1:5000/docs

FastAPI dependencies usage example

pip install uvicorn

example2.py

import logging
from contextlib import asynccontextmanager

from pydantic import BaseModel, Field
import fastapi_jsonrpc as jsonrpc
from fastapi import Body, Header, Depends


logger = logging.getLogger(__name__)


# database models

class User:
    def __init__(self, name):
        self.name = name

    def __eq__(self, other):
        if not isinstance(other, User):
            return False
        return self.name == other.name


class Account:
    def __init__(self, account_id, owner, amount, currency):
        self.account_id = account_id
        self.owner = owner
        self.amount = amount
        self.currency = currency

    def owned_by(self, user: User):
        return self.owner == user


# fake database

users = {
    '1': User('user1'),
    '2': User('user2'),
}

accounts = {
    '1.1': Account('1.1', users['1'], 100, 'USD'),
    '1.2': Account('1.2', users['1'], 200, 'EUR'),
    '2.1': Account('2.1', users['2'], 300, 'USD'),
}


def get_user_by_token(auth_token) -> User:
    return users[auth_token]


def get_account_by_id(account_id) -> Account:
    return accounts[account_id]


# schemas

class Balance(BaseModel):
    """Account balance"""
    amount: int = Field(..., example=100)
    currency: str = Field(..., example='USD')


# errors

class AuthError(jsonrpc.BaseError):
    CODE = 7000
    MESSAGE = 'Auth error'


class AccountNotFound(jsonrpc.BaseError):
    CODE = 6000
    MESSAGE = 'Account not found'


class NotEnoughMoney(jsonrpc.BaseError):
    CODE = 6001
    MESSAGE = 'Not enough money'

    class DataModel(BaseModel):
        balance: Balance


# dependencies

def get_auth_user(
    # this will become the header-parameter of json-rpc method that uses this dependency
    auth_token: str = Header(
        None,
        alias='user-auth-token',
    ),
) -> User:
    if not auth_token:
        raise AuthError

    try:
        return get_user_by_token(auth_token)
    except KeyError:
        raise AuthError


def get_account(
    # this will become the parameter of the json-rpc method that uses this dependency
    account_id: str = Body(..., example='1.1'),
    user: User = Depends(get_auth_user),
) -> Account:
    try:
        account = get_account_by_id(account_id)
    except KeyError:
        raise AccountNotFound

    if not account.owned_by(user):
        raise AccountNotFound

    return account


# JSON-RPC middlewares

@asynccontextmanager
async def logging_middleware(ctx: jsonrpc.JsonRpcContext):
    logger.info('Request: %r', ctx.raw_request)
    try:
        yield
    finally:
        logger.info('Response: %r', ctx.raw_response)


# JSON-RPC entrypoint

common_errors = [AccountNotFound, AuthError]
common_errors.extend(jsonrpc.Entrypoint.default_errors)

api_v1 = jsonrpc.Entrypoint(
    # Swagger shows for entrypoint common parameters gathered by dependencies and common_dependencies:
    #    - json-rpc-parameter 'account_id'
    #    - header parameter 'user-auth-token'
    '/api/v1/jsonrpc',
    errors=common_errors,
    middlewares=[logging_middleware],
    # this dependencies called once for whole json-rpc batch request
    dependencies=[Depends(get_auth_user)],
    # this dependencies called separately for every json-rpc request in batch request
    common_dependencies=[Depends(get_account)],
)


# JSON-RPC methods of this entrypoint

# this json-rpc method has one json-rpc-parameter 'account_id' and one header parameter 'user-auth-token'
@api_v1.method()
def get_balance(
    account: Account = Depends(get_account),
) -> Balance:
    return Balance(
        amount=account.amount,
        currency=account.currency,
    )


# this json-rpc method has two json-rpc-parameters 'account_id', 'amount' and one header parameter 'user-auth-token'
@api_v1.method(errors=[NotEnoughMoney])
def withdraw(
    account: Account = Depends(get_account),
    amount: int = Body(..., gt=0, example=10),
) -> Balance:
    if account.amount - amount < 0:
        raise NotEnoughMoney(data={'balance': get_balance(account)})
    account.amount -= amount
    return get_balance(account)


# JSON-RPC API

app = jsonrpc.API()
app.bind_entrypoint(api_v1)


if __name__ == '__main__':
    import uvicorn
    uvicorn.run('example2:app', port=5000, debug=True, access_log=False)

Go to:

http://127.0.0.1:5000/docs

./images/fastapi-jsonrpc.png

Development

  • Install poetry

    https://github.com/sdispater/poetry#installation

  • Install dephell

    pip install dephell
  • Install dependencies

    poetry update
  • Regenerate README.rst

    rst_include include -q README.src.rst README.rst
  • Change dependencies

    Edit pyproject.toml

    poetry update
    dephell deps convert
  • Bump version

    poetry version patch
    dephell deps convert
  • Publish to pypi

    poetry publish --build
Comments
  • В swagger в Example Value выставляется неверное значение версии jsonrpc

    В swagger в Example Value выставляется неверное значение версии jsonrpc

    В swagger в примере запросе поле "jsonrpc" выставляется равным 2, как число. Необходимо, чтобы выставлялось "2.0", как строка.

    image image

    Есть предположение что, если тут значение example='"2.0"', то тогда swagger автоматом не преобразовывал бы это значение в численное.

    Версия библиотеки fastapi-jsonrpc==2.0.2, pydantic==1.7.3

    opened by DianaArapova 6
  • No validation error if id is not passed with request

    No validation error if id is not passed with request

    Hey folks Great lib and I'm using it with my projects quite often now

    I saw one strange behavior that I suppose needs some fixing or enhancement

    Here I'm sending a simple request via postman and getting a blank response:

    Request:
    
    {
        "jsonrpc": "2.0",
        "params": {
            "invite_id": "fb233510-9862-4f98-8278-8a173841857e"
        },
        "method": "verify_invite"
    }
    

    Response: image

    As you can see id field is missing on the JSON body, but no error is raised if it's missing there

    When I'm adding id to the body I got the correct JSON response:

    Request:
    
    {
        "jsonrpc": "2.0",
        "params": {
            "invite_id": "fb233510-9862-4f98-8278-8a173841857e"
        },
        "method": "verify_invite",
        "id": 0
    }
    

    Response: image

    Maybe I'm missing something and you can point me In the right direction of using things, but for me, it looks like there should be an error raised when id is not passed to the JSON body

    enhancement 
    opened by appvales-lemeshko 4
  • Allow using custom request class

    Allow using custom request class

    Hey

    My team and I came across a use case where we needed to allow some extra fields in the first level of the Json-RPC payload request.

    So I added an option to use a custom JsonRpcRequest class, inheriting from the initial fastapi-jsonrpc's JsonRpcRequest class.

    The usage is the following:

    
    import fastapi_jsonrpc as jsonrpc
    
    from fastapi.middleware.cors import CORSMiddleware
    from fastapi import Body
    from fastapi_jsonrpc import JsonRpcRequest
    
    app = jsonrpc.API()
    
    app.add_middleware(CORSMiddleware, allow_origins=["*"])
    
    
    class CustomJsonRpcRequest(JsonRpcRequest):
        extravalue: str
    
    api_v1 = jsonrpc.Entrypoint("/api", request_class=CustomJsonRpcRequest)
    
    
    @api_v1.method()
    def echo(
        data: str = Body(..., example="123"),
    ) -> dict:
        return {"from": "echo", "data": data}
    
    
    app.bind_entrypoint(api_v1)
    

    This example allows receiving this payload:

    {
      id: 0,
      jsonrpc: "2.0",
      method: "echo",
      params: {data: "testdata"},
      extravalue: "test"
    }
    

    I hope you'll find this feature useful 👍.

    opened by Smlep 4
  • New FastAPI version breaks fastapi-jsonrpc

    New FastAPI version breaks fastapi-jsonrpc

    Following release 0.18.0 of Starlette accepted by FastAPI in 0.76.0, starlette.Response object does not accept None value anymore for status_code (starlette/responses.py#L77). This breaks the EntrypointRoute.handle_http_request function.

    A fix might be possible, but freezing dependencies would be safer to avoid future issue with future updates.

    To reproduce:

    This minimal example does not work anymore

    # main.py
    import fastapi_jsonrpc as jsonrpc
    
    app = jsonrpc.API()
    api_v1 = jsonrpc.Entrypoint('/api/v1/jsonrpc')
    
    @api_v1.method()
    def echo(
        x: int,
    ) -> int:
        return x
    
    app.bind_entrypoint(api_v1)
    
    if __name__ == '__main__':
        import uvicorn
        uvicorn.run('main:app', port=5000, debug=True, access_log=False)
    
    pip install fastapi==0.76.0
    
    python main.py
    
    curl --request POST \
      --url http://localhost:5000/api/v1/jsonrpc \
      --header 'Content-Type: application/json' \
      --data '{
    	"method": "echo",
    	"id": "1",
    	"params": {
    	    "x": 1
    	}
    }'
    
    opened by VincentHch 3
  • Logs from JSON-RPC views are missing when running in pytest

    Logs from JSON-RPC views are missing when running in pytest

    Live logs are not captured for anything that happens in JSON-RPC views when running pytest (logging_middleware from README also doesn't output anything when running in pytest). But logs are present when running web app.

    Requirements:

    uvicorn==0.17.6
    fastapi==0.75.2
    fastapi-jsonrpc==2.2.0
    
    # checked on "pytest<7" too
    pytest==7.1.2
    # checked on "pytest-asyncio<0.16" too
    pytest-asyncio==0.18.3
    # checked on "httpx<0.20" too
    httpx==0.22.0
    

    pytest.ini

    [pytest]
    log_cli = True
    log_cli_level = INFO
    asyncio_mode=auto
    

    main.py

    import logging
    
    logging.basicConfig(level=logging.DEBUG)
    log = logging.getLogger(__name__)
    
    import fastapi_jsonrpc as jsonrpc
    from pydantic import BaseModel
    from fastapi import Body
    
    
    app = jsonrpc.API()
    
    api_v1 = jsonrpc.Entrypoint("/api/v1/jsonrpc")
    
    
    @app.get("/hello")
    def handle_hello(name: str):
        log.info("hello %s", name)
        return {"hello": name}
    
    
    class MyError(jsonrpc.BaseError):
        CODE = 9001
        MESSAGE = 'My error'
    
        class DataModel(BaseModel):
            details: str
    
    
    @api_v1.method(errors=[MyError])
    def echo(
        data: str = Body(..., example='123'),
    ) -> str:
        log.info("Process echo view, data: %s", data)
        if data == 'error':
            raise MyError(data={'details': 'error'})
        else:
            return data
    
    
    app.bind_entrypoint(api_v1)
    

    test_main.py

    import logging
    
    from pytest import fixture, mark
    from httpx import AsyncClient
    
    from main import app
    
    log = logging.getLogger(__name__)
    
    pytestmark = mark.asyncio
    
    
    @fixture
    async def async_client():
        async with AsyncClient(app=app, base_url="http://test") as ac:
            yield ac
    
    
    async def test_echo_jsonrpc(async_client):
        url = "/api/v1/jsonrpc"
        log.info("gonna run async test for JSON-RPC")
        response = await async_client.post(url)
        assert response.status_code == 200
        log.info("async test for JSON-RPC done")
    
    
    async def test_hello(async_client):
        url = "/hello"
        name = "John"
        log.info("gonna run async test for hello view")
        response = await async_client.get(url, params={"name": name})
        assert response.status_code == 200
        log.info("async test for hello view done")
    

    Getting logs when app is running

    1. Run app:
    uvicorn "main:app"
    
    1. visit http://127.0.0.1:8000/docs or use terminal utilities (curl, httpie) for requests
    2. call a regular FastAPI view:
    curl -X 'GET' \
      'http://127.0.0.1:8000/hello?name=John' \
      -H 'accept: application/json'
    
    {"hello":"John"}% 
    
    1. check terminal where the app is running for logs:
    INFO:main:hello John
    INFO:     127.0.0.1:51376 - "GET /hello?name=John HTTP/1.1" 200 OK
    

    The INFO:main:hello John log comes from the handle_hello view function 5) call a JSON-RPC FastAPI view:

    curl -X 'POST' \
      'http://127.0.0.1:8000/api/v1/jsonrpc' \     
      -H 'accept: application/json' \
      -H 'Content-Type: application/json' \
      -d '{
      "jsonrpc": "2.0",
      "id": 0,
      "method": "echo",
      "params": {
        "data": "spam and eggs"
      }
    }'
    
    {"jsonrpc":"2.0","result":"spam and eggs","id":0}%
    
    1. check terminal where the app is running for logs:
    INFO:main:Process echo view, data: spam and eggs
    INFO:     127.0.0.1:51388 - "POST /api/v1/jsonrpc HTTP/1.1" 200 OK
    

    The INFO:main:Process echo view, data: spam and eggs log comes from the echo JSON-RPC view function

    So we HAVE logs when the app runs.

    Run pytest and check logs

    1. Run pytest -s -v
    2. Check output:
    ========================= test session starts =========================
    platform darwin -- Python 3.9.9, pytest-7.1.2, pluggy-1.0.0 -- /Users/suren/Projects/fastapi-pytest-logging/venv/bin/python
    cachedir: .pytest_cache
    rootdir: /Users/suren/Projects/fastapi-pytest-logging, configfile: pytest.ini
    plugins: asyncio-0.18.3, anyio-3.5.0
    asyncio: mode=auto
    collected 2 items                                                     
    
    test_main.py::test_echo_jsonrpc 
    ---------------------------- live log call ----------------------------
    INFO     test_main:test_main.py:21 gonna run async test for JSON-RPC
    INFO     test_main:test_main.py:24 async test for JSON-RPC done
    PASSED
    test_main.py::test_hello 
    ---------------------------- live log call ----------------------------
    INFO     test_main:test_main.py:30 gonna run async test for hello view
    INFO     main:main.py:18 hello John
    INFO     test_main:test_main.py:33 async test for hello view done
    PASSED
    
    ========================== 2 passed in 0.14s ==========================
    

    test_echo_jsonrpc is missing the INFO:main:Process echo view log, but test_hello contains the INFO:main:hello log

    Expected behaviour: all logs are captured

    Is this fixable via some configs, or does this need to be fixed inside the lib?

    opened by mahenzon 3
  • Loosen version requirements on FastApi

    Loosen version requirements on FastApi

    This lib is (most likely) needlessly restricted to 0.55.x rather than 0.55+ and this gets rid of that restriction making it compatible with 0.56, 57, 58 etc

    This PR closes #9

    May I add this is blocking adoption for anyone not using specifically version 0.55 of fastapi on poetry (and potentially more) as there is no simple way to override version solving issues. For now I have vendored it and await for a version bump.

    Thanks for the lib!

    opened by arlyon 3
  • Logging access

    Logging access

    Because client makes post on only one route it's hard to tell what is request

    Maybe it's not about this library, but it would be really useful to have this feature out of the box.

    opened by denisSurkov 3
  • Upgrade to FastAPI >= 0.80

    Upgrade to FastAPI >= 0.80

    Currently this library is limited to not to be used with FastAPI greater then 0.80 but FastAPI has already released ver. 0.86. Is it possible to change this limitation, please?

    pyproject.toml
    fastapi = ">0.55,<0.80"
    
    opened by ksmolyanin 2
  • build(deps-dev): bump mistune from 0.8.4 to 2.0.3

    build(deps-dev): bump mistune from 0.8.4 to 2.0.3

    Bumps mistune from 0.8.4 to 2.0.3.

    Release notes

    Sourced from mistune's releases.

    Version 2.0.2

    Fix escape_url via lepture/mistune#295

    Version 2.0.1

    Fix XSS for image link syntax.

    Version 2.0.0

    First release of Mistune v2.

    Version 2.0.0 RC1

    In this release, we have a Security Fix for harmful links.

    Version 2.0.0 Alpha 1

    This is the first release of v2. An alpha version for users to have a preview of the new mistune.

    Changelog

    Sourced from mistune's changelog.

    Changelog

    Here is the full history of mistune v2.

    Version 2.0.4

    
    Released on Jul 15, 2022
    
    • Fix url plugin in &lt;a&gt; tag
    • Fix * formatting

    Version 2.0.3

    Released on Jun 27, 2022

    • Fix table plugin
    • Security fix for CVE-2022-34749

    Version 2.0.2

    
    Released on Jan 14, 2022
    

    Fix escape_url

    Version 2.0.1

    Released on Dec 30, 2021

    XSS fix for image link syntax.

    Version 2.0.0

    
    Released on Dec 5, 2021
    

    This is the first non-alpha release of mistune v2.

    Version 2.0.0rc1

    Released on Feb 16, 2021

    Version 2.0.0a6

    
    </tr></table> 
    

    ... (truncated)

    Commits
    • 3f422f1 Version bump 2.0.3
    • a6d4321 Fix asteris emphasis regex CVE-2022-34749
    • 5638e46 Merge pull request #307 from jieter/patch-1
    • 0eba471 Fix typo in guide.rst
    • 61e9337 Fix table plugin
    • 76dec68 Add documentation for renderer heading when TOC enabled
    • 799cd11 Version bump 2.0.2
    • babb0cf Merge pull request #295 from dairiki/bug.escape_url
    • fc2cd53 Make mistune.util.escape_url less aggressive
    • 3e8d352 Version bump 2.0.1
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 2
  • Query Parameter

    Query Parameter

    Hi,

    Does this library support the usage of the query parameters? (example: POST http://127.0.0.1:8000/api/v1/jsonrpc?skip=10)

    If yes, can you provide an example?

    Thank you! Fabio

    question 
    opened by fgiudici95 2
  • OpenAPI Becomes Invalid for Datamodel code generator

    OpenAPI Becomes Invalid for Datamodel code generator

    Prance gives errors like:

    Processing "https://.../openapi.json"...
     -> Resolving external references.
    
    [ValidationError]: ("{'content': {'application/json': {'schema': {'title': '_Request', 'required': ['method', 'params'], 'type': 'object', 'properties': {'jsonrpc': {'title': 'Jsonrpc', 'type': 'string', 'example': '2.0', 'const': '2.0'}, 'id': {'title': 'Id', 'anyOf': [{'type': 'string'}, {'type': 'integer'}], 'example': 0}, 'method': {'title': 'Method', 'type': 'string'}, 'params': {'title': 'Params', 'type': 'object'}}, 'additionalProperties': False}}}, 'required': True} is not valid under any of the given schemas", 'oneOf', deque(['paths', '/rpc', 'post', 'requestBody']), None, [<ValidationError: "{'title': '_Request', 'required': ['method', 'params'], 'type': 'object', 'properties': {'jsonrpc': {'title': 'Jsonrpc', 'type': 'string', 'example': '2.0', 'const': '2.0'}, 'id': {'title': 'Id', 'anyOf': [{'type': 'string'}, {'type': 'integer'}], 'example': 0}, 'method': {'title': 'Method', 'type': 'string'}, 'params': {'title': 'Params', 'type': 'object'}}, 'additionalProperties': False} is not valid under any of the given schemas">, <ValidationError: "'$ref' is a required property">], [{'$ref': '#/definitions/RequestBody'}, {'$ref': '#/definitions/Reference'}], {'content': {'application/json': {'schema': {'title': '_Request', 'required': ['method', 'params'], 'type': 'object', 'properties': {'jsonrpc': {'title': 'Jsonrpc', 'type': 'string', 'example': '2.0', 'const': '2.0'}, 'id': {'title': 'Id', 'anyOf': [{'type': 'string'}, {'type': 'integer'}], 'example': 0}, 'method': {'title': 'Method', 'type': 'string'}, 'params': {'title': 'Params', 'type': 'object'}}, 'additionalProperties': False}}}, 'required': True}, {'oneOf': [{'$ref': '#/definitions/RequestBody'}, {'$ref': '#/definitions/Reference'}]}, deque(['properties', 'paths', 'patternProperties', '^\\/', 'patternProperties', '^(get|put|post|delete|options|head|patch|trace)$', 'properties', 'requestBody', 'oneOf']), None)
    

    It makes impossible use of model generators for pydantic https://pydantic-docs.helpmanual.io/datamodel_code_generator/

    bug wontfix 
    opened by tigrus 2
  • build(deps): bump certifi from 2022.9.24 to 2022.12.7

    build(deps): bump certifi from 2022.9.24 to 2022.12.7

    Bumps certifi from 2022.9.24 to 2022.12.7.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Multiple OpenAPI examples

    Multiple OpenAPI examples

    I understand that I can add examples to endpoints via

    @api.method()
    def endpoint(value1: str = Body(example='test'), value2: int = Body(example=3))
        ...
    

    What to do if I want to add multiple examples as discussed in https://fastapi.tiangolo.com/tutorial/schema-extra-example/?h=examples#body-with-multiple-examples ? The obvious thing to do would be to use list the examples in the Body, as it is done in plain FastAPI, but that doesn't work. Perhaps the Entrypoint#method method can accept an examples parameter (i.e. add it to the MethodRoute class)?

    opened by v-- 0
  • Support by-position parameters

    Support by-position parameters

    According to JSON-RPC 2.0 Specification , the params field of request object may be either by-position (Array) or by-name (Object).

    However the current implementation of fastapi-jsonrpc forces to use by-name parameter:

    https://github.com/smagafurov/fastapi-jsonrpc/blob/1329be64ea635a844cdb529eaf31a1ac3055ae58/fastapi_jsonrpc/init.py#L369

    This causes this awesome library is not usable in some circumstances. Can we support by-position parameters in the future version?

    opened by hongqn 1
  • Add bind_entrypoints option to reproduce FastApi's router feature

    Add bind_entrypoints option to reproduce FastApi's router feature

    closes #18

    Fastapi offers a router functionality detailed here. It can be really useful to split the methods into many files.

    This PR adds an option to bind_entrypoint so that multiple Entrypoint with the same path can be merged.

    Here is an example of how I would use this:

    # main.py
    from items import items_router
    from products import products_router
    
    
    app = jsonrpc.API()
    
    app.bind_entrypoint(items_router)
    
    app.bind_entrypoint(products_router, add_to_existing_path=True)
    
    
    # items.py
    import fastapi_jsonrpc as jsonrpc
    
    items_router = jsonrpc.Entrypoint("/api")
    
    
    @items_router.method()
    def list_items() -> dict:
        return {"from": "list_items"}
    
    # products.py
    import fastapi_jsonrpc as jsonrpc
    
    products_router = jsonrpc.Entrypoint("/api")
    
    
    @products_router.method()
    def list_products() -> dict:
        return {"from": "list_products"}
    

    With this example, both list_items and list_products methods can be accessed from /api.

    I have also added some tests for this feature.

    opened by Smlep 2
  • Allow using routers to split the code

    Allow using routers to split the code

    Hi,

    Fastapi offers a router functionality detailed here. It can be really useful to split the methods into many files.

    It would be nice to be able to do the same things with the JSONRPC methods. Currently, since Entrypoint inherits from fastapi's APIRouter, trying to bind another Entrypoint with the same path won't allow access to the methods from the second Entrypoint.

    There should be a way to bind 2 Entrypoint with the same path to one app, allowing both of their methods to be considered.

    Really great library btw, good work!

    opened by Smlep 3
  • Websocket support

    Websocket support

    Nice library! I was wondering if there are any plans to also support websockets (which is a nice extra fastapi provides), like these libraries do?:

    https://jsonrpcclient.readthedocs.io/en/latest/ https://github.com/codemation/easyrpc

    opened by pjotterplotter 1
Releases(v2.4.1)
Owner
null
A Jupyter server based on FastAPI (Experimental)

jupyverse is experimental and should not be used in place of jupyter-server, which is the official Jupyter server.

Jupyter Server 122 Dec 27, 2022
OpenAPI generated FastAPI server

OpenAPI generated FastAPI server This Python package is automatically generated by the OpenAPI Generator project: API version: 1.0.0 Build package: or

microbo 1 Oct 31, 2021
Mnist API server w/ FastAPI

Mnist API server w/ FastAPI

Jinwoo Park (Curt) 8 Feb 8, 2022
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 8, 2023
a lightweight web framework based on fastapi

start-fastapi Version 2021, based on FastAPI, an easy-to-use web app developed upon Starlette Framework Version 2020 中文文档 Requirements python 3.6+ (fo

HiKari 71 Dec 30, 2022
Example app using FastAPI and JWT

FastAPI-Auth Example app using FastAPI and JWT virtualenv -p python3 venv source venv/bin/activate pip3 install -r requirements.txt mv config.yaml.exa

Sander 28 Oct 25, 2022
FastAPI Learning Example,对应中文视频学习教程:https://space.bilibili.com/396891097

视频教学地址 中文学习教程 1、本教程每一个案例都可以独立跑,前提是安装好依赖包。 2、本教程并未按照官方教程顺序,而是按照实际使用顺序编排。 Video Teaching Address FastAPI Learning Example 1.Each case in this tutorial c

null 381 Dec 11, 2022
🤪 FastAPI + Vue构建的Mall项目后台管理

Mall项目后台管理 前段时间学习Vue写了一个移动端项目 https://www.charmcode.cn/app/mall/home 然后教程到此就结束了, 我就总感觉少点什么,计划自己着手写一套后台管理。 相关项目 移动端Mall项目源码(Vue构建): https://github.com/

王小右 131 Jan 1, 2023
Backend, modern REST API for obtaining match and odds data crawled from multiple sites. Using FastAPI, MongoDB as database, Motor as async MongoDB client, Scrapy as crawler and Docker.

Introduction Apiestas is a project composed of a backend powered by the awesome framework FastAPI and a crawler powered by Scrapy. This project has fo

Fran Lozano 54 Dec 13, 2022
Backend Skeleton using FastAPI and Sqlalchemy ORM

Backend API Skeleton Based on @tiangolo's full stack postgres template, with some things added, some things removed, and some things changed. This is

David Montague 18 Oct 31, 2022
FastAPI on Google Cloud Run

cloudrun-fastapi Boilerplate for running FastAPI on Google Cloud Run with Google Cloud Build for deployment. For all documentation visit the docs fold

Anthony Corletti 139 Dec 27, 2022
FastAPI + Django experiment

django-fastapi-example This is an experiment to demonstrate one potential way of running FastAPI with Django. It won't be actively maintained. If you'

Jordan Eremieff 78 Jan 3, 2023
Auth for use with FastAPI

FastAPI Auth Pluggable auth for use with FastAPI Supports OAuth2 Password Flow Uses JWT access and refresh tokens 100% mypy and test coverage Supports

David Montague 95 Jan 2, 2023
FastAPI Boilerplate

FastAPI Boilerplate Features SQlAlchemy session Custom user class Top-level dependency Dependencies for specific permissions Celery SQLAlchemy for asy

Hide 417 Jan 7, 2023
Minimal example utilizing fastapi and celery with RabbitMQ for task queue, Redis for celery backend and flower for monitoring the celery tasks.

FastAPI with Celery Minimal example utilizing FastAPI and Celery with RabbitMQ for task queue, Redis for Celery backend and flower for monitoring the

Grega Vrbančič 371 Jan 1, 2023
A simple docker-compose app for orchestrating a fastapi application, a celery queue with rabbitmq(broker) and redis(backend)

fastapi - celery - rabbitmq - redis -> Docker A simple docker-compose app for orchestrating a fastapi application, a celery queue with rabbitmq(broker

Kartheekasasanka Kaipa 83 Dec 19, 2022
fastapi-crud-sync

Developing and Testing an API with FastAPI and Pytest Syncronous Example Want to use this project? Build the images and run the containers: $ docker-c

null 59 Dec 11, 2022
FastAPI Skeleton App to serve machine learning models production-ready.

FastAPI Model Server Skeleton Serving machine learning models production-ready, fast, easy and secure powered by the great FastAPI by Sebastián Ramíre

null 268 Jan 1, 2023
row level security for FastAPI framework

Row Level Permissions for FastAPI While trying out the excellent FastApi framework there was one peace missing for me: an easy, declarative way to def

Holger Frey 315 Dec 25, 2022