Learn how to write an HTTP / 2 server in Python using the Python API included in nghttp2.
The Python API is provided as an extension library using the nghttp2 C library. Python 3.4 or later is required because the code that provides the HTTP / 2 server uses the ʻasynciomodule. Build the extension library. Requires the Python 3.4 development package and Cython. Ubuntu 14.04 LTS accepts the python3.4-dev and cython packages. The configure script automatically chooses the available Python environment, but by default I think Python is not 3.4 in many cases, so explicitly specify the path of the Python 3.4 interpreter with the
PYTHON` variable and give it to the configure script:
$ ./configure PYTHON=/usr/bin/python3.4
make install
will install the nghttp2 C library and the Python extension library. If you don't want to install it, you can specify the respective directories with LD_LIBRARY_PATH
and PYTHONPATH
.
Now that you're ready, let's write a server. We'll use the nghttp2.HTTP2Server
and nghttp2.BaseRequestHandler
classes. The nghttp2.HTTP2Server
class will listen for connections, run event loops, etc. A class that provides server functionality. Nghttp2.BaseRequestHandler
is a class that handles one stream (HTTP request). There is a callback method that fires for each event, and it is subclassed and these callback methods are implemented appropriately and streamed. Let's take a look at a simple server implementation that returns "nghttp2 FTW" first, leaving a detailed explanation later:
import ssl
import nghttp2
class Handler(nghttp2.BaseRequestHandler):
def on_headers(self):
res = b'nghttp2 FTW\n'
self.send_response(status=200,
headers = [('content-length', str(len(res)))],
body=res)
# SSL/To enable TLS,Certificate server.crt,Private key server.in the key file
#Save,Enable the following 3 lines, nghttp2.Specify ctx for the HTTP2Server ssl parameter.
# ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
# ctx.options = ssl.OP_ALL | ssl.OP_NO_SSLv2
# ctx.load_cert_chain('server.crt', 'server.key')
server = nghttp2.HTTP2Server(('127.0.0.1', 8080), Handler, ssl=None)
server.serve_forever()
When run, it listens on port 8080. Accessing on nghttp http://127.0.0.1:8080/
should return the characters" nghttp2 FTW ".
Let's take a closer look at nghttp2.BaseRequestHandler
.
nghttp2.BaseRequestHandler
provides the following instance variables:
: scheme
header field.: method
header field.: authority
or host
header field.: path
header field.The following describes the callback method. The above example implements the ʻon_headers () `method. This method is called when the request header is received. There are other callback methods as well: ..
To return the response, use the send_response (status = 200, headers = None, body = None)
method as in the example above. * Status * specifies the HTTP status code. * Headers * is Specify additional response headers. * Body * is the response body, which specifies an instance of the str
, byte
or ʻio.Base` subclass.
It also provides a push (path, method ='GET', request_headers = None, status = 200, headers = None, body = None)
method for doing Server Push, which is one of the features of HTTP / 2. Server Push requires you to specify the request path and method that the client will use when requesting the resources that the server pushes, and additional request header fields. * Path *, * method *, *, respectively. It is specified by request_headers *. The remaining * status *, * headers *, * body * specify the content of the response in the same way as the send_response ()
method.
Let's add Server Push to the above example. Let's push resources in the request path / push:
class Handler(nghttp2.BaseRequestHandler):
def on_headers(self):
self.push(path='/push',
status=200,
body='pushed content')
res = b'nghttp2-python FTW\n'
self.send_response(status=200,
headers = [('content-length', str(len(res)))],
body=res)
...
You can see that it is being pushed by accessing it with the nghttp command line tool. Although the number of streams to be multiplexed is limited, multiple pushes can be specified. Also, due to protocol restrictions, push ( )
Must be called beforesend_response ()
.
So far we've shown you how to write an HTTP / 2 server using the nghttp2 Python API. For a detailed API, see Documentation (https://nghttp2.org/documentation/python-apiref.html).
Recommended Posts