LinkedIn Sourceforge Twitter

Vincent's Blog

Pleasure in the job puts perfection in the work (Aristote)

Fapws4 a Fast Asynchronous Python Web Server

Posted on 2019-07-17 14:34:00 from Vincent in OpenBSD fapws

Fapws4 is a re-write of fapws3, but using libraries like libuv and picohttpparser. So, the goal is to build a very fast python web server where most of the processing aspects are written in C. The developer using it, will have to simply write the logic of his web pages in Python.


I'm a user of Fapws3 since several years. Initially I was using it inside small devices where the web server is the administration console of the device. Fapws3 do this task very well because his small memory and disk foot's print. Finally, after years of usage on those devices, and because of the simplicity of Fapws3, I'm using it on many different servers. One of the it is my blog, where Fapws3 has done the job during last 3 years. Since may 2019 it's served by Fapws4.

Fapws3 is existing since 2008! And is no more evolving since 2012. Few commits in 2015 and 2017.
Since then, the eco-system around webservers has changed : libuv, http parser. And most importantly, we have now python3.

So, it's a good opportunity to give it a fresh impulse to Fapws3. Moreover, as python's developer since 2003, jumping into such C programming aspects is a very fun challenge for me.

Pre-requisites to build Fapws4

As pre-requisites, you need to have libuv and python3.x installed.

On OpenBSD machines (my daily machine), you can get them by doing:

doas pkg_add python libuv

Please select python-3.x


To install fapws4, you just have to untar it, compile it and install it.

You can get the source code here. Then just perform the following commands:

tar -xzvf fapws4*.tgz
cd fapws4
sh build
sh install

If the build succeed, you can perform the install. No need to be root !!!

Please note that you do no need root (or doas, sudo) account to install it !!!!
Indeed, fapws4 will be installed in the user's local directory: ~/.local/bin/ and in ~/.local/lib/python3.x/site-packages/fapws4 (in my case x is 6, because I'm using python 3.6)

Please make sure that ~/.local/bin is in your PATH environment variable:

export PATH=~/.local/bin:$PATH

In fact, Fapws4 is not a python module. Fapws4 is an executable which embed python.
In the next paragraph, it's explained how to use it.

Doing this facilitate management of my different development environments (DEV, Acceptance, PROD) because they all have their respective chroot and userIDs. This is for security reasons.


Since Fapws4 is an executable embedding python, you have to adapt a little bit your code (and your Fapws3 programs):

  • Your code must have a PATHS object. This must be a list of tuples. Each tuple have 2 elements: uri, python object. Like for Fapws3, Fapws4 will look for the first uri having a path starting like the one the client is requesting. Once found, we execute the associated python object. Some samples here after will show how to use it.

  • Your python object triggered by a specific uri request, must have the following layout. Such python object must return a string object, a list object, a tuple object or a file object. Here after a sample with a string object returned.

    def test(environ, start_response):
    return "Hello world"

  • Your code must import Start_response and Environ from fapws4.base. Those objects will be instantiated and used by Fapws4 as parameters in your called object

    from fapws4.base import Start_response, Environ

  • Your code can contain the object SERVER (Optional). This object must be a string/unicode object with the form :[port]. Where ip is the IP on which your web server will listen. By default it's "". Port is an optional parameter specifying the port at which your web server must listen. By default it's 8888. For sure, if you want to run your Fapws4's webserver on port 80, you must start it with a root account.

  • Your code can contain the DEBUG object (optional). This object must be an integer. Currently it must be 1, 2 or 3. The default is 0 meaning no debug. This debug element is to debug libuv events. Except developers jumping into the C code of Fapws4, no one need it.

  • Your code can contain the MAX_BODY_SIZE object (Optional). This is an integer value indicating, in bytes, the maximum size of the http body, the client can send to your webserver. By default it's 10MB. If your http clients send you a file bigger than this value, Fapws4 will interrupt the connection by saying "input body too big".

Like the standard python executable code, you can use python libraries located in your usual PYTHONPATH. So, feel free to import all what you need for your web pages. In fact, the only impact is that you will run your script by using the Fapws4 binary instead of Python binary.


The usual sample is to return a simple text "Hello World!!".

from fapws4.base import Start_response, Environ

def hello(env, resp):
    return "Hello world!!"

PATHS = [('/', hello)]

Imagine that you save this code in a file called:

To execute it, you just have to provide this code to Fapws4:


Via your usual browser, go to and you ill receive your welcome message "Hello World!!".
You can also use wget or curl command:


You can retreive this code in the folder samples/hello/.


Side this the standard features of Fapws4, I've added some contribution copied (and slightly adapted) from Fapws3.

In, you can find "redirect". A method that send 301 or 302 HTTP response code.

In, you can find Staticfile. A class allowing you to easily add the management of static files to your python's webserver.


This code is written by me: Vincent Delft:

Since is heavily inspired by Fapws3 having a GPL2 license, Fapws4 is using the same license model.

I would prefer a more BSD like license, but I'm not an expert on that legal aspects. If there is a possibility to have a BSD license model, please explain it me.

39, 40
displayed: 6894

What is the first letter of the word Python?