nghttp2/doc/python.rst

581 lines
19 KiB
ReStructuredText

Spdylay Python Extension
========================
.. py:module:: spdylay
This is the Python extension of Spdylay library. The wrapping is made
using Cython. The extension provides mostly same APIs as original C
API. The API is still callback-centric. We use exceptions instead of
error code where they are appropriate.
Build
-----
To generate C source code from ``spdylay.pyx``, run ``cython``::
$ cython spdylay.pyx
To build extension, run ``setup.py``::
$ python setup.py build_ext
Session objects
---------------
.. py:class:: Session(side, version, config=None, send_cb=None, recv_cb=None, on_ctrl_recv_cb=None, on_data_chunk_recv_cb=None, on_stream_close_cb=None, on_request_recv_cb=None, user_data=None)
This is the class to hold the resources needed for a SPDY session.
Sending and receiving SPDY frames are done using the methods of
this class.
The *side* specifies server or client. Use one of the following:
.. py:data:: CLIENT
Indicates client.
.. py:data:: SERVER
Indicates server.
The *version* specifies SPDY protocol version. Use of the following:
.. py:data:: PROTO_SPDY2
Indicates SPDY/2.
.. py:data:: PROTO_SPDY3
Indicates SPDY/3.
The *user_data* specifies opaque object tied to this object. It
can be accessed through :py:attr:`user_data` attribute.
The *recv_cb* specifies callback function (callable) invoked when
the object wants to receive data from the remote peer. The
signature of this callback is:
.. py:function:: recv_cb(session, length)
The *session* is the :py:class:`Session` object invoking the
callback. The implementation of this function must read at
most *length* bytes of bytestring and return it. If it cannot
read any single byte without blocking, it must return empty
bytestring or ``None``. If it gets EOF before it reads any
single byte, it must raise :py:class:`EOFError`. For other
errors, it must raise :py:class:`CallbackFailureError`.
The *send_cb* specifies callback function (callable) invoked when
session wants to send data to the remote peer. The signature of
this callback is:
.. py:function:: send_cb(session, data)
The *session* is the :py:class:`Session` object invoking the
callback. The *data* is the bytestring to send. The
implementation of this function will send all or part of
*data*. It must return the number of bytes sent if it
succeeds. If it cannot send any single byte without blocking,
it must return 0 or ``None``. For other errors, it must return
:py:class:`CallbackFailureError`.
The *on_ctrl_recv_cb* specifies callback function (callable)
invoked when a control frame is received.
.. py:function:: on_ctrl_recv_cb(session, frame)
The *session* is the :py:class:`Session` object invoking the
callback. The *frame* is the received control
frame. ``frame.frame_type`` tells the type of frame. See
`Frame Types`_ for the details. Once the frame type is
identified, access attribute of the *frame* to get
information.
The *on_data_chunk_recv_cb* specifies callback function (callable)
invoked when a chunk of data in DATA frame is received.
.. py:function:: on_data_chunk_recv_cb(session, flags, stream_id, data)
The *session* is the :py:class:`Session` object invoking the
callback. The *stream_id* is the stream ID this DATA frame
belongs to. The *flags* is the flags of DATA frame which this
data chunk is contained. ``(flags & DATA_FLAG_FIN) != 0`` does
not necessarily mean this chunk of data is the last one in the
stream. You should use :py:func:`on_data_recv_cb` to know all
data frames are received. The *data* is the bytestring of
received data.
The *on_stream_close_cb* specifies callback function (callable)
invoked when the stream is closed.
.. py:function:: on_stream_close_cb(session, stream_id, status_code)
The *session* is the :py:class:`Session` object invoking the
callback. The *stream_id* indicates the stream ID. The reason
of closure is indicated by the *status_code*. See `Stream
Status Codes`_ for the details. The stream_user_data, which
was specified in :py:meth:`submit_request()` or
:py:meth:`submit_syn_stream()`, is still available in this
function.
The *on_request_recv_cb* specifies callback function (callable)
invoked when the request from the remote peer is received. In
other words, the frame with FIN flag set is received. In HTTP,
this means HTTP request, including request body, is fully
received.
.. py:function:: on_request_recv_cb(session, stream_id)
The *session* is the :py:class:`Session` object invoking the
callback. The *stream_id* indicates the stream ID.
The :py:class:`UnsupportedVersionError` will be raised if the
*version* is not supported. The :py:class:`ZlibError` will be
raised if initialization of zlib failed.
.. py:attribute:: Session.user_data
The object passed in the constructor as *user_data* argument.
This attribute is read-only.
.. py:method:: Session.send()
Sends pending frames to the remote peer. This method retrieves
the highest prioritized frame from the outbound queue and sends it
to the remote peer. It does this as many as possible until the
user callback :py:func:`send_cb` returns 0 or ``None`` or the
outbound queue becomes empty. This method calls several callback
functions which are passed when initializing the session. See
:func:`spdylay_session_send` about the callback functions invoked
from this method.
The :py:class:`CallbackFailureError` will be raised if the
callback function failed.
.. py:method:: Session.recv(data=None)
Receives frames from the remote peer. This method receives as
many frames as possible until the user callback :py:func:`recv_cb`
returns empty bytestring or ``None``. This function calls several
callback functions which are passed when initializing the session.
See :func:`spdylay_session_recv` about the callback functions
invoked from this method. If data is ``None``, this method will
invoke :py:func:`recv_cb` callback function to receive incoming
data. If data is not ``None``, it must be a bytestring and this
method uses it as the incoming data and does not call
:py:func:`recv_cb` callback function.
The :py:class:`EOFError` will be raised if the remote peer did
shutdown on the connection. The :py:class:`CallbackFailureError`
will be raised if the callback function failed.
.. py:method:: Session.resume_data(stream_id)
Puts back previously deferred DATA frame in the stream *stream_id*
to the outbound queue.
The :py:class:`InvalidArgumentError` will be raised if the stream
does not exist or no deferred data exist.
.. py:method:: Session.want_read()
Returns ``True`` if session wants to receive data from the
remote peer.
If both :py:meth:`want_read()` and :py:meth:`want_write()` return
``False``, the application should drop the connection.
.. py:method:: Session.want_write()
Returns ``True`` if session wants to send data to the remote peer.
If both :py:meth:`want_read()` and :py:meth:`want_write()` return
``False``, the application should drop the connection.
.. py:method:: Session.get_stream_user_data(stream_id)
Returns stream_user_data for the stream *stream_id*. The
stream_user_data is provided by :py:meth:`submit_request()` or
:py:meth:`submit_syn_stream()`. If the stream is initiated by the
remote endpoint, stream_user_data is always ``None``. If the
stream is initiated by the local endpoint and ``None`` is given in
:py:meth:`submit_request()` or :py:meth:`submit_syn_stream()`,
then this function returns ``None``. If the stream does not exist,
this function returns ``None``.
.. py:method:: Session.get_outbound_queue_size()
Returns the number of frames in the outbound queue. This does not
include the deferred DATA frames.
.. py:method:: Session.get_pri_lowest()
Returns lowest priority value for the session.
.. py:method:: Session.fail_session(status_code)
Submits GOAWAY frame. The status code *status_code* is ignored if
the protocol version is :py:const:`PROTO_SPDY2`.
This method should be called when the connection should be
terminated after sending GOAWAY. If the remaining streams should
be processed after GOAWAY, use :py:meth:`submit_goaway()` instead.
.. py:method:: Session.submit_request(pri, nv, data_prd=None, stream_user_data=None)
Submits SYN_STREAM frame and optionally one or more DATA frames.
The *pri* is priority of this request. ``0`` is the highest
priority value. Use :py:meth:`get_pri_lowest()` to know the lowest
priority value for this session.
The *nv* is a list containing the name/value pairs. The each
element is a tuple of 2 bytestrings: name and value (e.g.,
``(b'host', b'localhost')``).
The *nv* must include following name/value pairs:
``:method``
HTTP method (e.g., ``GET``, ``POST``, ``HEAD``, etc)
``:scheme``
URI scheme (e.g., ``https``)
``:path``
Absolute path and parameters of this request (e.g., ``/foo``,
``/foo;bar;haz?h=j&y=123``)
``:version``
HTTP version (e.g., ``HTTP/1.1``)
``:host``
The hostport portion of the URI for this request (e.g.,
``example.org:443``). This is the same as the HTTP “Host”
header field.
If the session is initialized with the version
:py:const:`PROTO_SPDY2`, the above names are translated to
``method``, ``scheme``, ``url``, ``version`` and ``host``
respectively.
The names in *nv* will be lower-cased when they are sent.
If *data_prd* is not ``None``, it provides data which will be sent
in subsequent DATA frames. In this case, a method that allows
request message bodies
(http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9) must
be specified with ``:method`` key in nv (e.g. ``POST``). The type
of *data_prd* is expected to be :py:class:`DataProvider`. If
*data_prd* is ``None``, SYN_STREAM have FLAG_FIN set.
.. note::
This method does not increase reference count of *data_prd*,
so the application must hold the reference to it until the
stream is closed.
The *stream_user_data* is data associated to the stream opened by
this request and can be an arbitrary object, which can be
retrieved later by :py:meth:`get_stream_user_data()`.
Since the library reorders the frames and tries to send the
highest prioritized one first and the SPDY specification requires
the stream ID must be strictly increasing, the stream ID of this
request cannot be known until it is about to sent. To know the
stream ID of the request, the application can use
:py:func:`before_ctrl_send_cb`. This callback is called just
before the frame is sent. For SYN_STREAM frame, the argument frame
has the stream ID assigned. Also since the stream is already
opened, :py:meth:`get_stream_user_data()` can be used to get
stream_user_data to identify which SYN_STREAM we are processing.
The :py:class:`InvalidArgumentError` will be raised if the *pri*
is invalid; or the *nv* includes empty name or ``None`` value.
.. py:method:: Session.submit_response(stream_id, nv, data_prd=None)
Submits SYN_REPLY frame and optionally one or more DATA frames
against the stream *stream_id*.
The *nv* is a list containing the name/value pairs. The each
element is a tuple of 2 bytestrings: name and value (e.g.,
``(b'host', b'localhost')``).
The *nv* must include following name/value pairs:
``:status``
HTTP status code (e.g., ``200`` or ``200 OK``)
``:version``
HTTP response version (e.g., ``HTTP/1.1``)
If the session is initialized with the version
:py:const:`PROTO_SPDY2`, the above names are translated to
``status`` and ``version`` respectively.
The names in *nv* will be lower-cased when they are sent.
If *data_prd* is not ``None``, it provides data which will be sent
in subsequent DATA frames. The type of *data_prd* is expected to
be :py:class:`DataProvider`. If *data_prd* is ``None``, SYN_REPLY
have FLAG_FIN set.
.. note::
This method does not increase reference count of *data_prd*,
so the application must hold the reference to it until the
stream is closed.
The :py:class:`InvalidArgumentError` will be raised if the *nv*
includes empty name or ``None`` value.
.. py:method:: Session.submit_syn_stream(flags, assoc_stream_id, pri, nv, stream_user_data)
Submits SYN_STREAM frame. The *flags* is bitwise OR of the
following values:
* :py:const:`CTRL_FLAG_FIN`
* :py:const:`CTRL_FLAG_UNIDIRECTIONAL`
If *flags* includes :py:const:`CTRL_FLAG_FIN`, this frame has
FLAG_FIN flag set.
The *assoc_stream_id* is used for server-push. Specify 0 if this
stream is not server-push. If session is initialized for client
use, *assoc_stream_id* is ignored.
The *pri* is priority of this request. ``0`` is the highest
priority value. Use :py:meth:`get_pri_lowest()` to know the lowest
priority value for this session.
The *nv* is a list containing the name/value pairs. The each
element is a tuple of 2 bytestrings: name and value (e.g.,
``(b'host', b'localhost')``).
The names in *nv* will be lower-cased when they are sent.
The *stream_user_data* is data associated to the stream opened by
this request and can be an arbitrary object, which can be
retrieved later by :py:meth:`get_stream_user_data()`.
This function is low-level in a sense that the application code
can specify flags and the Associated-To-Stream-ID directly. For
usual HTTP request, :py:meth:`submit_request()` is useful.
The :py:class:`InvalidArgumentError` will be raised if the *pri*
is invalid; or the *assoc_stream_id* is invalid; or the *nv*
includes empty name or ``None`` value.
.. py:method:: Session.submit_syn_reply(flags, stream_id, nv)
Submits SYN_REPLY frame. The *flags* is bitwise OR of the
following values:
* :py:const:`CTRL_FLAG_FIN`
If *flags* includes :py:const:`CTRL_FLAG_FIN`, this frame has
FLAG_FIN flag set.
The stream which this frame belongs to is given in the
*stream_id*. The *nv* is the name/value pairs in this frame.
The *nv* is a list containing the name/value pairs. The each
element is a tuple of 2 bytestrings: name and value (e.g.,
``(b'host', b'localhost')``).
The names in *nv* will be lower-cased when they are sent.
The :py:class:`InvalidArgumentError` will be raised if the *nv*
includes empty name or ``None`` value.
.. py:method:: Session.submit_headers(flags, stream_id, nv)
Submits HEADERS frame. The *flags* is bitwise OR of the following
values:
* :py:const:`CTRL_FLAG_FIN`
If *flags* includes :py:const:`CTRL_FLAG_FIN`, this frame has
FLAG_FIN flag set.
The stream which this frame belongs to is given in the
*stream_id*. The *nv* is the name/value pairs in this frame.
The *nv* is a list containing the name/value pairs. The each
element is a tuple of 2 bytestrings: name and value (e.g.,
``(b'host', b'localhost')``).
The names in *nv* will be lower-cased when they are sent.
The :py:class:`InvalidArgumentError` will be raised if the *nv*
includes empty name or ``None`` value.
.. py:method:: Session.submit_data(stream_id, flags, data_prd)
Submits one or more DATA frames to the stream *stream_id*. The
data to be sent are provided by *data_prd*. The type of
*data_prd* is expected to be :py:class:`DataProvider`. If *flags*
contains :py:const:`DATA_FLAG_FIN`, the last DATA frame has
FLAG_FIN set.
.. note::
This method does not increase reference count of *data_prd*,
so the application must hold the reference to it until the
stream is closed.
.. py:method:: Session.submit_rst_stream(stream_id, status_code)
Submits RST_STREAM frame to cancel/reject the stream *stream_id*
with the status code *status_code*. See `Stream Status Codes`_ for
available status codes.
.. py:method:: Session.submit_ping()
Submits PING frame.
.. py:method:: Session.submit_goaway(status_code)
Submits GOAWAY frame. The status code *status_code* is ignored if
the protocol version is :py:const:`PROTO_SPDY2`. See `GOAWAY
Status Codes`_ for available status codes.
.. py:method:: Session.submit_settings(flags, iv)
Stores local settings and submits SETTINGS frame. The *flags* is
bitwise OR of the values described in `SETTINGS Frame Flags`_.
The *iv* is a list of tuple ``(settings_id, flag, value)``. For
settings_id, see `SETTINGS IDs`_. For flag, see `SETTINGS ID
Flags`_.
The :py:class:`InvalidArgumentError` will be raised if the *iv*
contains duplicate settings ID or invalid value.
.. py:method:: Session.submit_window_update(stream_id, delta_window_size)
Submits WINDOW_UPDATE frame. The effective range of the
*delta_window_size* is ``[1, (1 << 31)-1]``, inclusive. But the
application must be responsible to keep the resulting window
``size <= (1 << 31)-1``.
The :py:class:`InvalidArgumentError` will be raised if the
*delta_window_size* is 0 or negative. The
:py:class:`StreamClosedError` will be raised if the stream is
already closed or does not exist.
Frame Types
-----------
.. py:data:: SYN_STREAM
.. py:data:: SYN_REPLY
.. py:data:: RST_STREAM
.. py:data:: SETTINGS
.. py:data:: NOOP
Note that this was deprecated in SPDY/3.
.. py:data:: PING
.. py:data:: GOAWAY
.. py:data:: HEADERS
.. py:data:: WINDOW_UPDATE
This first appeared in SPDY/3.
.. py:data:: CREDENTIAL
This first appeared in SPDY/3.
Control Frame Flags
-------------------
.. py:data:: CTRL_FLAG_NONE
Indicates no flags set.
.. py:data:: CTRL_FLAG_FIN
.. py:data:: CTRL_FLAG_UNIDIRECTIONAL
Stream Status Codes
-------------------
.. py:data:: OK
This is not a valid status code for RST_STREAM. Don't use this in
:py:meth:`Session.submit_rst_stream()`.
.. py:data:: PROTOCOL_ERROR
.. py:data:: INVALID_STREAM
.. py:data:: REFUSED_STREAM
.. py:data:: UNSUPPORTED_VERSION
.. py:data:: CANCEL
.. py:data:: INTERNAL_ERROR
.. py:data:: FLOW_CONTROL_ERROR
Following status codes were introduced in SPDY/3.
.. py:data:: STREAM_IN_USE
.. py:data:: STREAM_ALREADY_CLOSED
.. py:data:: INVALID_CREDENTIALS
.. py:data:: FRAME_TOO_LARGE
GOAWAY Status Codes
-------------------
.. py:data:: GOAWAY_OK
.. py:data:: GOAWAY_PROTOCOL_ERROR
.. py:data:: GOAWAY_INTERNAL_ERROR
SETTINGS Frame Flags
--------------------
.. py:data:: FLAG_SETTINGS_NONE
.. py:data:: FLAG_SETTINGS_CLEAR_SETTINGS
SETTINGS IDs
------------
.. py:data:: SETTINGS_UPLOAD_BANDWIDTH
.. py:data:: SETTINGS_DOWNLOAD_BANDWIDTH
.. py:data:: SETTINGS_ROUND_TRIP_TIME
.. py:data:: SETTINGS_MAX_CONCURRENT_STREAMS
.. py:data:: SETTINGS_CURRENT_CWND
.. py:data:: SETTINGS_DOWNLOAD_RETRANS_RATE
.. py:data:: SETTINGS_INITIAL_WINDOW_SIZE
.. py:data:: SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE
.. py:data:: SETTINGS_MAX
SETTINGS ID Flags
-----------------
.. py:data:: ID_FLAG_SETTINGS_NONE
.. py:data:: ID_FLAG_SETTINGS_PERSIST_VALUE
.. py:data:: ID_FLAG_SETTINGS_PERSISTED