Skip to main content

Simple FastCGI

simple FastCGI protocol parser and sync/async handler in pure python

Example 1: echo (sync)

import json
from simple_fastcgi import *

class example_handler(HttpResponseMixin, FcgiHandler):
	def handle(self):
		self.send_response(200, json = self.environ)

if __name__ == "__main__":
	with FcgiServer(example_handler) as server:
		server.serve_forever()

Example 2: dir listing (async)

import os
import json
import asyncio
from functools import partial
from urllib.parse import parse_qs
from simple_fastcgi import *


async def dir_listing(path):
	with os.scandir(path) as it:
		for entry in it:
			record = {
				"name": entry.name
			}
			try:
				if entry.is_dir():
					record["type"] = "dir"
				elif entry.is_file():
					record["type"] = "file"
				else:
					continue

				stat = entry.stat()
				record["size"] = stat.st_size
				record["mtime"] = int(stat.st_mtime * 1000)
			except Exception:
				pass

			line = json.dumps(record, ensure_ascii = False) + '\n'
			yield line


class dir_listing_handler(AsyncHttpResponseMixin, AsyncFcgiHandler):
	async def handle(self):
		try:
			doc_root = self.environ["DOCUMENT_ROOT"]
			query = parse_qs(self.environ["QUERY_STRING"])
			path = query["path"][0].lstrip("/.")

			func = partial(dir_listing, os.path.join(doc_root, path))
			return await self.send_response(200, "application/x-ndjson", data = func)
		except Exception as e:
			return await self.send_response(404)


async def main():
	async with AsyncFcgiServer(dir_listing_handler) as server:
		await server.serve_forever()

if __name__ == "__main__":
	asyncio.run(main())

API reference

The import module name is simple_fastcgi

Exceptions

ProtocolError

Raised when encountered FastCGI protocol violations.

Handlers

class FcgiHandler

FastCGI Handler, subclass of BaseRequestHandler. To implement your own handler, subclass FcgiHandler and override the handle() method.

environ

Member environ is a dictionary containing key-value pairs from the webserver. The keys are converted to upper-case.

server

Member server refers to the server object that creates this handler.

handle()

Override this method and do all the work here to serve a request.

aborted()

Check if the FastCGI request has been aborted by the webserver.

read(sz = -1)

Read and return up to sz bytes from input stream. If sz < 0, read until EOF. Returns empty bytes object on EOF.

readinto(buffer)

Read from input stream into buffer, return the actual read byte count. Returns 0 on EOF.

readall()

Read input stream until EOF and return all the data.

write(data)

Write data to the output stream.

write_err(data)

Write data to the error stream.

flush()

Flush the buffered data to underlying socket.

class AsyncFcgiHandler

Async variant of FcgiHandler. methods are the same, except being async.

environ

server

async handle()

aborted()

async read(sz = -1)

async readinto(buffer)

async readall()

async write(data)

async write_err(data)

async flush()

Servers

class FcgiServer

Subclass of BaseServer, but listening on passed in socket or FCGI_LISTENSOCK_FILENO ( fd 0 ). Can be used with context manager.

__init__(handler, sock = None)

Initialize a server object. Subclass may override and do extra initialization.

handler is the handler-class which is instantiated on each request.

sock is a listening socket on which the server is running. defaults to sys.stdin in conforming to FastCGI Specification.

fileno()

Get the underlying fd of the server object.

shutdown()

Stop the server.

serve_forever()

Start the server and block until shutdown.

service_actions()

Called in serve_forever loop. Subclass may override and do their own actions.

class AsyncFcgiServer

Async variant of FcgiServer. methods are the same, except being async. Can be used with async context manager.

Note there is no service_actions() in AsyncFcgiServer, since it runs on event loop instead of its own loop, and one can easily schedule tasks to event loop.

__init__(handler, sock = None)

fileno()

get_loop()

Get the event loop on which the server is running.

async shutdown()

async serve_forever()

Mixins

class HttpResponseMixin

Helper mixin class for FcgiServer, to construct CGI/HTTP responses.

send_response(code, /, mime_type = None, data = None, *, json = None, extra_headers = [])

Construct a CGI document response and write to output stream.

code is the HTTP status code of the response.

mime_type is the content-type of the response. Default to "text/plain", or "application/json" if json is not None.

extra_headers is the extra HTTP header fields that should be included in the response header.

data is the payload of the response.

  • if data is a function, it is assumed to be a generator and called to get chunks of data.
  • if data is a string, it is encoded in UTF-8.
  • if "json" appears in mime_type and data is not bytes-like, try to encode data as json.
  • else, append data to payload as-is.

If json is not None, it is serialized using json.dumps and as payload of the response.

If data is a function, each data chunk is followed by a flush.

If data, json and mime_type are all None, the payload would be the HTTP status code and description.

data and json should not be specified at the same time.

Note that you can mix this method with write() calls. For example, you can call this method, passing first data chunk as data parameter, followed by multiple write() calls to append more data.

Also note that this method does not calculate or append a content-length header for you. You need to handle content-length header yourself, either omit this header, or calculate in advance.

If data is a function and raises before yielding any data, no response (including the header) is sent out. You can then call send_response again, possibly with different parameters.

send_redirect(target)

Construct a CGI redirect response and write to output stream.

target is the redirect target, it can be either local-Location or client-Location as defined in CGI Specification.

AsyncHttpResponseMixin

Async variant of HttpResponseMixin. methods are the same, except being async

async send_response(code, /, mime_type = None, data = None, *, json = None, extra_headers = [])

Note that if data is a function, it is assumed to be an async generator instead.

async send_redirect(target)

Reference

Metadata

Release files for simple-fastcgi 0.0.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for simple-fastcgi 0.0.7
File Size Uploaded
simple_fastcgi-0.0.7.tar.gz 12.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for simple-fastcgi 0.0.7
File Interpreter ABI Platform
simple_fastcgi-0.0.7-py3-none-any.whl Python 3 none any Details

Total release size: 23.5 kB

Release files / simple_fastcgi-0.0.7.tar.gz

Download URL simple_fastcgi-0.0.7.tar.gz
Size 12.2 kB
Tags Source
SHA-256 checksum
How to use checksums
b3dea671239b3418967557d94d82d108930ae2ae366423ade62218d5f4be0bca
BLAKE2b-256 checksum
How to use checksums
23a79bc381fef2133d3c9a89a506c298ff9f13469beebaef1d65c819241ed8df
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / simple_fastcgi-0.0.7-py3-none-any.whl

Download URL simple_fastcgi-0.0.7-py3-none-any.whl
Size 11.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e7eaa026b455cb202586603ec875348e2e6c2b19fdf5f612117118c1b7006a22
BLAKE2b-256 checksum
How to use checksums
7a8c2c28ce507d9840ff83a65b8fa1493167d08c4a396e9d4e9216e9b4f75d79
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.0.7 This release

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page