Package: fastcgi
fastcgiFastCGI and HTTP handlers for Python'ssocketserverclassesFastCGIis a way for front-end servers to talk to back-end workers in a (somewhat) efficient and (somewhat) simple way. Although it's been around since 1996, it is not very widely appreciated, except in the PHP community, where it is very commonly used.It can be a great approach for hosting Python scripts, avoiding the overhead of creating a new Python process for every request (as standard CGI would otherwise require) and without requiring large dependencies, complex C projects, or fiddly deployments.fastcgihas no dependencies other thanfastcore.There's no new frameworks or concepts to learn. Just callsendto send anything you like back to the client, read the parameters fromparams, and the input from the client fromstdin.fastcgirequires a front-end web server. If you don't already have one set up, we recommendCaddy. To forward all requests toexample.comto afastcgiserver listening on port 1234 create a file calledCaddyfilewith the following contents, and thencaddy run:example.com
reverse_proxy localhost:1234 { transport fastcgi }This library also provides an HTTP handler that can be used in an identical way, except remove{ transport fastcgi }from the aboveCaddyfileexample. Python's standard library already includes an HTTP handler (inhttp.server), however the documentation warns that that module should not be used in production code. The HTTP handler provided here is trimmed down to a minimal implementation (just 40 lines of code) so that it can easily be studied and extended. It uses the same basic API as Python's othersocketserverclasses (and the same asFcgiHandlerhere) so there's fewer new concepts to understand.Installpip install fastcgiorconda install -c fastai fastcgiHow to useSee the full docs pages for each class for details. Quick overviews of each approach are shown below.fastcgi decoratorUsing thefastcgidecorator you can use CGI scripts with minimal changes. Just add the decorator above a function used for CGI, and it converts that script automatically into a FastCGI server, e.g if you save this asserver.py:@fastcgi()defhello():query=os.environ["QUERY_STRING"]content=sys.stdin.read()sys.stdout.write(f"Content-type: text/html\r\n\r\n<html>{content}; ")sys.stdout.write(f"{query}</html>\r\n")...then if you runpython server.pyit will make a unix socket available asfcgi.sockin the current directory.FcgiHandlerFcgiHandleris used in much the same way as Python'sBaseRequestHandler. Here's an example:classTestHandler(FcgiHandler):defhandle(self):print('query:',self.environ['QUERY_STRING'])print('content type:',self.environ['HTTP_CONTENT_TYPE'])print('stdin:',self['stdin'].read())self['stdout'].write(b"Content-type: text/html\r\n\r\n<html>foobar</html>\r\n")You can run this using any of Python'ssocketserverclasses, e.g to listen on localhost port 1234:withTCPServer(('localhost',1234),TestHandler)assrv:srv.handle_request()See the API docs forFcgiHandlerfor an end-to-end example.You can also create a forking or threading server by using Python'smixins or predefined classes.In yourhandlemethod, you can use thestdin,stdout, andstderrattributes, which each contain aBytesIOstream.MinimalHTTPHandlerfastcgialso comes with theMinimalHTTPHandlerclass, which provides very similar functionality toFcgiHandler, but using theHTTPprotocol instead of theFastCGIprotocol. Here's an example:class_TestHandler(MinimalHTTPHandler):defhandle(self):print(f'Command/path/version:{self.command}{self.path}{self.request_version}')print(self.headers)self.send_response(200)self.send_header("Content-Type","text/plain")self.send_header('Content-Length','2')self.end_headers()self.wfile.write(b'ok')You can run it with asocketserverserver in the same way shown above forFcgiHandler.