Python-spdylay - Spdylay Python Extension Module

Python-spdylay is the Python extension module of Spdylay SPDY C library.

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

class spdylay.Session(side, version, config=None, send_cb=None, recv_cb=None, on_ctrl_recv_cb=None, on_invalid_ctrl_recv_cb=None, on_data_chunk_recv_cb=None, on_data_recv_cb=None, before_ctrl_send_cb=None, on_ctrl_send_cb=None, on_ctrl_not_send_cb=None, on_data_send_cb=None, on_stream_close_cb=None, on_request_recv_cb=None, on_ctrl_recv_parse_error_cb=None, on_unknown_ctrl_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:

CLIENT

Indicates client.

SERVER

Indicates server.

The version specifies SPDY protocol version. Use of the following:

PROTO_SPDY2

Indicates SPDY/2.

PROTO_SPDY3

Indicates SPDY/3.

The user_data specifies opaque object tied to this object. It can be accessed through 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:

recv_cb(session, length)

The session is the 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 EOFError. For other errors, it must raise 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:

send_cb(session, data)

The session is the 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 CallbackFailureError.

The on_ctrl_recv_cb specifies callback function (callable) invoked when a control frame is received.

on_ctrl_recv_cb(session, frame)

The session is the 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_invalid_ctrl_recv_cb specifies callback function (callable) invoked when an invalid control frame is received.

on_invalid_ctrl_recv_cb(session, frame, status_code)

The session is the 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 status_code is one of the Stream Status Codes and indicates the error. When this callback function is invoked, either RST_STREAM or GOAWAY will be sent.

The on_data_chunk_recv_cb specifies callback function (callable) invoked when a chunk of data in DATA frame is received.

on_data_chunk_recv_cb(session, flags, stream_id, data)

The session is the 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 on_data_recv_cb() to know all data frames are received. The data is the bytestring of received data.

The on_data_recv_cb specifies callback function (callable) invoked when DATA frame is received.

on_data_recv_cb(session, flags, stream_id, length)

The actual data it contains are received by on_data_chunk_recv_cb().

The before_ctrl_send_cb specifies callback function (callable) invoked before the control frame is sent.

before_ctrl_send_cb(session, frame)

The session is the Session object invoking the callback. The frame is the control frame to be sent. 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_ctrl_send_cb specifies callback function (callable) invoked after the control frame is sent.

on_ctrl_send_cb(session, frame)

The session is the Session object invoking the callback. The frame is the control frame to be sent. 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_ctrl_not_send_cb specifies callback function (callable) after the control frame is not sent because of the error.

on_ctrl_not_send_cb(session, frame, error_code)

The session is the 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 error_code is one of the Error Codes and indicates the error.

The on_data_send_cb specifies callback function (callable) invoked after DATA frame is sent.

on_data_send_cb(session, flags, stream_id, length)

The on_stream_close_cb specifies callback function (callable) invoked when the stream is closed.

on_stream_close_cb(session, stream_id, status_code)

The session is the 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 submit_request() or 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.

on_request_recv_cb(session, stream_id)

The session is the Session object invoking the callback. The stream_id indicates the stream ID.

The on_ctrl_recv_parse_error_cb specifies callback function (callable) invoked when the received control frame octets could not be parsed correctly.

on_ctrl_recv_parse_error_cb(session, type, head, payload, error_code)

The type indicates the type of received control frame. The head is the bytestring of control frame header. The payload is the bytestring of data portion of the received frame. The error_code is one of the error code defined in Error Codes and indicates the error.

The on_unknown_ctrl_recv_cb specifies callback function (callable) invoked when the received control frame type is unknown.

on_unknown_ctrl_recv_cb(session, head, payload)

The head is the bytestring of control frame header. The payload is the bytestring of data portion of the received frame.

The InvalidArgumentError will be raised if the given argument is invalid. The UnsupportedVersionError will be raised if the version is not supported. The ZlibError will be raised if initialization of zlib failed.

Session.user_data

The object passed in the constructor as user_data argument. This attribute is read-only.

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 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 spdylay_session_send() about the callback functions invoked from this method.

The CallbackFailureError will be raised if the callback function failed.

Session.recv(data=None)

Receives frames from the remote peer. This method receives as many frames as possible until the user callback recv_cb() returns empty bytestring or None. This function calls several callback functions which are passed when initializing the session. See spdylay_session_recv() about the callback functions invoked from this method. If data is None, this method will invoke 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 recv_cb() callback function.

The EOFError will be raised if the remote peer did shutdown on the connection. The CallbackFailureError will be raised if the callback function failed.

Session.resume_data(stream_id)

Puts back previously deferred DATA frame in the stream stream_id to the outbound queue.

This method returns True if it succeeds, or False. This method will fail if the stream does not exist or no deferred data exist.

Session.want_read()

Returns True if session wants to receive data from the remote peer.

If both want_read() and want_write() return False, the application should drop the connection.

Session.want_write()

Returns True if session wants to send data to the remote peer.

If both want_read() and want_write() return False, the application should drop the connection.

Session.get_stream_user_data(stream_id)

Returns stream_user_data for the stream stream_id. The stream_user_data is provided by submit_request() or 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 submit_request() or submit_syn_stream(), then this function returns None. If the stream does not exist, this function returns None.

Session.get_outbound_queue_size()

Returns the number of frames in the outbound queue. This does not include the deferred DATA frames.

Session.get_pri_lowest()

Returns lowest priority value for the session.

Session.fail_session(status_code)

Submits GOAWAY frame. The status code status_code is ignored if the protocol version is 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 submit_goaway() instead.

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 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 pair of unicode strings: name and value (e.g., (u'host', u'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 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 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 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 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, get_stream_user_data() can be used to get stream_user_data to identify which SYN_STREAM we are processing.

The InvalidArgumentError will be raised if the pri is invalid; or the nv includes empty name or None value.

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 pair of unicode strings: name and value (e.g., (u'host', u'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 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 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 InvalidArgumentError will be raised if the nv includes empty name or None value.

Session.submit_syn_stream(flags, pri, nv, assoc_stream_id=0, stream_user_data=None)

Submits SYN_STREAM frame. The flags is bitwise OR of the following values:

If flags includes 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 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 pair of unicode strings: name and value (e.g., (u'host', u'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 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, submit_request() is useful.

The 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.

Session.submit_syn_reply(flags, stream_id, nv)

Submits SYN_REPLY frame. The flags is bitwise OR of the following values:

If flags includes 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 pair of unicode strings: name and value (e.g., (u'host', u'localhost')).

The names in nv will be lower-cased when they are sent.

The InvalidArgumentError will be raised if the nv includes empty name or None value.

Session.submit_headers(flags, stream_id, nv)

Submits HEADERS frame. The flags is bitwise OR of the following values:

If flags includes 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 pair of unicode strings: name and value (e.g., (u'host', u'localhost')).

The names in nv will be lower-cased when they are sent.

The InvalidArgumentError will be raised if the nv includes empty name or None value.

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 DataProvider. If flags contains 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.

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.

Session.submit_ping()

Submits PING frame.

Session.submit_goaway(status_code)

Submits GOAWAY frame. The status code status_code is ignored if the protocol version is PROTO_SPDY2. See GOAWAY Status Codes for available status codes.

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 InvalidArgumentError will be raised if the iv contains duplicate settings ID or invalid value.

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 InvalidArgumentError will be raised if the delta_window_size is 0 or negative. The StreamClosedError will be raised if the stream is already closed or does not exist.

Helper Functions

spdylay.get_npn_protocols()

Returns SPDY version strings which can be directly passed to ssl.SSLContext.set_npn_protocols(). Please note that the returned list only includes SPDY version strings this library supports. If the application intends to support other fallback protocols (e.g., http/1.1), the application should add them to the returned list.

spdylay.npn_get_version(proto)

Returns SPDY version which spdylay library supports from the given protocol name. The proto is the unicode string to the protocol name. Currently, spdy/2 and spdy/3 are supported. The returned nonzero SPDY version can be passed as the version argument in Session constructor.

This function returns nonzero SPDY version if it succeeds, or 0.

Data Provider Objects

class spdylay.DataProvider(source, read_cb)

This class represents the data source and the way to read a chunk of data from it. The source is expected to be the data source to read, but the application can freely pass any object including None. The read_cb is the callback function invoked when the library needs to read data. The data read will be sent as DATA frame.

read_cb(session, stream_id, length, read_ctrl, source)

The session is the Session object. The stream_id is the stream to send data. The source is the object passed as a source in DataProvider constructor. The implementation of this callback must read at most length bytes of data and return it as bytestring. When all data is read, assign READ_EOF to read_ctrl.flags. If the application wants to postpone DATA frames, (e.g., asynchronous I/O, or reading data blocks for long time), it is achieved by returning ERR_DEFERRED without reading any data in this invocation. The library removes DATA frame from the outgoing queue temporarily. To move back deferred DATA frame to outgoing queue, call Session.resume_data(). In case of error, there are 2 choices. Raising TemporalCallbackFailureError will close the stream by issuing RST_STREAM with INTERNAL_ERROR. Raising CallbackFailureError will signal the entire session failure.

DataProvider.source
DataProvider.read_cb

Control Frame Objects

class spdylay.CtrlFrame

The base class of SPDY control frames.

version

Version

frame_type

Frame type. See Frame Types.

flags

Flags. See Control Frame Flags.

length

Frame payload length

The following frame classes inherit CtrlFrame class.

class spdylay.SynStreamFrame
stream_id

Stream ID

assoc_stream_id

Associated-To-Stream-ID

pri

Priority

slot

Credential slot

nv

List of name/value pair.

class spdylay.SynReplyFrame
stream_id

Stream ID

nv

List of name/value pair.

class spdylay.HeadersFrame
stream_id

Stream ID

nv

List of name/value pair.

class spdylay.RstStreamFrame
stream_id

Stream ID

status_code

Status code

class spdylay.SettingsFrame
iv

List of tuple (settings_id, flags, value)

class spdylay.PingFrame
unique_id

Unique ID

class spdylay.GoawayFrame
last_good_stream_id

Last good stream ID

status_code

Status code

class spdylay.WindowUpdateFrame
stream_id

Stream ID

delta_window_size

Delta window size

Exceptions

class spdylay.EOFError
class spdylay.CallbackFailureError
class spdylay.TemporalCallbackFailureError
class spdylay.InvalidArgumentError
class spdylay.ZlibError
class spdylay.UnsupportedVersionError
class spdylay.StreamClosedError

Read Callback Flags

spdylay.READ_EOF

Error Codes

spdylay.ERR_INVALID_ARGUMENT
spdylay.ERR_ZLIB
spdylay.ERR_UNSUPPORTED_VERSION
spdylay.ERR_WOULDBLOCK
spdylay.ERR_PROTO
spdylay.ERR_INVALID_FRAME
spdylay.ERR_EOF
spdylay.ERR_DEFERRED
spdylay.ERR_STREAM_ID_NOT_AVAILABLE
spdylay.ERR_STREAM_CLOSED
spdylay.ERR_STREAM_CLOSING
spdylay.ERR_STREAM_SHUT_WR
spdylay.ERR_INVALID_STREAM_ID
spdylay.ERR_INVALID_STREAM_STATE
spdylay.ERR_DEFERRED_DATA_EXIST
spdylay.ERR_SYN_STREAM_NOT_ALLOWED
spdylay.ERR_GOAWAY_ALREADY_SENT
spdylay.ERR_INVALID_HEADER_BLOCK
spdylay.ERR_INVALID_STATE
spdylay.ERR_GZIP
spdylay.ERR_TEMPORAL_CALLBACK_FAILURE

Following error codes indicate fatal error.

spdylay.ERR_FATAL
spdylay.ERR_NOMEM
spdylay.ERR_CALLBACK_FAILURE

Frame Types

spdylay.SYN_STREAM
spdylay.SYN_REPLY
spdylay.RST_STREAM
spdylay.SETTINGS
spdylay.NOOP

Note that this was deprecated in SPDY/3.

spdylay.PING
spdylay.GOAWAY
spdylay.HEADERS
spdylay.WINDOW_UPDATE

This first appeared in SPDY/3.

spdylay.CREDENTIAL

This first appeared in SPDY/3.

Control Frame Flags

spdylay.CTRL_FLAG_NONE

Indicates no flags set.

spdylay.CTRL_FLAG_FIN
spdylay.CTRL_FLAG_UNIDIRECTIONAL

Stream Status Codes

spdylay.OK

This is not a valid status code for RST_STREAM. Don’t use this in Session.submit_rst_stream().

spdylay.PROTOCOL_ERROR
spdylay.INVALID_STREAM
spdylay.REFUSED_STREAM
spdylay.UNSUPPORTED_VERSION
spdylay.CANCEL
spdylay.INTERNAL_ERROR
spdylay.FLOW_CONTROL_ERROR

Following status codes were introduced in SPDY/3.

spdylay.STREAM_IN_USE
spdylay.STREAM_ALREADY_CLOSED
spdylay.INVALID_CREDENTIALS
spdylay.FRAME_TOO_LARGE

GOAWAY Status Codes

spdylay.GOAWAY_OK
spdylay.GOAWAY_PROTOCOL_ERROR
spdylay.GOAWAY_INTERNAL_ERROR

SETTINGS Frame Flags

spdylay.FLAG_SETTINGS_NONE
spdylay.FLAG_SETTINGS_CLEAR_SETTINGS

SETTINGS IDs

spdylay.SETTINGS_UPLOAD_BANDWIDTH
spdylay.SETTINGS_DOWNLOAD_BANDWIDTH
spdylay.SETTINGS_ROUND_TRIP_TIME
spdylay.SETTINGS_MAX_CONCURRENT_STREAMS
spdylay.SETTINGS_CURRENT_CWND
spdylay.SETTINGS_DOWNLOAD_RETRANS_RATE
spdylay.SETTINGS_INITIAL_WINDOW_SIZE
spdylay.SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE
spdylay.SETTINGS_MAX

SETTINGS ID Flags

spdylay.ID_FLAG_SETTINGS_NONE
spdylay.ID_FLAG_SETTINGS_PERSIST_VALUE
spdylay.ID_FLAG_SETTINGS_PERSISTED

Simple SPDY Client

This module offers a simple SPDY client implementation. The function urlfetch() fetches given URLs. For each URL, StreamHandlerClass is instantiated and its methods are called when certain event occurs. The StreamHandlerClass must be a subclass of BaseSPDYStreamHandler.

spdylay.urlfetch(url_or_urls, StreamHandlerClass)

Opens URL and handles the response from the servers.

The url_or_urls is either one URL string or list of URL string. For each URL, StreamHandlerClass is instantiated and it handles the request to and response from the server. If successive URLs in url_or_urls list have same origin, they are processed in one SPDY session.

class spdylay.BaseSPDYStreamHandler(url, fetcher)

This class handles one URL retrieval, which corresponds one SPDY stream. The url is the URL to fetch. The fetcher is a driver object to call methods of this object. For now it is opaque object. This class is intended to be subclassed by the application to add specific behavior.

BaseSPDYStreamHandler has the following instance variables:

url

The URL for this stream.

stream_id

The stream ID for this stream.

BaseSPDYStreamHandler has the following methods:

on_header(nv)

Called when name/value pairs (headers) nv is received. This method may be overridden by subclasses. The default implementation does nothing.

on_data(data)

Called when data is received. This method may be overridden by subclass. The default implementation does nothing.

on_close(status_code)

Called when this stream is closed. The status_code indicates the reason of the closure. See Stream Status Codes. This method may be overridden by subclass. The default implementation does nothing.

The example follows:

#!/usr/bin/env python

# The example SPDY client.  You need Python 3.3 or later because we
# use TLS NPN.
#
# Usage: spdyclient.py URL...
#
import sys
import spdylay

class MyStreamHandler(spdylay.BaseSPDYStreamHandler):
    def on_header(self, nv):
        sys.stdout.write('Stream#{}\n'.format(self.stream_id))
        for k, v in nv:
            sys.stdout.write('{}: {}\n'.format(k, v))

    def on_data(self, data):
        sys.stdout.write('Stream#{}\n'.format(self.stream_id))
        sys.stdout.buffer.write(data)

    def on_close(self, status_code):
        sys.stdout.write('Stream#{} closed\n'.format(self.stream_id))

if __name__ == '__main__':
    uris = sys.argv[1:]
    spdylay.urlfetch(uris, MyStreamHandler)

Simple SPDY Server

This module offers a simple SPDY server implementation to ready for use with little additional code.

The ThreadedSPDYServer is a socketserver.TCPServer subclass. As the name of the class suggests, it is multi threaded. It only supports SPDY connection and does not fallback to HTTP/1.1. Since it uses TLS NPN extension, Python 3.3.0 or later is required.

class spdylay.ThreadedSPDYServer(server_address, RequestHandlerCalss, cert_file, key_file)

This class builds on TCPServer class by passing server_address and RequestHandlerCalss. The request is handled by the instance of RequestHandlerCalss.

The ThreadedSPDYServer requires a RequestHandlerCalss on instantiation, which must be a subclass of BaseSPDYRequestHandler.

Most texts are copied (and modified) from http.server documentation.

class spdylay.BaseSPDYRequestHandler(request, client_address, server)

This class is used to handle the SPDY requests (streams) that arrive at the server. By itself, it cannot respond to any actual SPDY requests; it must be subclassed to handle each request method (e.g. GET or POST). BaseSPDYRequestHandler provides a number of class and instance variables, and methods for use by subclasses.

The handler will gather headers (name/value pairs in SPDY terms) and read POST data (if any), then call a method specific to the request type. The method name is constructed from the request. For example, for the request method SPAM, the do_SPAM() method will be called with no arguments. All of the relevant information is stored in instance variables of the handler. Subclasses should not need to override or extend the __init__() method.

Note

Currently, this implementation accepts request body only if method is POST and the request body will be stored in memory.

BaseSPDYRequestHandler has the following instance variables:

client_address

Contains a tuple of the form (host, port) referring to the client’s address.

server

Contains the server instance.

command

Contains the command (request type, method). For example, GET.

path

Contains the request path.

request_version

Contains the version string from the request. For example, HTTP/1.1.

headers

Contains the request headers. Each name/value pair is a tuple of the form (name, value).

rfile

Contains an input stream, positioned at the start of the optional input data. If there is no optional input data, it may be None.

wfile

Contains the output stream for writing a response back to the client.

BaseSPDYRequestHandler has the following class variables:

server_version

Specifies the server software version.

sys_version

Contains the Python system version.

A BaseSPDYRequestHandler instance has the following methods:

handle()

Interacts client exchanging SPDY frames. When a request is completely received, it calls appropriate do_*() method. This method will handle multiple requests (streams) until SPDY session is over.

send_error(code, message=None)

Send a complete error reply to the client The numeric code specifies the HTTP error code, with message as optional, more specific text. A complete set of headers is sent, followed by HTML text.

send_response(code, message=None)

Adds a response code and, optionally, short message. This will be formatted as ‘:status’ response header field.

send_header(keyword, value)

Adds the HTTP header. The keyword and value must be unicode strings and not None.

The example of BaseSPDYRequestHandler and ThreadedSPDYServer follows:

#!/usr/bin/env python

# The example SPDY server. Python 3.3 or later is required because TLS
# NPN is used in spdylay.ThreadedSPDYServer. Put private key and
# certificate file in the current working directory.

import spdylay

# private key file
KEY_FILE='server.key'
# certificate file
CERT_FILE='server.crt'

class MySPDYRequestHandler(spdylay.BaseSPDYRequestHandler):

    def do_GET(self):
        if self.path == '/notfound':
            # Example code to return error
            self.send_error(404)
            return

        self.send_response(200)
        self.send_header('content-type', 'text/html; charset=UTF-8')

        content = '''\
<html>
<head><title>SPDY FTW</title></head>
<body>
<h1>SPDY FTW</h1>
<p>The age of HTTP/1.1 is over. The time of SPDY has come.</p>
</body>
</html>'''.encode('UTF-8')

        self.wfile.write(content)

if __name__ == "__main__":
    HOST, PORT = "localhost", 3000

    server = spdylay.ThreadedSPDYServer((HOST, PORT),
                                        MySPDYRequestHandler,
                                        cert_file=CERT_FILE,
                                        key_file=KEY_FILE)
    server.start()