From 03e2dabea93f2a41fe40c64b1c8726c3940d7b0b Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Tue, 13 May 2014 21:46:39 +0900 Subject: [PATCH] doc: Add Python API doc --- doc/python-apiref.rst | 1 + doc/sources/index.rst | 1 + doc/sources/python-apiref.rst | 319 ++++++++++++++++++++++++++++++++++ 3 files changed, 321 insertions(+) create mode 100644 doc/python-apiref.rst create mode 100644 doc/sources/python-apiref.rst diff --git a/doc/python-apiref.rst b/doc/python-apiref.rst new file mode 100644 index 00000000..50040627 --- /dev/null +++ b/doc/python-apiref.rst @@ -0,0 +1 @@ +.. include:: ../doc/sources/python-apiref.rst diff --git a/doc/sources/index.rst b/doc/sources/index.rst index 448bc470..aa73f2e1 100644 --- a/doc/sources/index.rst +++ b/doc/sources/index.rst @@ -21,6 +21,7 @@ Contents: tutorial-server nghttpx-howto apiref + python-apiref nghttp2.h nghttp2ver.h Source diff --git a/doc/sources/python-apiref.rst b/doc/sources/python-apiref.rst new file mode 100644 index 00000000..2996149e --- /dev/null +++ b/doc/sources/python-apiref.rst @@ -0,0 +1,319 @@ +Python API Reference +==================== + +.. py:module:: nghttp2 + +nghttp2 offers some high level Python API to C library. The bindings +currently provide HPACK compressor and decompressor classes and HTTP/2 +server class. + +The extension module is called ``nghttp2``. + +``make`` will build the bindings. The target Python version is +determined by configure script. If the detected Python version is not +what you expect, specify a path to Python executable in ``PYTHON`` +variable as an argument to configure script (e.g., ``./configure +PYTHON=/usr/bin/python3.4``). + +HPACK API +--------- + +.. py:class:: HDDeflater(hd_table_bufsize_max=DEFLATE_MAX_HEADER_TABLE_SIZE) + + This class is used to perform header compression. The + *hd_table_bufsize_max* limits the usage of header table in the + given amount of bytes. The default value is + :py:data:`DEFLATE_MAX_HEADER_TABLE_SIZE`. This is necessary + because the deflater and inflater share the same amount of header + table and the inflater decides that number. The deflater may not + want to use all header table size because of limited memory + availability. In that case, *hd_table_bufsize_max* can be used to + cap the upper limit of table size whatever the header table size is + chosen by the inflater. + + .. py:method:: deflate(headers) + + Deflates the *headers*. The *headers* must be sequence of tuple + of name/value pair, which are byte strings (not unicode string). + + This method returns the deflated header block in byte string. + Raises the exception if any error occurs. + + .. py:method:: set_no_refset(no_refset) + + Tells the deflater not to use reference set if *no_refset* is + evaluated to ``True``. If that happens, on each subsequent + invocation of :py:meth:`deflate()`, deflater will clear up + refersent set. + + .. py:method:: change_table_size(hd_table_bufsize_max) + + Changes header table size to *hd_table_bufsize_max* byte. if + *hd_table_bufsize_max* is strictly larger than + ``hd_table_bufsize_max`` given in constructor, + ``hd_table_bufsize_max`` is used as header table size instead. + + Raises the exception if any error occurs. + + .. py:method:: get_hd_table() + + Returns copy of current dynamic header table. + +The following example shows how to deflate header name/value pairs: + +.. code-block:: python + + import binascii, nghttp2 + + deflater = nghttp2.HDDeflater() + + res = deflater.deflate([(b'foo', b'bar'), + (b'baz', b'buz')]) + + print(binascii.b2a_hex(res)) + + +.. py:class:: HDInflater() + + This class is used to perform header decompression. + + .. py:method:: inflate(data) + + Inflates the deflated header block *data*. The *data* must be + byte string. + + Raises the exception if any error occurs. + + .. py:method:: change_table_size(hd_table_bufsize_max) + + Changes header table size to *hd_table_bufsize_max* byte. + + Raises the exception if any error occurs. + + .. py:method:: get_hd_table() + + Returns copy of current dynamic header table. + +The following example shows how to inflate deflated header block: + +.. code-block:: python + + deflater = nghttp2.HDDeflater() + + data = deflater.deflate([(b'foo', b'bar'), + (b'baz', b'buz')]) + + inflater = nghttp2.HDInflater() + + hdrs = inflater.inflate(data) + + print(hdrs) + + +.. py:function:: print_hd_table(hdtable) + + Convenient function to print *hdtable* to the standard output. The + *hdtable* is the one retrieved by + :py:meth:`HDDeflater.get_hd_table()` or + :py:meth:`HDInflater.get_hd_table()`. This function does not work + if header name/value cannot be decoded using UTF-8 encoding. + + In output, ``s=N`` means the entry occupies ``N`` bytes in header + table. If ``r=y``, then the entry is in the reference set. + +.. py:data:: DEFAULT_HEADER_TABLE_SIZE + + The default header table size, which is 4096 as per HTTP/2 + specification. + +.. py:data:: DEFLATE_MAX_HEADER_TABLE_SIZE + + The default header table size for deflater. The initial value + is 4096. + +HTTP/2 servers +-------------- + +.. note:: + + We use :py:mod:`asyncio` for HTTP/2 server classes. Therefore, + Python 3.4 or later is required to use these objects. To + explicitly configure nghttp2 build to use Python 3.4, specify the + ``PYTHON`` variable to the path to Python 3.4 executable when + invoking configure script like this:: + + $ ./configure PYTHON=/usr/bin/python3.4 + +.. py:class:: HTTP2Server(address, RequestHandlerClass, ssl=None) + + This class builds on top of the :py:mod:`asyncio` event loop. On + construction, *RequestHandlerClass* must be given, which must be a + subclass of :py:class:`BaseRequestHandler` class. + + The *address* must be a tuple of hostname/IP address and port to + bind. If hostname/IP address is ``None``, all interfaces are + assumed. + + To enable SSL/TLS, specify instance of :py:class:`ssl.SSLContext` + in *ssl*. Before passing *ssl* to + :py:func:`BaseEventLoop.create_server`, ALPN protocol identifiers + are set using :py:meth:`ssl.SSLContext.set_npn_protocols`. + + To disable SSL/TLS, omit *ssl* or specify ``None``. + + .. py:method:: serve_forever() + + Runs server and processes incoming requests forever. + +.. py:class:: BaseRequestHandler(http2, stream_id) + + The class is used to handle the single HTTP/2 stream. By default, + it does not nothing. It must be subclassed to handle each event + callback method. + + The first callback method invoked is :py:meth:`on_headers()`. It is + called when HEADERS frame, which includes request header fields, is + arrived. + + If request has request body, :py:meth:`on_data()` is invoked for + each chunk of received data chunk. + + When whole request is received, :py:meth:`on_request_done()` is + invoked. + + When stream is closed, :py:meth:`on_close()` is called. + + The application can send response using :py:meth:`send_response()` + method. It can be used in :py:meth:`on_headers()`, + :py:meth:`on_data()` or :py:meth:`on_request_done()`. + + The application can push resource using :py:meth:`push()` method. + It must be used before :py:meth:`send_response()` call. + + A :py:class:`BaseRequestHandler` has the following instance + variables: + + .. py:attribute:: client_address + + Contains a tuple of the form ``(host, port)`` referring to the + client's address. + + .. py:attribute:: stream_id + + Stream ID of this stream + + .. py:attribute:: scheme + + Scheme of the request URI. This is a value of ``:scheme`` + header field. + + .. py:attribute:: method + + Method of this stream. This is a value of ``:method`` header + field. + + .. py:attribute:: host + + This is a value of ``:authority`` or ``host`` header field. + + .. py:attribute:: path + + This is a value of ``:path`` header field. + + A :py:class:`BaseRequestHandler` has the following methods: + + .. py:method:: on_headers() + + Called when request HEADERS is arrived. By default, this method + does nothing. + + .. py:method:: on_data(data) + + Called when a chunk of request body *data* is arrived. This + method will be called multiple times until all data are + received. By default, this method does nothing. + + .. py:method:: on_request_done() + + Called when whole request was received. By default, this method + does nothing. + + .. py:method:: on_close(error_code) + + Called when stream is about to close. The *error_code* + indicates the reason of closure. If it is ``0``, the stream is + going to close without error. + + .. py:method:: send_response(status=200, headers=None, body=None) + + Send response. The *status* is HTTP status code. The *headers* + is additional response headers. The *:status* header field will + be appended by the library. The *body* is the response body. + It could be ``None`` if response body is empty. Or it must be + instance of either ``str``, ``bytes`` or :py:class:`io.IOBase`. + If instance of ``str`` is specified, it will be encoded using + UTF-8. + + The *headers* is a list of tuple of the form ``(name, + value)``. The ``name`` and ``value`` can be either byte string + or unicode string. In the latter case, they will be encoded + using UTF-8. + + Raises the exception if any error occurs. + + .. py:method:: push(path, method='GET', request_headers=None, status=200, headers=None, body=None) + + Push a specified resource. The *path* is a path portion of + request URI for this resource. The *method* is a method to + access this resource. The *request_headers* is additional + request headers to access this resource. The ``:scheme``, + ``:method``, ``:authority`` and ``:path`` are appended by the + library. The ``:scheme`` and ``:authority`` are inherited from + request header fields of the associated stream. + + The *status* is HTTP status code. The *headers* is additional + response headers. The ``:status`` header field is appended by + the library. The *body* is the response body. It could be + ``None`` if response body is empty. Or it must be instance of + either ``str``, ``bytes`` or ``io.IOBase``. If instance of + ``str`` is specified, it is encoded using UTF-8. + + The headers and request_headers are a list of tuple of the form + ``(name, value)``. The ``name`` and ``value`` can be either byte + string or unicode string. In the latter case, they will be + encoded using UTF-8. + + Returns an instance of ``RequestHandlerClass`` specified in + :py:class:`HTTP2Server` constructor for the pushed resource. + + Raises the exception if any error occurs. + +The following example illustrates :py:class:`HTTP2Server` and +:py:class:`BaseRequestHandler` usage: + +.. code-block:: python + + #!/usr/bin/env python + + import io, ssl + import nghttp2 + + class Handler(nghttp2.BaseRequestHandler): + + def on_headers(self): + self.push(path='/css/style.css', + request_headers = [('content-type', 'text/css')], + status=200, + body='body{margin:0;}') + + self.send_response(status=200, + headers = [('content-type', 'text/plain')], + body=io.BytesIO(b'nghttp2-python FTW')) + + ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + ctx.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 + ctx.load_cert_chain('server.crt', 'server.key') + + # give None to ssl to make the server non-SSL/TLS + server = nghttp2.HTTP2Server(('127.0.0.1', 8443), Handler, ssl=ctx) + server.serve_forever()