Skip to main content

ASGI compliant web server

Project description

Qactuar

An ASGI compliant web server the goal of which is to support multiple asynchronous models. This started as a companion project to the Tonberry ASGI framework.

1. Post-Fork Multiprocessing

The first strategy is a post-fork model creating a new process for every request. This is the only model available right now.

2. Async/Await

The second strategy is one that a lot of current ASGI servers already do. In a single process just handle requests using asyncio/uvloop.

3. Pre-Fork Multiprocessing with Async/Await

Start up a pool of processes which can share a socket and each take a set number of requests and then handle them internally with async.

Installing

Just do the usual

$ pip install qactuar

Usage

During the install it creates a command line app.

Command Line

$ qactuar module:app

If your module is in the python path then it will get imported and any ASGI compatible object in the module can be called. If the apps are setup in the config (see Configuration section below) then you can just start up qactuar without any arguments.

$ qactuar

Programmatically

from tonberry import create_app, expose
from tonberry.content_types import TextPlain

import qactuar

class Root:
    @expose.get
    async def index(self) -> TextPlain:
        return "Hello, world!"


if __name__ == "__main__":
    app = create_app(Root)
    qactuar.run(app=app)
    # other keyword arguments for run() are host, port and conf

For a nice ASGI framework, check out Tonberry!

Configuration

File and programatic based configurations are supported. For a config file just create an environment variable QACTUAR_CONFIG and set the value to the absolute or relative path of a JSON file. This file can overwride any of the default values listed here. Only the values you wish to override need to be provided.

  • HOST: str = "localhost"
  • PORT: int = 8000
  • ADMIN_HOST: str = "localhost"
  • ADMIN_PORT: int = 1986
  • CHECK_PROCESS_INTERVAL: int = 1
  • SELECT_SLEEP_TIME: float = 0.025
  • RECV_TIMEOUT: float = 0.001
  • RECV_BYTES: int = 65536
  • MAX_PROCESSES: int = 500
  • GATHER_PROC_STATS: bool = False
  • REQUEST_TIMEOUT: float = 5
  • APPS: Dict[str, str] = {}
  • LOGS: Dict[str, Any] = default_log_setup (see below)

The APPS dictionary takes a route as the key and a module:app style string as the value. Multiple applications can be hosted at the same time by registering each at its own route. A basic example can be seen in the qactuar_config.json file.

The Config dataclass

The config is managed in a dataclass object and can be created programmatically. All arguments are optional and are defined above.

config = qactuar.Config(HOST='0.0.0.0')
qactuar.run(app=app, conf=config)

The LOGS dictionary is for the logging.config setup as detailed in the Python documentation here. It uses logging.config.dictConfig to set the logging configs. The loggers used throught the code are qt_server (used by the parent process), qt_child (used in the child processes), qt_access (used to log each request), qt_exception (used to log any exceptions)

Default Log Setup

{
    "version": 1,
    "disable_existing_loggers": false,
    "formatters": {
        "standard": {
            "format": "{asctime} {levelname} {message}",
            "style": "{"
        },
        "access": {
            "format": "{asctime} ACCESS {message}",
            "style": "{"
        }
    },
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "level": "DEBUG",
            "formatter": "standard",
            "stream": "ext://sys.stdout"
        },
        "access": {
            "class": "logging.StreamHandler",
            "level": "INFO",
            "formatter": "access",
            "stream": "ext://sys.stdout"
        },
        "exception": {
            "class": "logging.StreamHandler",
            "level": "ERROR",
            "formatter": "standard",
            "stream": "ext://sys.stderr"
        }
    },
    "loggers": {
        "qt_server": {
            "handlers": ["console"],
            "level": "DEBUG"
        },
        "qt_child": {
            "handlers": ["console"],
            "level": "DEBUG"
        },
        "qt_access": {
            "handlers": ["access"],
            "level": "INFO"
        },
        "qt_exception": {
            "handlers": ["exception"],
            "level": "ERROR"
        }
    }
}

If changing the LOGS config then the whole dictionary needs to be replaced. Individual parts of the log config cannot be changed by themselves.

Future Config Options

  • ASYNCRONOUS_MODEL: Enum = 1
  • SSL_CERT_PATH: str = ""
  • SSL_KEY_PATH: str = ""

Tornado Apps

Included is a utility wrapper to take a Tornado Request Handler and make it work with ASGI. See tornado_app.py for an example.

Admin

The plan is to support an extra socket connection that can accept connections for adminitrative purposes. Maybe for viewing system recources, viewing the processes and current load, changing configs on the fly, installing new apps via git clone without restarting the server. This is still in the works.

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests.

Versioning

SemVer is used for versioning. For the versions available, see the tags on this repository.

Authors

License

This project is licensed under the MIT License - see the LICENSE.txt file for details

TODO

  • Admin socket
  • UPD support
  • WebSockets
  • Send http.disconnect to app when each socket closes
  • Filter HTTP/2-3 pseudo headers
  • Client streaming, check "more_body" in send method
  • Async only model
  • Pre-Fork model
  • TESTS!!!
  • Docs

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

Qactuar-0.1.0.tar.gz (16.4 kB view details)

Uploaded Source

File details

Details for the file Qactuar-0.1.0.tar.gz.

File metadata

  • Download URL: Qactuar-0.1.0.tar.gz
  • Upload date:
  • Size: 16.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.42.0 CPython/3.8.1

File hashes

Hashes for Qactuar-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c8ab6cb7cec0056f0bd9b6bd44c337f338e7bcd1c73043a3d05a8b4ffd303084
MD5 c9f894c6028ce021fe46e09c8368e463
BLAKE2b-256 b4e94ea256e184731cb018d9f9596802b38b54945e1e24974a033f23dd7733d3

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