Package: granian
GranianA Rust HTTP server for Python applications.RationaleThe main reasons behind Granian design are:Have a single, correct HTTP implementation, supporting versions 1, 2 (and eventually 3)Provide a single package for several platformsAvoid the usual Gunicorn + uvicorn + http-tools dependency composition on unix systemsProvide stableperformancewhen compared to existing alternativesFeaturesSupports ASGI/3,RSGIand WSGI interface applicationsImplements HTTP/1 and HTTP/2 protocolsSupports HTTPSSupports WebsocketsQuickstartYou can install Granian using pip:$ pip install granianCreate an ASGI application in yourmain.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!',})and serve it:$ granian --interface asgi main:appYou can also create an app using theRSGIspecification:asyncdefapp(scope,proto):assertscope.proto=='http'proto.response_str(status=200,headers=[('content-type','text/plain')],body="Hello, world!")and serve it using:$ granian --interface rsgi main:appOptionsYou can check all the options provided by Granian with the--helpcommand:$granian--help
Usage:granian[OPTIONS]APP

Arguments:APPApplicationtargettoserve.[required]Options:--hostTEXTHostaddresstobindto[envvar:GRANIAN_HOST;default:127.0.0.1]--portINTEGERPorttobindto.[envvar:GRANIAN_PORT;default:8000]--interface[asgi|rsgi|wsgi]Applicationinterfacetype[envvar:GRANIAN_INTERFACE;default:rsgi]--http[auto|1|2]HTTPversion[envvar:GRANIAN_HTTP;default:auto]--ws/--no-wsEnablewebsocketshandling[envvar:GRANIAN_WEBSOCKETS;default:(enabled)]--workersINTEGERRANGENumberofworkerprocesses[envvar:GRANIAN_WORKERS;default:1;x>=1]--threadsINTEGERRANGENumberofthreads[envvar:GRANIAN_THREADS;default:1;x>=1]--blocking-threadsINTEGERRANGENumberofblockingthreads[envvar:GRANIAN_BLOCKING_THREADS;default:1;x>=1]--threading-mode[runtime|workers]Threadingmodetouse[envvar:GRANIAN_THREADING_MODE;default:workers]--loop[auto|asyncio|uvloop]Eventloopimplementation[envvar:GRANIAN_LOOP;default:auto]--opt/--no-optEnableloopoptimizations[envvar:GRANIAN_LOOP_OPT;default:(disabled)]--backlogINTEGERRANGEMaximumnumberofconnectionstoholdinbacklog[envvar:GRANIAN_BACKLOG;default:1024;x>=128]--http1-buffer-sizeINTEGERRANGESetthemaximumbuffersizeforHTTP/1connections[envvar:GRANIAN_HTTP1_BUFFER_SIZE;default:417792;x>=8192]--http1-keep-alive/--no-http1-keep-aliveEnablesordisablesHTTP/1keep-alive[envvar:GRANIAN_HTTP1_KEEP_ALIVE;default:(enabled)]--http1-pipeline-flush/--no-http1-pipeline-flushAggregatesHTTP/1flushestobettersupportpipelinedresponses(experimental)[envvar:GRANIAN_HTTP1_PIPELINE_FLUSH;default:(disabled)]--http2-adaptive-window/--no-http2-adaptive-windowSetswhethertouseanadaptiveflowcontrolforHTTP2[envvar:GRANIAN_HTTP2_ADAPTIVE_WINDOW;default:(disabled)]--http2-initial-connection-window-sizeINTEGERSetsthemaxconnection-levelflowcontrolforHTTP2[envvar:GRANIAN_HTTP2_INITIAL_CONNECTION_WINDOW_SIZE;default:1048576]--http2-initial-stream-window-sizeINTEGERSetsthe`SETTINGS_INITIAL_WINDOW_SIZE`optionforHTTP2stream-levelflowcontrol[envvar:GRANIAN_HTTP2_INITIAL_STREAM_WINDOW_SIZE;default:1048576]--http2-keep-alive-intervalINTEGERSetsanintervalforHTTP2Pingframesshouldbesenttokeepaconnectionalive[envvar:GRANIAN_HTTP2_KEEP_ALIVE_INTERVAL;default:(disabled)]--http2-keep-alive-timeoutINTEGERSetsatimeoutforreceivinganacknowledgementoftheHTTP2keep-aliveping[envvar:GRANIAN_HTTP2_KEEP_ALIVE_TIMEOUT;default:20]--http2-max-concurrent-streamsINTEGERSetstheSETTINGS_MAX_CONCURRENT_STREAMSoptionforHTTP2connections[envvar:GRANIAN_HTTP2_MAX_CONCURRENT_STREAMS;default:200]--http2-max-frame-sizeINTEGERSetsthemaximumframesizetouseforHTTP2[envvar:GRANIAN_HTTP2_MAX_FRAME_SIZE;default:16384]--http2-max-headers-sizeINTEGERSetsthemaxsizeofreceivedheaderframes[envvar:GRANIAN_HTTP2_MAX_HEADERS_SIZE;default:16777216]--http2-max-send-buffer-sizeINTEGERSetthemaximumwritebuffersizeforeachHTTP/2stream[envvar:GRANIAN_HTTP2_MAX_SEND_BUFFER_SIZE;default:409600]--log/--no-logEnablelogging[envvar:GRANIAN_LOG_ENABLED;default:(enabled)]--log-level[critical|error|warning|warn|info|debug]Loglevel[envvar:GRANIAN_LOG_LEVEL;default:info]--log-configFILELoggingconfigurationfile(json)[envvar:GRANIAN_LOG_CONFIG]--ssl-keyfileFILESSLkeyfile[envvar:GRANIAN_SSL_KEYFILE]--ssl-certificateFILESSLcertificatefile[envvar:GRANIAN_SSL_CERTIFICATE]--url-path-prefixTEXTURLpathprefixtheappismountedon[envvar:GRANIAN_URL_PATH_PREFIX]--respawn-failed-workers/--no-respawn-failed-workersEnableworkersrespawnonunexpectedexit[envvar:GRANIAN_RESPAWN_FAILED_WORKERS;default:(disabled)]--reload/--no-reloadEnableautoreloadonapplication'sfileschanges(requiresgranian[reload]extra)[envvar:GRANIAN_RELOAD;default:(disabled)]--process-nameTEXTSetacustomnameforprocesses(requiresgranian[pname]extra)[envvar:GRANIAN_PROCESS_NAME]--versionShowstheversionandexit--install-completion[bash|zsh|fish|powershell|pwsh]Installcompletionforthespecifiedshell.[envvar:GRANIAN_INSTALL_COMPLETION]--show-completion[bash|zsh|fish|powershell|pwsh]Showcompletionforthespecifiedshell,tocopyitorcustomizetheinstallation.[envvar:GRANIAN_SHOW_COMPLETION]--helpShowthismessageandexit.Threading modeGranian offers two different threading paradigms, due to the fact the inner Rust runtime can be multi-threaded – in opposition to what happens in Python event-loop which can only run as a single thread.Given you specify N threads with the relevant option, inworkersthreading mode Granian will spawn N single-threaded Rust runtimes, while inruntimethreading mode Granian will spawn a single multi-threaded runtime with N threads.Benchmarks suggestsworkersmode to be more efficient with a small amount of processes, whileruntimemode seems to scale more efficiently where you have a large number of CPUs. Real performance will though depend on specific application code, and thusyour mileage might vary.Event loop optimizationsWith the--optoption Granian will use custom task handlers for Python coroutines and awaitables to improve Python code execution. Due to the nature of such handlers some libraries and specific application code relying onasynciointernals might not work.You might test the effect such optimizations cause over your application and decide whether to enable 'em or leave 'em disabled (as per default).Project statusGranian is currently under active development.Granian is compatible with Python 3.8 and above versions.LicenseGranian is released under the BSD License.