Package: esg
Enhanced Service Gateway.IntroductionESG is a speed-orientedASGIserver implementation with HTTP/1.1 and WebSockets support.Is a hard fork of the awesomeuvicornproject.Protocol implementation based on:llhttp- For HTTP payloadhttp-parser- For URL parsinghttptools- Clean and fast binding for the previous two. ESG Cython part development started from its forking.PerformanceSpeed comparison ESG vs UvicornPS>docker-composerun--rmbench-esg
Running15stest@http://esg:8000/4threadsand64connectionsThreadStatsAvgStdevMax+/-StdevLatency2.15ms390.13us9.51ms92.82%Req/Sec7.47k455.239.39k68.00%445749requestsin15.01s,66.32MBreadRequests/sec:29694.49
Transfer/sec:4.42MB
PS>docker-composerun--rmbench-uvicorn
Running15stest@http://uvicorn:8000/4threadsand64connectionsThreadStatsAvgStdevMax+/-StdevLatency4.03ms0.85ms16.28ms91.16%Req/Sec3.99k376.724.53k82.67%238272requestsin15.01s,36.36MBreadRequests/sec:15874.17
Transfer/sec:2.42MBQuickstartInstall usingpip:$pipinstallesg[standard]standartextra will also install:uvloopif applicable to system archwebsocketsif available *watchgodfor development's mode flag--reloadPyYAMLfor using*.yamlconfig files in--log-configparameterpython-dotenvfor enabling--env-fileparameter functionalitycoloramafor Windows users*If you want usewsprotoinstead ofwebsocketsyou'd need to install it manuallyRunning simple ASGI applicationCreate an application, inexample.py:asyncdefapp(scope,receive,send):assertscope['type']=='http'awaitsend({'type':'http.response.start','status':200,'headers':[[b'content-type',b'text/plain'],],})awaitsend({'type':'http.response.body','body':b'Hello, world!','more_body':False})Run the server:$esgexample:appASGI frameworksSquallSquallframework which looks ahead.High performance API framework.StarletteStarletteis a lightweight ASGI framework/toolkit.It is ideal for building high performance asyncio services, and supports both HTTP and WebSockets.Django ChannelsThe ASGI specification was originally designed for use withDjango Channels.Channels is a little different to other ASGI frameworks in that it provides
an asynchronous frontend onto a threaded-framework backend. It allows Django
to support WebSockets, background tasks, and long-running connections,
with application code still running in a standard threaded context.QuartQuartis a Flask-like ASGI web framework.FastAPIFastAPIis an API framework based onStarletteandPydantic, heavily inspired by previous server versions ofAPIStar.You write your API function parameters with Python 3.6+ type declarations and get automatic data conversion, data validation, OpenAPI schemas (with JSON Schemas) and interactive API documentation UIs.BlackSheepBlackSheepis a web framework based on ASGI, inspired by Flask and ASP.NET Core.Its most distinctive features are built-in support for dependency injection, automatic binding of parameters by request handler's type annotations, and automatic generation of OpenAPI documentation and Swagger UI.UsageThe ESG command line tool is the easiest way to run your application...Command line options$ esg --help
Usage: esg [OPTIONS] APP

Options:
  --host TEXT                     Bind socket to this host.  [default:
                                  127.0.0.1]
  --port INTEGER                  Bind socket to this port.  [default: 8000]
  --uds TEXT                      Bind to a UNIX domain socket.
  --fd INTEGER                    Bind to socket from this file descriptor.
  --reload                        Enable auto-reload.
  --reload-dir PATH               Set reload directories explicitly, instead
                                  of using the current working directory.
  --reload-include TEXT           Set glob patterns to include while watching
                                  for files. Includes '*.py' by default; these
                                  defaults can be overridden in `--reload-
                                  exclude`.
  --reload-exclude TEXT           Set glob patterns to exclude while watching
                                  for files. Includes '.*, .py[cod], .sw.*,
                                  ~*' by default; these defaults can be
                                  overridden in `--reload-include`.
  --reload-delay FLOAT            Delay between previous and next check if
                                  application needs to be. Defaults to 0.25s.
                                  [default: 0.25]
  --workers INTEGER               Number of worker processes. Defaults to the
                                  $WEB_CONCURRENCY environment variable if
                                  available, or 1. Not valid with --reload.
  --loop [auto|asyncio|uvloop]    Event loop implementation.  [default: auto]
  --ws [auto|none|websockets|wsproto]
                                  WebSocket protocol implementation.
                                  [default: auto]
  --ws-max-size INTEGER           WebSocket max size message in bytes
                                  [default: 16777216]
  --ws-ping-interval FLOAT        WebSocket ping interval  [default: 20.0]
  --ws-ping-timeout FLOAT         WebSocket ping timeout  [default: 20.0]
  --lifespan [auto|on|off]        Lifespan implementation.  [default: auto]
  --interface [auto|asgi3|asgi2|wsgi]
                                  Select ASGI3, ASGI2, or WSGI as the
                                  application interface.  [default: auto]
  --env-file PATH                 Environment configuration file.
  --log-config PATH               Logging configuration file. Supported
                                  formats: .ini, .json, .yaml.
  --log-level [critical|error|warning|info|debug|trace]
                                  Log level. [default: info]
  --access-log / --no-access-log  Enable/Disable access log.
  --use-colors / --no-use-colors  Enable/Disable colorized logging.
  --proxy-headers / --no-proxy-headers
                                  Enable/Disable X-Forwarded-Proto,
                                  X-Forwarded-For, X-Forwarded-Port to
                                  populate remote address info.
  --server-header / --no-server-header
                                  Enable/Disable default Server header.
  --date-header / --no-date-header
                                  Enable/Disable default Date header.
  --forwarded-allow-ips TEXT      Comma seperated list of IPs to trust with
                                  proxy headers. Defaults to the
                                  $FORWARDED_ALLOW_IPS environment variable if
                                  available, or '127.0.0.1'.
  --root-path TEXT                Set the ASGI 'root_path' for applications
                                  submounted below a given URL path.
  --limit-concurrency INTEGER     Maximum number of concurrent connections to
                                  allow, before issuing HTTP 503 responses.
  --backlog INTEGER               Maximum number of connections to hold in
                                  backlog
  --limit-max-requests INTEGER    Maximum number of requests to service before
                                  terminating the process.
  --timeout-keep-alive INTEGER    Close Keep-Alive connections if no new data
                                  is received within this timeout.  [default:
                                  5]
  --ssl-keyfile TEXT              SSL key file
  --ssl-certfile TEXT             SSL certificate file
  --ssl-keyfile-password TEXT     SSL keyfile password
  --ssl-version INTEGER           SSL version to use (see stdlib ssl module's)
                                  [default: 17]
  --ssl-cert-reqs INTEGER         Whether client certificate is required (see
                                  stdlib ssl module's)  [default: 0]
  --ssl-ca-certs TEXT             CA certificates file
  --ssl-ciphers TEXT              Ciphers to use (see stdlib ssl module's)
                                  [default: TLSv1]
  --header TEXT                   Specify custom default HTTP response headers
                                  as a Name:Value pair
  --version                       Display the esg version and exit.
  --app-dir TEXT                  Look for APP in the specified directory, by
                                  adding this to the PYTHONPATH. Defaults to
                                  the current working directory.  [default: .]
  --factory                       Treat APP as an application factory, i.e. a
                                  () -> <ASGI app> callable.  [default: False]
  --help                          Show this message and exit.Running programmaticallyTo run ESG directly from your applicationexample.py:importesgasyncdefapp(scope,receive,send):assertscope['type']=='http'awaitsend({'type':'http.response.start','status':200,'headers':[[b'content-type',b'text/plain'],],})awaitsend({'type':'http.response.body','body':b'Hello, world!','more_body':False})if__name__=="__main__":esg.run("example:app",host="127.0.0.1",port=5000,log_level="info")Running with GunicornGunicornis a mature, fully featured server and process manager.ESG includes a Gunicorn worker class allowing you to run ASGI applications,
with all of ESG's performance benefits, while also giving you Gunicorn's
fully-featured process management.This allows you to increase or decrease the number of worker processes on the
fly, restart worker processes gracefully, or perform server upgrades without downtime.For production deployments we recommend using gunicorn with the ESG worker class.gunicorn example:app -w 4 -k esg.workers.ESGWorkerFor more information, see thedeployment documentation.Application factoriesThe--factoryflag allows loading the application from a factory function, rather than an application instance directly. The factory will be called with no arguments and should return an ASGI application.example.py:defcreate_app():app=...returnapp$esg--factoryexample:create_appThe ASGI interfaceESG uses theASGI specificationfor interacting with an ASGI application.The application should expose an async callable which takes three arguments:scope- A dictionary containing information about the incoming connection.receive- A channel on which to receive incoming messages from the server.send- A channel on which to send outgoing messages to the server.Two common patterns you might use are either function-based applications:asyncdefapp(scope,receive,send):assertscope['type']=='http'...Or instance-based applications:classApp:asyncdef__call__(self,scope,receive,send):assertscope['type']=='http'...app=App()It's good practice for applications to raise an exception on scope types
that they do not handle.The content of thescopeargument, and the messages expected byreceiveandsenddepend on the protocol being used.The format for HTTP messages is described in theASGI HTTP Message format.HTTP ScopeAn incoming HTTP request might have a connectionscopelike this:{'type':'http.request','scheme':'http','root_path':'','server':('127.0.0.1',8000),'http_version':'1.1','method':'GET','path':'/','headers':[[b'host',b'127.0.0.1:8000'],[b'user-agent',b'curl/7.51.0'],[b'accept',b'*/*']]}HTTP MessagesThe instance coroutine communicates back to the server by sending messages to thesendcoroutine.awaitsend({'type':'http.response.start','status':200,'headers':[[b'content-type',b'text/plain'],]})awaitsend({'type':'http.response.body','body':b'Hello, world!',})Requests & responsesHere's an example that displays the method and path used in the incoming request:asyncdefapp(scope,receive,send):"""Echo the method and path back in an HTTP response."""assertscope['type']=='http'body=f'Received{scope["method"]}request to{scope["path"]}'awaitsend({'type':'http.response.start','status':200,'headers':[[b'content-type',b'text/plain'],]})awaitsend({'type':'http.response.body','body':body.encode('utf-8'),})Reading the request bodyYou can stream the request body without blocking the asyncio task pool,
by fetching messages from thereceivecoroutine.asyncdefread_body(receive):"""Read and return the entire body from an incoming ASGI message."""body=b''more_body=Truewhilemore_body:message=awaitreceive()body+=message.get('body',b'')more_body=message.get('more_body',False)returnbodyasyncdefapp(scope,receive,send):"""Echo the request body back in an HTTP response."""body=awaitread_body(receive)awaitsend({'type':'http.response.start','status':200,'headers':[[b'content-type',b'text/plain'],]})awaitsend({'type':'http.response.body','body':body,})Streaming responsesYou can stream responses by sending multiplehttp.response.bodymessages to
thesendcoroutine.importasyncioasyncdefapp(scope,receive,send):"""Send a slowly streaming HTTP response back to the client."""awaitsend({'type':'http.response.start','status':200,'headers':[[b'content-type',b'text/plain'],]})forchunkin[b'Hello',b', ',b'world!']:awaitsend({'type':'http.response.body','body':chunk,'more_body':True})awaitasyncio.sleep(1)awaitsend({'type':'http.response.body','body':b'',})Alternative ASGI serversUvicornThe most famous ASGI server. ESG development started from hard-forking of exactly Uvicorn.Uvicorn has a clean codebase and superior fast performance.$ pip install uvicorn
$ uvicorn app:AppDaphneThe first ASGI server implementation, originally developed to power Django Channels, isthe Daphne webserver.It is run widely in production, and supports HTTP/1.1, HTTP/2, and WebSockets.Any of the example applications given here can equally well be run usingdaphneinstead.$ pip install daphne
$ daphne app:AppHypercornHypercornwas initially part of the Quart web framework, before
being separated out into a standalone ASGI server.Hypercorn supports HTTP/1.1, HTTP/2, and WebSockets.$ pip install hypercorn
$ hypercorn app:AppRoadmapBetter security setting.Header timeoutBody timeout (timeout between calling receive and data arrive)Headers size limitRequest body size limitStatisticCythonized WebSocket protocol