Giter Club home page Giter Club logo

fastapi-gateway's Introduction

https://scrutinizer-ci.com/g/dotX12/fastapi-gateway/ https://scrutinizer-ci.com/g/dotX12/fastapi-gateway/ https://scrutinizer-ci.com/g/dotX12/fastapi-gateway/ https://badge.fury.io/py/fastapi-gateway https://pepy.tech/project/fastapi-gateway https://pepy.tech/project/fastapi-gateway https://github.com/dotX12/fastapi-gateway/blob/master/LICENSE

⚙️ fastapi-gateway is async single entry point for microservices.

API Gateway performs many tasks: accepts, processes and distributes requests, controls traffic, monitors and controls access and security, caching, throttling.

Initially, this project was created for myself, I needed to implement identification, authentication and authorization. In the future, there was a need to limit requests for each user on every endpoint, create API plans. There were a lot of microservices and to keep in each microservice the logic for limiting endpoints, security logic, logging etc. - meaningless. Therefore, all this functionality is located at a single entry point, which already implements all the necessary tasks with security, limiting, etc., while microservices now directly solve their tasks.

💿 Installation

pip install fastapi_gateway

❗️ Benchmark

1.5k - 3k RPC.

gitshit@git ~ % wrk -t 4 -c 40 http://gateway.localtest.me:8003/gateway_endpoint/path_param/12
Running 10s test @ http://gateway.localtest.me:8003/gateway_endpoint/path_param/12
  4 threads and 40 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    30.11ms   33.65ms 312.55ms   95.98%
    Req/Sec   395.03    218.80     0.89k    73.21%
  15550 requests in 10.05s, 2.31MB read
Requests/sec:   1547.81
Transfer/sec:    235.81KB

💻 Example

Example of use (long code)
from starlette import status
from starlette.requests import Request
from starlette.responses import Response
from fastapi_gateway import route
from fastapi import FastAPI
from pydantic import BaseModel
from fastapi import Depends
from fastapi.security import APIKeyHeader
from starlette import status
from starlette.exceptions import HTTPException

app = FastAPI(title='API Gateway')
SERVICE_URL = "http://microservice.localtest.me:8002"

API_KEY_NAME = "x-api-key"

api_key_header = APIKeyHeader(
    name=API_KEY_NAME,
    auto_error=False
)


def check_api_key(key: str = Depends(api_key_header)):
    if key:
        return key
    raise HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="You didn't pass the api key in the header! Header: x-api-key",
    )


class FooModel(BaseModel):
    example_int: int
    example_str: str


@route(
    request_method=app.post,
    service_url=SERVICE_URL,
    gateway_path='/query_and_body_path/{path}',
    service_path='/v1/query_and_body_path/{path}',
    query_params=['query_int', 'query_str'],
    body_params=['test_body'],
    status_code=status.HTTP_200_OK,
    tags=['Query', 'Body', 'Path'],
    dependencies=[
        Depends(check_api_key)
    ],
)
async def check_query_params_and_body(
        path: int, query_int: int, query_str: str,
        test_body: FooModel, request: Request, response: Response
):
    pass

See more examples here:

🪛 How to use?

  • request_method - is a callable (like app.get, app.post, foo_router.patch and so on.).
  • service_url - the path to the endpoint on another service (like "https://microservice1.example.com").
  • service_path - the path to the method in microservice (like "/v1/microservice/users").
  • gateway_path - is the path to bind gateway.
    For example, your gateway api is located here - https://gateway.example.com and the path to endpoint (gateway_path) - "/users" then the full way to this method will be - https://gateway.example.com/users
  • override_headers - Boolean value allows you to return all the headlines that were created by microservice in gateway.
  • query_params - used to extract query parameters from endpoint and transmission to microservice
  • form_params - used to extract form model parameters from endpoint and transmission to microservice
  • param body_params - used to extract body model from endpoint and transmission to microservice

⚠️ - Be sure to transfer the name of the argument to the router, which is in the endpoint func!

query_params - List[Query]
body_params - List[Body]
form_params - List[File, Form]
In more detail how to transmit body, form and query (photo)

fastapi-gateway's People

Contributors

dotx12 avatar uk1996 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

fastapi-gateway's Issues

Unprocessable Entity with OAuth2PasswordRequestForm

Hello I am using the gateway as reverse proxy for all my backend. I have an issue to process OAuth2PasswordRequestForm. The microservice throw this error " 172.19.0.1:59754 - "POST /api/login HTTP/1.1" 422 Unprocessable Entity".

{"detail":[{"loc":["body","username"],"msg":"field required","type":"value_error.missing"},{"loc":["body","password"],"msg":"field required","type":"value_error.missing"}]}

The method definition of my micoservice is defined by this code:


async def login(self, user_signin: OAuth2PasswordRequestForm = Depends(),
                    session: AsyncSession = Depends(get_session)):
      

The gateway definition is :

@staticmethod
    @route(
        request_method=api_gateway_account_settings_router.post,
        service_url=SERVICE_URL,
        gateway_path='/api/login',
        service_path='/api/login',
        query_params=[],
        form_params=['user_signin'],
        status_code=status.HTTP_200_OK,
        tags=['account_settings'],
        response_model=Any
    )
    @pm_logger
    async def login(request: Request, response: Response, user_signin: OAuth2PasswordRequestForm = Depends()):
        pass

reuseable_oauth = OAuth2PasswordBearer(
    tokenUrl="/api/login",
    scheme_name="JWT"
)

image

I'm trying to run the PyPI model.

Exception has occurred: ImportError
cannot import name 'SetIntStr' from 'fastapi.encoders' (c:\Users\202665\Documents\Trabalho\0188_api_gatway.venv\lib\site-packages\fastapi\encoders.py)
File "C:\Users\202665\Documents\Trabalho\0188_api_gatway\teste2.py", line 4, in
from fastapi_gateway import route
ImportError: cannot import name 'SetIntStr' from 'fastapi.encoders' (c:\Users\202665\Documents\Trabalho\0188_api_gatway.venv\lib\site-packages\fastapi\encoders.py)

I would like to request pull by putting the mock server function in this library. Is it possible?

Hello, I am a developer who is developing a gateway using the fastapi_gateway library. But when the service to connect to the gateway was not developed, I wanted to use the gateway as a mock server. Therefore, by adding the bool type mock parameter of the route decoder, I will distinguish whether the corresponding API of the gateway is connected to the service, and if the mock is True, I will respond to the sample data added to the responses parameter. Is this effective in your opinion? If you think it's efficient, Is it okay if I develop the function and make a pull request?

route throw error when it deserialize a StreamingResponse/FileResponse (Fastapi)

Hello.
I'm having trouble downloading PDF files from the microservice. I suppose that the maqueRequest method only decodes JSON responses. In my example, the gateway throws an exception since the microservice returns a StreamingResponse.

with async_timeout.timeout(delay=timeout):
        async with aiohttp.ClientSession(headers=headers) as session:
            async with session.request(
                    method=method, url=url, params=query, data=data) as response:
                response_json = await response.json()
                decoded_json = decode_json(data=response_json)
                return decoded_json, response.status, response.headers

My method signature

@pmrush_billing_information_router.get("/api/billing/invoices/download/{invoice_number}", response_model=Any,
                                          tags=["billing_information"])
   @pm_logger
   async def download_invoice(self, invoice_number: str, auth_user: UserInfoResponse = Depends(get_current_user)):

      ......

       invoice_pdf = requests.get(download_link, stream=True)
       output = BytesIO(invoice_pdf.content)
       output.seek(0)
       headers = {
           'Content-Disposition': 'attachment; filename="invoice.pdf"'
       }
       return StreamingResponse(output, headers=headers)

Api gateway signature:

@staticmethod
   @route(
       request_method=api_gateway_billing_information_router.get,
       service_url=SERVICE_URL,
       gateway_path='/api/billing/invoices/download/{invoice_number}',
       service_path='/api/billing/invoices/download/{invoice_number}',
       query_params=["invoice_number"],
       body_params=[],
       status_code=status.HTTP_200_OK,
       tags=['billing_information'],
       response_model=Any
   )
   @pm_logger
   async def download_invoice(invoice_number: str, request: Request, response: Response,
                              token: str = Depends(reuseable_oauth)):
       pass

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.