Skip to main content

This python library allows you integrate async-await middleware-based system to your project

Project description

Middletools

Coverage Status Supported python version PyPI package version Downloads

This is a python library that allows you to integrate middlewares-based system to your project. It contains base tools for creating and running middlewares with async-await style

Installation

PyPI

python -m pip install middletools

GitHub

python -m pip install https://github.com/deknowny/middlewares/archive/main.zip

Usage

The main idea is give an ability just passing the middlewares and inbox/outbox payload values in a few methods instead of running and saving middlewares state by hand

Standard case: a function runs RESTful API routers and requires a middleware that checks a header in client's request


There are 2 endpoints for an abstract GET and POST methods

# Some abstract router
@router.get("/")
async def route_get(request):
    return 200, {"response": "some content"}


@router.post("/")
async def route_post(request):
    return 201, {"response": "ok"}

In the core of web framework you used a function like this that just call all routers

class Router:
    ...
    ...
    
    async def call_routers(self, request):
        for router in self.routers:
            ... # Pass request to routers and check it matched

middlewares library allows you easy integrate middleware system to your call_routers


Create middleware function

import middletools

...
...

# Adding a middleware handler to an abstract 
@router.add_middleware
async def my_middleware(
    request: SomeRequest, call_next: middletools.types.CallNext
) -> SomeResponse:
    # Just check if header exists, id not set the default value
    if "X-Required-Header" not in request.headers:
        request.header["X-Required-Header"] = "default"
    response = await call_next()
    return response

Here we add a header to client request if clint didn't do it. Then await call_next() give control to other middlewares or to our call_routers handler and response from this is the value call_next() returns


call_routers should looks like this

import typing

import middletools


class Router:
    # You can use generics to describe middleware hand;er
    middlewares: typing.List[
        middletools.types.MiddlewareHandler[
            SomeRequest, SomeResponse
        ]
    ]
    ...
    ...

    async def call_routers(self, request):
        read_afterwords = await middletools.read_forewords(
            *self.middlewares, inbox_value=request
        )
        for router in self.routers:
            ... # Pass request to routers and check it matched
            response = ...
            await read_afterwords(response)
            break
        

middlewares.read_forewords run middlewares until every one of them give control with await call_next(). When we do all our stuff and get the router response we can call await read_afterwords(response) and run all middlewares completely.

Notes

If a middleware doesn't call call_next() it raises middlewares.CallNextNotUsedError. It means that the middleware forcibly decline middlewares handlers and response should be sent immediately without routers running. call_routers should looks like this:

import middletools


async def call_routers(self, request):
    try:
        read_afterwords = await middletools.read_forewords(
            *self.middlewares, inbox_value=request
        )
        for router in self.routers:
            ... # Pass request to routers and check it matched
            response = ...
            await read_afterwords(response)
            return response
    except middletools.CallNextNotUsedError:
        return SomeBadResponseBecauseNotRouted(400, "Require a header!")
    

If a middleware doesn't return anything, middlewares dispatching declined forcibly too but after routers handled. (Return nothing means there isn't any return or return None used). It raises middlewares.NothingReturnedError

import middletools


async def call_routers(self, request):
    try:
        read_afterwords = await middletools.read_forewords(
            *self.middlewares, inbox_value=request
        )
        for router in self.routers:
            ... # Pass request to routers and check it matched
            response = ...
            await read_afterwords(response)
            return response
    except middletools.CallNextNotUsedError:
        return SomeBadResponseBecauseNotRouted(400, "Require a header!")
    except middletools.NothingReturnedError:
        return SomeBadResponseBecauseMiddlewareDntReturnResponse(
            500, "Oops, internal server error"
        )

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

middletools-0.1.2.tar.gz (5.5 kB view details)

Uploaded Source

Built Distribution

middletools-0.1.2-py3-none-any.whl (5.8 kB view details)

Uploaded Python 3

File details

Details for the file middletools-0.1.2.tar.gz.

File metadata

  • Download URL: middletools-0.1.2.tar.gz
  • Upload date:
  • Size: 5.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.4 CPython/3.9.1 Darwin/19.3.0

File hashes

Hashes for middletools-0.1.2.tar.gz
Algorithm Hash digest
SHA256 12d58c44258126dfac4f91d265aee9f42751745d1d9738d07cfdd9f0de14b77b
MD5 89285686b65f8445ef2534b6a068a582
BLAKE2b-256 67503acc5c10ce5772d4fc7fe62109da6d78d237e2ff1d833420195cba7d9fc3

See more details on using hashes here.

File details

Details for the file middletools-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: middletools-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 5.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.4 CPython/3.9.1 Darwin/19.3.0

File hashes

Hashes for middletools-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 6a2cef863244be65df4125e623d6b21056d351507b4faa917d25049673d8ad1d
MD5 ef3b3318cbe4d3efc087c2274001fb9a
BLAKE2b-256 47fbde15c09ec7a31cd270bffaec3b4dbb15840f8964e9371c24a2478b263118

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page