* TLS NPN means that one of many protocols can be selected after a TCP connection is established. A
layer of indirection was added to TCPServer to allow it to delegate handling of a TCP connection
to whichever protocol handler was negotiated. If the `npn_protocols` parameter (a list of
(name, handler) tuples in order of preference) was passed to the constructor, the connection is
over TLS, and NPN succeeded, the handler for the chosen name will be called. Otherwise, the
`protocol` constructor parameter will be called. For example, SPDYServer is essentially:
def __init__(self, request_callback):
http_protocol = HTTPServerProtocol(request_callback)
* TCPServer was moved from netutil to its own module, tcpserver.
* Since utilizing NPN support in Python 3.3 requires the `ssl.SSLContext` class, which isn't
available in Python 2.x, the wrap_socket() top-level function was added to `netutil` to abstract
away these details. In addition, the `SUPPORTS_NPN` constant was added as a convenience for
determining if the system supported NPN.
* Previously, `web.RequestHandler` formatted the HTTP response itself and wrote it directly to the
IOStream. This responsibility has been moved to the HTTPRequest.connection object, which must
provide the write_preamble() and write() methods - the former writes the response status line and
headers, while the latter writes a chunk of the response body.
* Although IOStream.connect() already takes a callback parameter, in SSLIOStream it's not called
until the SSL handshake is completed (which contains TLS NPN) - and TCPServer, which doesn't call
connect(), won't know which protocol handler to execute until that happens. To fix this, a
set_connect_callback method was added to IOStream.
* Snippets that conditionally imported BytesIO and ssl were moved into util and netutil,
respectively. These symbols are now imported from there.