1066 lines
67 KiB
HTML
1066 lines
67 KiB
HTML
|
|
|
|
|
|
<!DOCTYPE html>
|
|
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
|
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
<title>nghttp2 - HTTP/2.0 C Library — nghttp2 0.3.0-DEV documentation</title>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<link href='https://fonts.googleapis.com/css?family=Lato:400,700|Roboto+Slab:400,700|Inconsolata:400,700' rel='stylesheet' type='text/css'>
|
|
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
|
var DOCUMENTATION_OPTIONS = {
|
|
URL_ROOT:'',
|
|
VERSION:'0.3.0-DEV',
|
|
COLLAPSE_INDEX:false,
|
|
FILE_SUFFIX:'.html',
|
|
HAS_SOURCE: true
|
|
};
|
|
</script>
|
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
|
<script type="text/javascript" src="_static/underscore.js"></script>
|
|
<script type="text/javascript" src="_static/doctools.js"></script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
|
|
<script type="text/javascript" src="_static/js/theme.js"></script>
|
|
|
|
|
|
|
|
<link rel="top" title="nghttp2 0.3.0-DEV documentation" href="index.html"/>
|
|
<link rel="next" title="Tutorial: HTTP/2.0 client" href="tutorial-client.html"/>
|
|
<link rel="prev" title="nghttp2 - HTTP/2.0 C Library" href="index.html"/>
|
|
|
|
<script src="//cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js"></script>
|
|
|
|
</head>
|
|
|
|
<body class="wy-body-for-nav">
|
|
|
|
<div class="wy-grid-for-nav">
|
|
|
|
|
|
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
|
|
<div class="wy-side-nav-search">
|
|
<a href="index.html" class="icon icon-home"> nghttp2</a>
|
|
<form id ="rtd-search-form" class="wy-form" action="search.html" method="get">
|
|
<input type="text" name="q" placeholder="Search docs" />
|
|
<input type="hidden" name="check_keywords" value="yes" />
|
|
<input type="hidden" name="area" value="default" />
|
|
</form>
|
|
</div>
|
|
|
|
<div class="wy-menu wy-menu-vertical" data-spy="affix">
|
|
|
|
|
|
<ul class="current">
|
|
<li class="toctree-l1 current"><a class="current reference internal" href="">nghttp2 - HTTP/2.0 C Library</a><ul>
|
|
<li class="toctree-l2"><a class="reference internal" href="#development-status">Development Status</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#public-test-server">Public Test Server</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#requirements">Requirements</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#build-from-git">Build from git</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#building-documentation">Building documentation</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#client-server-and-proxy-programs">Client, Server and Proxy programs</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#hpack-tools">HPACK tools</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#python-bindings">Python bindings</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="toctree-l1"><a class="reference internal" href="tutorial-client.html">Tutorial: HTTP/2.0 client</a><ul>
|
|
<li class="toctree-l2"><a class="reference internal" href="tutorial-client.html#libevent-client-c">libevent-client.c</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="toctree-l1"><a class="reference internal" href="tutorial-server.html">Tutorial: HTTP/2.0 server</a><ul>
|
|
<li class="toctree-l2"><a class="reference internal" href="tutorial-server.html#libevent-server-c">libevent-server.c</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="toctree-l1"><a class="reference internal" href="apiref.html">API Reference</a><ul>
|
|
<li class="toctree-l2"><a class="reference internal" href="apiref.html#includes">Includes</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="apiref.html#remarks">Remarks</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="apiref.html#macros">Macros</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="apiref.html#enums">Enums</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="apiref.html#types-structs-unions-and-typedefs">Types (structs, unions and typedefs)</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="apiref.html#functions">Functions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="toctree-l1"><a class="reference internal" href="nghttp2.h.html">nghttp2.h</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="nghttp2ver.h.html">nghttp2ver.h</a></li>
|
|
<li class="toctree-l1"><a class="reference external" href="https://github.com/tatsuhiro-t/nghttp2">Source</a></li>
|
|
<li class="toctree-l1"><a class="reference external" href="https://github.com/tatsuhiro-t/nghttp2/issues">Issues</a></li>
|
|
</ul>
|
|
|
|
|
|
</div>
|
|
|
|
</nav>
|
|
|
|
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
|
|
|
|
|
|
<nav class="wy-nav-top">
|
|
<i data-toggle="wy-nav-top" class="icon icon-reorder"></i>
|
|
<a href="index.html">nghttp2</a>
|
|
</nav>
|
|
|
|
|
|
|
|
<div class="wy-nav-content">
|
|
<div class="rst-content">
|
|
<ul class="wy-breadcrumbs">
|
|
<li><a href="index.html">Docs</a> »</li>
|
|
<li><a href="">nghttp2 - HTTP/2.0 C Library</a></li>
|
|
<li class="wy-breadcrumbs-aside">
|
|
|
|
<a href="_sources/package_README.txt" rel="nofollow"> View page source</a>
|
|
|
|
</li>
|
|
</ul>
|
|
<hr/>
|
|
|
|
|
|
<div class="section" id="nghttp2-http-2-0-c-library">
|
|
<h1>nghttp2 - HTTP/2.0 C Library<a class="headerlink" href="#nghttp2-http-2-0-c-library" title="Permalink to this headline">¶</a></h1>
|
|
<p>This is an experimental implementation of Hypertext Transfer Protocol
|
|
version 2.0.</p>
|
|
<div class="section" id="development-status">
|
|
<h2>Development Status<a class="headerlink" href="#development-status" title="Permalink to this headline">¶</a></h2>
|
|
<p>We started to implement HTTP-draft-09/2.0
|
|
(<a class="reference external" href="http://tools.ietf.org/html/draft-ietf-httpbis-http2-09">http://tools.ietf.org/html/draft-ietf-httpbis-http2-09</a>) and the
|
|
header compression
|
|
(<a class="reference external" href="http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-05">http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-05</a>).</p>
|
|
<p>The nghttp2 code base was forked from spdylay project.</p>
|
|
<table border="1" class="docutils">
|
|
<colgroup>
|
|
<col width="60%" />
|
|
<col width="40%" />
|
|
</colgroup>
|
|
<thead valign="bottom">
|
|
<tr class="row-odd"><th class="head">Features</th>
|
|
<th class="head">HTTP-draft-09/2.0</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody valign="top">
|
|
<tr class="row-even"><td>:authority</td>
|
|
<td>Done</td>
|
|
</tr>
|
|
<tr class="row-odd"><td>HPACK-draft-05</td>
|
|
<td>Done</td>
|
|
</tr>
|
|
<tr class="row-even"><td>SETTINGS_HEADER_TABLE_SIZE</td>
|
|
<td>Done</td>
|
|
</tr>
|
|
<tr class="row-odd"><td>SETTINGS_ENABLE_PUSH</td>
|
|
<td>Done</td>
|
|
</tr>
|
|
<tr class="row-even"><td>FRAME_SIZE_ERROR</td>
|
|
<td>Done</td>
|
|
</tr>
|
|
<tr class="row-odd"><td>SETTINGS with ACK</td>
|
|
<td>Done</td>
|
|
</tr>
|
|
<tr class="row-even"><td>Header Continuation</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr class="row-odd"><td>ALPN</td>
|
|
<td>Done</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="section" id="public-test-server">
|
|
<h2>Public Test Server<a class="headerlink" href="#public-test-server" title="Permalink to this headline">¶</a></h2>
|
|
<p>The following endpoints are available to try out nghttp2
|
|
implementation. These endpoints supports <tt class="docutils literal"><span class="pre">HTTP-draft-09/2.0</span></tt> and
|
|
the earlier draft versions are not supporeted.</p>
|
|
<ul>
|
|
<li><p class="first"><a class="reference external" href="https://106.186.112.116">https://106.186.112.116</a> (TLS + NPN)</p>
|
|
<p>NPN offers <tt class="docutils literal"><span class="pre">HTTP-draft-09/2.0</span></tt>, <tt class="docutils literal"><span class="pre">spdy/3.1</span></tt>, <tt class="docutils literal"><span class="pre">spdy/3</span></tt>,
|
|
<tt class="docutils literal"><span class="pre">spdy/2</span></tt> and <tt class="docutils literal"><span class="pre">http/1.1</span></tt>.</p>
|
|
<p>Note: certificate is self-signed and a browser will show alert</p>
|
|
</li>
|
|
<li><p class="first"><a class="reference external" href="http://106.186.112.116">http://106.186.112.116</a> (Upgrade + Direct)</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="section" id="requirements">
|
|
<h2>Requirements<a class="headerlink" href="#requirements" title="Permalink to this headline">¶</a></h2>
|
|
<p>The following packages are needed to build the library:</p>
|
|
<ul class="simple">
|
|
<li>pkg-config >= 0.20</li>
|
|
<li>zlib >= 1.2.3</li>
|
|
</ul>
|
|
<p>To build and run the unit test programs, the following packages are
|
|
required:</p>
|
|
<ul class="simple">
|
|
<li>cunit >= 2.1</li>
|
|
</ul>
|
|
<p>To build the documentation, you need to install:</p>
|
|
<ul class="simple">
|
|
<li>sphinx (<a class="reference external" href="http://sphinx-doc.org/">http://sphinx-doc.org/</a>)</li>
|
|
</ul>
|
|
<p>To build and run the application programs (<tt class="docutils literal"><span class="pre">nghttp</span></tt>, <tt class="docutils literal"><span class="pre">nghttpd</span></tt> and
|
|
<tt class="docutils literal"><span class="pre">nghttpx</span></tt>) in <tt class="docutils literal"><span class="pre">src</span></tt> directory, the following packages are
|
|
required:</p>
|
|
<ul class="simple">
|
|
<li>OpenSSL >= 1.0.1</li>
|
|
<li>libevent-openssl >= 2.0.8</li>
|
|
</ul>
|
|
<p>ALPN support requires unreleased version OpenSSL >= 1.0.2.</p>
|
|
<p>To enable SPDY protocol in the application program <tt class="docutils literal"><span class="pre">nghttpx</span></tt>, the
|
|
following packages are required:</p>
|
|
<ul class="simple">
|
|
<li>spdylay >= 1.2.3</li>
|
|
</ul>
|
|
<p>To enable <tt class="docutils literal"><span class="pre">-a</span></tt> option (getting linked assets from the downloaded
|
|
resource) in <tt class="docutils literal"><span class="pre">nghttp</span></tt>, the following packages are needed:</p>
|
|
<ul class="simple">
|
|
<li>libxml2 >= 2.7.7</li>
|
|
</ul>
|
|
<p>The HPACK tools require the following package:</p>
|
|
<ul class="simple">
|
|
<li>jansson >= 2.5</li>
|
|
</ul>
|
|
<p>The Python bindings require the following packages:</p>
|
|
<ul class="simple">
|
|
<li>cython >= 0.19</li>
|
|
<li>python >= 2.7</li>
|
|
</ul>
|
|
<p>If you are using Ubuntu 12.04, you need the following packages
|
|
installed:</p>
|
|
<ul class="simple">
|
|
<li>autoconf</li>
|
|
<li>automake</li>
|
|
<li>autotools-dev</li>
|
|
<li>libtool</li>
|
|
<li>pkg-config</li>
|
|
<li>zlib1g-dev</li>
|
|
<li>libcunit1-dev</li>
|
|
<li>libssl-dev</li>
|
|
<li>libxml2-dev</li>
|
|
<li>libevent-dev</li>
|
|
<li>libjansson-dev</li>
|
|
</ul>
|
|
<p>spdylay is not packaged in Ubuntu, so you need to build it yourself:
|
|
<a class="reference external" href="http://tatsuhiro-t.github.io/spdylay/">http://tatsuhiro-t.github.io/spdylay/</a></p>
|
|
</div>
|
|
<div class="section" id="build-from-git">
|
|
<h2>Build from git<a class="headerlink" href="#build-from-git" title="Permalink to this headline">¶</a></h2>
|
|
<p>Building from git is easy, but please be sure that at least autoconf 2.68 is
|
|
used:</p>
|
|
<div class="highlight-c"><pre>$ autoreconf -i
|
|
$ automake
|
|
$ autoconf
|
|
$ ./configure
|
|
$ make</pre>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="building-documentation">
|
|
<h2>Building documentation<a class="headerlink" href="#building-documentation" title="Permalink to this headline">¶</a></h2>
|
|
<div class="admonition note">
|
|
<p class="first admonition-title">Note</p>
|
|
<p class="last">Documentation is still incomplete.</p>
|
|
</div>
|
|
<p>To build documentation, run:</p>
|
|
<div class="highlight-c"><pre>$ make html</pre>
|
|
</div>
|
|
<p>The documents will be generated under <tt class="docutils literal"><span class="pre">doc/manual/html/</span></tt>.</p>
|
|
<p>The generated documents will not be installed with <tt class="docutils literal"><span class="pre">make</span> <span class="pre">install</span></tt>.</p>
|
|
<p>The online documentation is available at
|
|
<a class="reference external" href="http://tatsuhiro-t.github.io/nghttp2/">http://tatsuhiro-t.github.io/nghttp2/</a></p>
|
|
</div>
|
|
<div class="section" id="client-server-and-proxy-programs">
|
|
<h2>Client, Server and Proxy programs<a class="headerlink" href="#client-server-and-proxy-programs" title="Permalink to this headline">¶</a></h2>
|
|
<p>The src directory contains HTTP/2.0 client, server and proxy programs.</p>
|
|
<div class="section" id="nghttp-client">
|
|
<h3>nghttp - client<a class="headerlink" href="#nghttp-client" title="Permalink to this headline">¶</a></h3>
|
|
<p><tt class="docutils literal"><span class="pre">nghttp</span></tt> is a HTTP/2.0 client. It can connect to the HTTP/2.0 server
|
|
with prior knowledge, HTTP Upgrade and NPN/ALPN TLS extension.</p>
|
|
<p>It has verbose output mode for framing information. Here is sample
|
|
output from <tt class="docutils literal"><span class="pre">nghttp</span></tt> client:</p>
|
|
<div class="highlight-c"><pre>$ src/nghttp -vn https://localhost:8443
|
|
[ 0.003] NPN select next protocol: the remote server offers:
|
|
* HTTP-draft-09/2.0
|
|
* spdy/3
|
|
* spdy/2
|
|
* http/1.1
|
|
NPN selected the protocol: HTTP-draft-09/2.0
|
|
[ 0.005] send SETTINGS frame <length=16, flags=0x00, stream_id=0>
|
|
(niv=2)
|
|
[SETTINGS_MAX_CONCURRENT_STREAMS(4):100]
|
|
[SETTINGS_INITIAL_WINDOW_SIZE(7):65535]
|
|
[ 0.006] send HEADERS frame <length=47, flags=0x05, stream_id=1>
|
|
; END_STREAM | END_HEADERS
|
|
; Open new stream
|
|
:authority: localhost:8443
|
|
:method: GET
|
|
:path: /
|
|
:scheme: https
|
|
accept: */*
|
|
accept-encoding: gzip, deflate
|
|
user-agent: nghttp2/0.1.0-DEV
|
|
[ 0.006] recv SETTINGS frame <length=16, flags=0x00, stream_id=0>
|
|
(niv=2)
|
|
[SETTINGS_MAX_CONCURRENT_STREAMS(4):100]
|
|
[SETTINGS_INITIAL_WINDOW_SIZE(7):65535]
|
|
[ 0.006] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
|
; ACK
|
|
(niv=0)
|
|
[ 0.006] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
|
|
(window_size_increment=1000000007)
|
|
[ 0.006] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
|
; ACK
|
|
(niv=0)
|
|
[ 0.006] recv HEADERS frame <length=132, flags=0x04, stream_id=1>
|
|
; END_HEADERS
|
|
; First response header
|
|
:status: 200
|
|
accept-ranges: bytes
|
|
content-encoding: gzip
|
|
content-length: 146
|
|
content-type: text/html
|
|
date: Sun, 27 Oct 2013 14:23:54 GMT
|
|
etag: "b1-4e5535a027780-gzip"
|
|
last-modified: Sun, 01 Sep 2013 14:34:22 GMT
|
|
server: Apache/2.4.6 (Debian)
|
|
vary: Accept-Encoding
|
|
via: 1.1 nghttpx
|
|
[ 0.006] recv DATA frame <length=146, flags=0x00, stream_id=1>
|
|
[ 0.006] recv DATA frame <length=0, flags=0x01, stream_id=1>
|
|
; END_STREAM
|
|
[ 0.007] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
|
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])</pre>
|
|
</div>
|
|
<p>The HTTP Upgrade is performed like this:</p>
|
|
<div class="highlight-c"><pre>$ src/nghttp -vnu http://localhost:8080
|
|
[ 0.000] HTTP Upgrade request
|
|
GET / HTTP/1.1
|
|
Host: localhost:8080
|
|
Connection: Upgrade, HTTP2-Settings
|
|
Upgrade: HTTP-draft-09/2.0
|
|
HTTP2-Settings: AAAABAAAAGQAAAAHAAD__w
|
|
Accept: */*
|
|
User-Agent: nghttp2/0.1.0-DEV
|
|
|
|
|
|
[ 0.000] HTTP Upgrade response
|
|
HTTP/1.1 101 Switching Protocols
|
|
Connection: Upgrade
|
|
Upgrade: HTTP-draft-09/2.0
|
|
|
|
|
|
[ 0.001] HTTP Upgrade success
|
|
[ 0.001] send SETTINGS frame <length=16, flags=0x00, stream_id=0>
|
|
(niv=2)
|
|
[SETTINGS_MAX_CONCURRENT_STREAMS(4):100]
|
|
[SETTINGS_INITIAL_WINDOW_SIZE(7):65535]
|
|
[ 0.001] recv SETTINGS frame <length=16, flags=0x00, stream_id=0>
|
|
(niv=2)
|
|
[SETTINGS_MAX_CONCURRENT_STREAMS(4):100]
|
|
[SETTINGS_INITIAL_WINDOW_SIZE(7):65535]
|
|
[ 0.001] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
|
|
(window_size_increment=1000000007)
|
|
[ 0.001] recv HEADERS frame <length=121, flags=0x04, stream_id=1>
|
|
; END_HEADERS
|
|
; First response header
|
|
:status: 200
|
|
accept-ranges: bytes
|
|
content-length: 177
|
|
content-type: text/html
|
|
date: Sun, 27 Oct 2013 14:26:04 GMT
|
|
etag: "b1-4e5535a027780"
|
|
last-modified: Sun, 01 Sep 2013 14:34:22 GMT
|
|
server: Apache/2.4.6 (Debian)
|
|
vary: Accept-Encoding
|
|
via: 1.1 nghttpx
|
|
[ 0.001] recv DATA frame <length=177, flags=0x00, stream_id=1>
|
|
[ 0.001] recv DATA frame <length=0, flags=0x01, stream_id=1>
|
|
; END_STREAM
|
|
[ 0.001] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
|
; ACK
|
|
(niv=0)
|
|
[ 0.001] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
|
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
|
|
[ 0.001] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
|
; ACK
|
|
(niv=0)</pre>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="nghttpd-server">
|
|
<h3>nghttpd - server<a class="headerlink" href="#nghttpd-server" title="Permalink to this headline">¶</a></h3>
|
|
<p><tt class="docutils literal"><span class="pre">nghttpd</span></tt> is static web server. It is single threaded and
|
|
multiplexes connections using non-blocking socket.</p>
|
|
<p>By default, it uses SSL/TLS connection. Use <tt class="docutils literal"><span class="pre">--no-tls</span></tt> option to
|
|
disable it.</p>
|
|
<p><tt class="docutils literal"><span class="pre">nghttpd</span></tt> only accept the HTTP/2.0 connection via NPN/ALPN or direct
|
|
HTTP/2.0 connection. No HTTP Upgrade is supported.</p>
|
|
<p><tt class="docutils literal"><span class="pre">-p</span></tt> option allows users to configure server push.</p>
|
|
<p>Just like <tt class="docutils literal"><span class="pre">nghttp</span></tt>, it has verbose output mode for framing
|
|
information. Here is sample output from <tt class="docutils literal"><span class="pre">nghttpd</span></tt> server:</p>
|
|
<div class="highlight-c"><pre>$ src/nghttpd --no-tls -v 8080
|
|
IPv4: listen on port 8080
|
|
IPv6: listen on port 8080
|
|
[id=1] [ 1.189] send SETTINGS frame <length=8, flags=0x00, stream_id=0>
|
|
(niv=1)
|
|
[SETTINGS_MAX_CONCURRENT_STREAMS(4):100]
|
|
[id=1] [ 1.191] recv SETTINGS frame <length=16, flags=0x00, stream_id=0>
|
|
(niv=2)
|
|
[SETTINGS_MAX_CONCURRENT_STREAMS(4):100]
|
|
[SETTINGS_INITIAL_WINDOW_SIZE(7):65535]
|
|
[id=1] [ 1.191] recv HEADERS frame <length=47, flags=0x05, stream_id=1>
|
|
; END_STREAM | END_HEADERS
|
|
; Open new stream
|
|
:authority: localhost:8080
|
|
:method: GET
|
|
:path: /
|
|
:scheme: http
|
|
accept: */*
|
|
accept-encoding: gzip, deflate
|
|
user-agent: nghttp2/0.1.0-DEV
|
|
[id=1] [ 1.192] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
|
; ACK
|
|
(niv=0)
|
|
[id=1] [ 1.192] send HEADERS frame <length=70, flags=0x04, stream_id=1>
|
|
; END_HEADERS
|
|
; First response header
|
|
:status: 404
|
|
content-encoding: gzip
|
|
content-type: text/html; charset=UTF-8
|
|
date: Sun, 27 Oct 2013 14:27:53 GMT
|
|
server: nghttpd nghttp2/0.1.0-DEV
|
|
[id=1] [ 1.192] send DATA frame <length=117, flags=0x00, stream_id=1>
|
|
[id=1] [ 1.192] send DATA frame <length=0, flags=0x01, stream_id=1>
|
|
; END_STREAM
|
|
[id=1] [ 1.192] stream_id=1 closed
|
|
[id=1] [ 1.192] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
|
; ACK
|
|
(niv=0)
|
|
[id=1] [ 1.192] recv GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
|
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
|
|
[id=1] [ 1.192] closed</pre>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="nghttpx-proxy">
|
|
<h3>nghttpx - proxy<a class="headerlink" href="#nghttpx-proxy" title="Permalink to this headline">¶</a></h3>
|
|
<p>The <tt class="docutils literal"><span class="pre">nghttpx</span></tt> is a multi-threaded reverse proxy for
|
|
HTTP-draft-09/2.0, SPDY and HTTP/1.1. It has several operation modes:</p>
|
|
<table border="1" class="docutils">
|
|
<colgroup>
|
|
<col width="24%" />
|
|
<col width="40%" />
|
|
<col width="19%" />
|
|
<col width="17%" />
|
|
</colgroup>
|
|
<thead valign="bottom">
|
|
<tr class="row-odd"><th class="head">Mode option</th>
|
|
<th class="head">Frontend</th>
|
|
<th class="head">Backend</th>
|
|
<th class="head">Note</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody valign="top">
|
|
<tr class="row-even"><td>default mode</td>
|
|
<td>HTTP/2.0, SPDY, HTTP/1.1 (TLS)</td>
|
|
<td>HTTP/1.1</td>
|
|
<td>Reverse proxy</td>
|
|
</tr>
|
|
<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">--http2-proxy</span></tt></td>
|
|
<td>HTTP/2.0, SPDY, HTTP/1.1 (TLS)</td>
|
|
<td>HTTP/1.1</td>
|
|
<td>SPDY proxy</td>
|
|
</tr>
|
|
<tr class="row-even"><td><tt class="docutils literal"><span class="pre">--http2-bridge</span></tt></td>
|
|
<td>HTTP/2.0, SPDY, HTTP/1.1 (TLS)</td>
|
|
<td>HTTP/2.0 (TLS)</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">--client</span></tt></td>
|
|
<td>HTTP/2.0, HTTP/1.1</td>
|
|
<td>HTTP/2.0 (TLS)</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr class="row-even"><td><tt class="docutils literal"><span class="pre">--client-proxy</span></tt></td>
|
|
<td>HTTP/2.0, HTTP/1.1</td>
|
|
<td>HTTP/2.0 (TLS)</td>
|
|
<td>Forward proxy</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<p>The interesting mode at the moment is the default mode. It works like
|
|
a reverse proxy and listens HTTP-draft-09/2.0, SPDY and HTTP/1.1 and
|
|
can be deployed SSL/TLS terminator for existing web server.</p>
|
|
<p>The default mode, <tt class="docutils literal"><span class="pre">--http2-proxy</span></tt> and <tt class="docutils literal"><span class="pre">--http2-bridge</span></tt> modes use
|
|
SSL/TLS in the frontend connection by default. To disable SSL/TLS, use
|
|
<tt class="docutils literal"><span class="pre">--frontend-no-tls</span></tt> option. If that option is used, SPDY is disabled
|
|
in the frontend and incoming HTTP/1.1 connection can be upgraded to
|
|
HTTP/2.0 through HTTP Upgrade.</p>
|
|
<p>The <tt class="docutils literal"><span class="pre">--http2-bridge</span></tt>, <tt class="docutils literal"><span class="pre">--client</span></tt> and <tt class="docutils literal"><span class="pre">--client-proxy</span></tt> modes use
|
|
SSL/TLS in the backend connection by deafult. To disable SSL/TLS, use
|
|
<tt class="docutils literal"><span class="pre">--backend-no-tls</span></tt> option.</p>
|
|
<p>The <tt class="docutils literal"><span class="pre">nghttpx</span></tt> supports configuration file. See <tt class="docutils literal"><span class="pre">--conf</span></tt> option and
|
|
sample configuration file <tt class="docutils literal"><span class="pre">nghttpx.conf.sample</span></tt>.</p>
|
|
<p>The <tt class="docutils literal"><span class="pre">nghttpx</span></tt> does not support server push.</p>
|
|
<p>In the default mode, (without any of <tt class="docutils literal"><span class="pre">--http2-proxy</span></tt>,
|
|
<tt class="docutils literal"><span class="pre">--http2-bridge</span></tt>, <tt class="docutils literal"><span class="pre">--client-proxy</span></tt> and <tt class="docutils literal"><span class="pre">--client</span></tt> options),
|
|
<tt class="docutils literal"><span class="pre">nghttpx</span></tt> works as reverse proxy to the backend server:</p>
|
|
<div class="highlight-c"><div class="highlight"><pre><span class="n">Client</span> <span class="o"><--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mf">2.0</span><span class="p">,</span> <span class="n">SPDY</span><span class="p">,</span> <span class="n">HTTP</span><span class="o">/</span><span class="mf">1.1</span><span class="p">)</span> <span class="o">--></span> <span class="n">nghttpx</span> <span class="o"><--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mf">1.1</span><span class="p">)</span> <span class="o">--></span> <span class="n">Web</span> <span class="n">Server</span>
|
|
<span class="p">[</span><span class="n">reverse</span> <span class="n">proxy</span><span class="p">]</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>With <tt class="docutils literal"><span class="pre">--http2-proxy</span></tt> option, it works as so called secure proxy (aka
|
|
SPDY proxy):</p>
|
|
<div class="highlight-c"><div class="highlight"><pre><span class="n">Client</span> <span class="o"><--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mf">2.0</span><span class="p">,</span> <span class="n">SPDY</span><span class="p">,</span> <span class="n">HTTP</span><span class="o">/</span><span class="mf">1.1</span><span class="p">)</span> <span class="o">--></span> <span class="n">nghttpx</span> <span class="o"><--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mf">1.1</span><span class="p">)</span> <span class="o">--></span> <span class="n">Proxy</span>
|
|
<span class="p">[</span><span class="n">secure</span> <span class="n">proxy</span><span class="p">]</span> <span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">g</span><span class="p">.,</span> <span class="n">Squid</span><span class="p">)</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>The <tt class="docutils literal"><span class="pre">Client</span></tt> in the above is needs to be configured to use
|
|
<tt class="docutils literal"><span class="pre">nghttpx</span></tt> as secure proxy.</p>
|
|
<p>At the time of this writing, Chrome is the only browser which supports
|
|
secure proxy. The one way to configure Chrome to use secure proxy is
|
|
create proxy.pac script like this:</p>
|
|
<div class="highlight-c"><div class="highlight"><pre><span class="n">function</span> <span class="nf">FindProxyForURL</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">host</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="s">"HTTPS SERVERADDR:PORT"</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
<p><tt class="docutils literal"><span class="pre">SERVERADDR</span></tt> and <tt class="docutils literal"><span class="pre">PORT</span></tt> is the hostname/address and port of the
|
|
machine nghttpx is running. Please note that Chrome requires valid
|
|
certificate for secure proxy.</p>
|
|
<p>Then run chrome with the following arguments:</p>
|
|
<div class="highlight-c"><pre>$ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn</pre>
|
|
</div>
|
|
<p>With <tt class="docutils literal"><span class="pre">--http2-bridge</span></tt>, it accepts HTTP/2.0, SPDY and HTTP/1.1
|
|
connections and communicates with backend in HTTP/2.0:</p>
|
|
<div class="highlight-c"><div class="highlight"><pre><span class="n">Client</span> <span class="o"><--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mf">2.0</span><span class="p">,</span> <span class="n">SPDY</span><span class="p">,</span> <span class="n">HTTP</span><span class="o">/</span><span class="mf">1.1</span><span class="p">)</span> <span class="o">--></span> <span class="n">nghttpx</span> <span class="o"><--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mf">2.0</span><span class="p">)</span> <span class="o">--></span> <span class="n">Web</span> <span class="n">or</span> <span class="n">HTTP</span><span class="o">/</span><span class="mf">2.0</span> <span class="n">Proxy</span> <span class="n">etc</span>
|
|
<span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">g</span><span class="p">.,</span> <span class="n">nghttpx</span> <span class="o">-</span><span class="n">s</span><span class="p">)</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>With <tt class="docutils literal"><span class="pre">--client-proxy</span></tt> option, it works as forward proxy and expects
|
|
that the backend is HTTP/2.0 proxy:</p>
|
|
<div class="highlight-c"><div class="highlight"><pre><span class="n">Client</span> <span class="o"><--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mf">2.0</span><span class="p">,</span> <span class="n">HTTP</span><span class="o">/</span><span class="mf">1.1</span><span class="p">)</span> <span class="o">--></span> <span class="n">nghttpx</span> <span class="o"><--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mf">2.0</span><span class="p">)</span> <span class="o">--></span> <span class="n">HTTP</span><span class="o">/</span><span class="mf">2.0</span> <span class="n">Proxy</span>
|
|
<span class="p">[</span><span class="n">forward</span> <span class="n">proxy</span><span class="p">]</span> <span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">g</span><span class="p">.,</span> <span class="n">nghttpx</span> <span class="o">-</span><span class="n">s</span><span class="p">)</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>The <tt class="docutils literal"><span class="pre">Client</span></tt> is needs to be configured to use nghttpx as forward
|
|
proxy. The frontend HTTP/1.1 connection can be upgraded to HTTP/2.0
|
|
through HTTP Upgrade. With the above configuration, one can use
|
|
HTTP/1.1 client to access and test their HTTP/2.0 servers.</p>
|
|
<p>With <tt class="docutils literal"><span class="pre">--client</span></tt> option, it works as reverse proxy and expects that
|
|
the backend is HTTP/2.0 Web server:</p>
|
|
<div class="highlight-c"><div class="highlight"><pre><span class="n">Client</span> <span class="o"><--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mf">2.0</span><span class="p">,</span> <span class="n">HTTP</span><span class="o">/</span><span class="mf">1.1</span><span class="p">)</span> <span class="o">--></span> <span class="n">nghttpx</span> <span class="o"><--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mf">2.0</span><span class="p">)</span> <span class="o">--></span> <span class="n">Web</span> <span class="n">Server</span>
|
|
<span class="p">[</span><span class="n">reverse</span> <span class="n">proxy</span><span class="p">]</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>The frontend HTTP/1.1 connection can be upgraded to HTTP/2.0
|
|
through HTTP Upgrade.</p>
|
|
<p>For the operation modes which talk to the backend in HTTP/2.0 over
|
|
SSL/TLS, the backend connections can be tunneled though HTTP
|
|
proxy. The proxy is specified using <tt class="docutils literal"><span class="pre">--backend-http-proxy-uri</span></tt>
|
|
option. The following figure illustrates the example of
|
|
<tt class="docutils literal"><span class="pre">--http2-bridge</span></tt> and <tt class="docutils literal"><span class="pre">--backend-http-proxy-uri</span></tt> option to talk to
|
|
the outside HTTP/2.0 proxy through HTTP proxy:</p>
|
|
<div class="highlight-c"><div class="highlight"><pre><span class="n">Client</span> <span class="o"><--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mf">2.0</span><span class="p">,</span> <span class="n">SPDY</span><span class="p">,</span> <span class="n">HTTP</span><span class="o">/</span><span class="mf">1.1</span><span class="p">)</span> <span class="o">--></span> <span class="n">nghttpx</span> <span class="o"><--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mf">2.0</span><span class="p">)</span> <span class="o">--</span>
|
|
|
|
<span class="o">--===================---></span> <span class="n">HTTP</span><span class="o">/</span><span class="mf">2.0</span> <span class="n">Proxy</span>
|
|
<span class="p">(</span><span class="n">HTTP</span> <span class="n">proxy</span> <span class="n">tunnel</span><span class="p">)</span> <span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">g</span><span class="p">.,</span> <span class="n">nghttpx</span> <span class="o">-</span><span class="n">s</span><span class="p">)</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="hpack-tools">
|
|
<h2>HPACK tools<a class="headerlink" href="#hpack-tools" title="Permalink to this headline">¶</a></h2>
|
|
<p>The <tt class="docutils literal"><span class="pre">src</span></tt> directory contains HPACK tools. The <tt class="docutils literal"><span class="pre">deflatehd</span></tt> is
|
|
command-line header compression tool. The <tt class="docutils literal"><span class="pre">inflatehd</span></tt> is
|
|
command-line header decompression tool. Both tools read input from
|
|
stdin and write output to stdout. The errors are written to
|
|
stderr. They take JSON as input and output. We use the same JSON data
|
|
format used in <a class="reference external" href="https://github.com/Jxck/hpack-test-case">https://github.com/Jxck/hpack-test-case</a></p>
|
|
<div class="section" id="deflatehd-header-compressor">
|
|
<h3>deflatehd - header compressor<a class="headerlink" href="#deflatehd-header-compressor" title="Permalink to this headline">¶</a></h3>
|
|
<p>The <tt class="docutils literal"><span class="pre">deflatehd</span></tt> reads JSON data or HTTP/1-style header fields from
|
|
stdin and outputs compressed header block in JSON.</p>
|
|
<p>For the JSON input, the root JSON object must contain <tt class="docutils literal"><span class="pre">context</span></tt> key,
|
|
which indicates which compression context is used. If it is
|
|
<tt class="docutils literal"><span class="pre">request</span></tt>, request compression context is used. Otherwise, response
|
|
compression context is used. The value of <tt class="docutils literal"><span class="pre">cases</span></tt> key contains the
|
|
sequence of input header set. They share the same compression context
|
|
and are processed in the order they appear. Each item in the sequence
|
|
is a JSON object and it must have at least <tt class="docutils literal"><span class="pre">headers</span></tt> key. Its value
|
|
is an array of a JSON object containing exactly one name/value pair.</p>
|
|
<p>Example:</p>
|
|
<div class="highlight-c"><div class="highlight"><pre><span class="p">{</span>
|
|
<span class="s">"context"</span><span class="o">:</span> <span class="s">"request"</span><span class="p">,</span>
|
|
<span class="s">"cases"</span><span class="o">:</span>
|
|
<span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"headers"</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">{</span> <span class="s">":method"</span><span class="o">:</span> <span class="s">"GET"</span> <span class="p">},</span>
|
|
<span class="p">{</span> <span class="s">":path"</span><span class="o">:</span> <span class="s">"/"</span> <span class="p">}</span>
|
|
<span class="p">]</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"headers"</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">{</span> <span class="s">":method"</span><span class="o">:</span> <span class="s">"POST"</span> <span class="p">},</span>
|
|
<span class="p">{</span> <span class="s">":path"</span><span class="o">:</span> <span class="s">"/"</span> <span class="p">}</span>
|
|
<span class="p">]</span>
|
|
<span class="p">}</span>
|
|
<span class="p">]</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>With <tt class="docutils literal"><span class="pre">-t</span></tt> option, the program can accept more familiar HTTP/1 style
|
|
header field block. Each header set is delimited by empty line:</p>
|
|
<p>Example:</p>
|
|
<div class="highlight-c"><div class="highlight"><pre><span class="o">:</span><span class="n">method</span><span class="o">:</span> <span class="n">GET</span>
|
|
<span class="o">:</span><span class="n">scheme</span><span class="o">:</span> <span class="n">https</span>
|
|
<span class="o">:</span><span class="n">path</span><span class="o">:</span> <span class="o">/</span>
|
|
|
|
<span class="o">:</span><span class="n">method</span><span class="o">:</span> <span class="n">POST</span>
|
|
<span class="n">user</span><span class="o">-</span><span class="n">agent</span><span class="o">:</span> <span class="n">nghttp2</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>The output is JSON object. It contains <tt class="docutils literal"><span class="pre">context</span></tt> key and its value
|
|
is <tt class="docutils literal"><span class="pre">request</span></tt> if the compression context is request, otherwise
|
|
<tt class="docutils literal"><span class="pre">response</span></tt>. The root JSON object also contains <tt class="docutils literal"><span class="pre">cases</span></tt> key and its
|
|
value is an array of JSON object, which has at least following keys:</p>
|
|
<dl class="docutils">
|
|
<dt>seq</dt>
|
|
<dd>The index of header set in the input.</dd>
|
|
<dt>input_length</dt>
|
|
<dd>The sum of length of name/value pair in the input.</dd>
|
|
<dt>output_length</dt>
|
|
<dd>The length of compressed header block.</dd>
|
|
<dt>percentage_of_original_size</dt>
|
|
<dd><tt class="docutils literal"><span class="pre">input_length</span></tt> / <tt class="docutils literal"><span class="pre">output_length</span></tt> * 100</dd>
|
|
<dt>wire</dt>
|
|
<dd>The compressed header block in hex string.</dd>
|
|
<dt>headers</dt>
|
|
<dd>The input header set.</dd>
|
|
<dt>header_table_size</dt>
|
|
<dd>The header table size adjsuted before deflating header set.</dd>
|
|
</dl>
|
|
<p>Examples:</p>
|
|
<div class="highlight-c"><div class="highlight"><pre><span class="p">{</span>
|
|
<span class="s">"context"</span><span class="o">:</span> <span class="s">"request"</span><span class="p">,</span>
|
|
<span class="s">"cases"</span><span class="o">:</span>
|
|
<span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"seq"</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span>
|
|
<span class="s">"input_length"</span><span class="o">:</span> <span class="mi">66</span><span class="p">,</span>
|
|
<span class="s">"output_length"</span><span class="o">:</span> <span class="mi">20</span><span class="p">,</span>
|
|
<span class="s">"percentage_of_original_size"</span><span class="o">:</span> <span class="mf">30.303030303030305</span><span class="p">,</span>
|
|
<span class="s">"wire"</span><span class="o">:</span> <span class="s">"01881f3468e5891afcbf83868a3d856659c62e3f"</span><span class="p">,</span>
|
|
<span class="s">"headers"</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":authority"</span><span class="o">:</span> <span class="s">"example.org"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":method"</span><span class="o">:</span> <span class="s">"GET"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":path"</span><span class="o">:</span> <span class="s">"/"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":scheme"</span><span class="o">:</span> <span class="s">"https"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"user-agent"</span><span class="o">:</span> <span class="s">"nghttp2"</span>
|
|
<span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="s">"header_table_size"</span><span class="o">:</span> <span class="mi">4096</span>
|
|
<span class="p">}</span>
|
|
<span class="p">,</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"seq"</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
|
|
<span class="s">"input_length"</span><span class="o">:</span> <span class="mi">74</span><span class="p">,</span>
|
|
<span class="s">"output_length"</span><span class="o">:</span> <span class="mi">10</span><span class="p">,</span>
|
|
<span class="s">"percentage_of_original_size"</span><span class="o">:</span> <span class="mf">13.513513513513514</span><span class="p">,</span>
|
|
<span class="s">"wire"</span><span class="o">:</span> <span class="s">"88448504252dd5918485"</span><span class="p">,</span>
|
|
<span class="s">"headers"</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":authority"</span><span class="o">:</span> <span class="s">"example.org"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":method"</span><span class="o">:</span> <span class="s">"POST"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":path"</span><span class="o">:</span> <span class="s">"/account"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":scheme"</span><span class="o">:</span> <span class="s">"https"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"user-agent"</span><span class="o">:</span> <span class="s">"nghttp2"</span>
|
|
<span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="s">"header_table_size"</span><span class="o">:</span> <span class="mi">4096</span>
|
|
<span class="p">}</span>
|
|
<span class="p">]</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>The output can be used as the input for <tt class="docutils literal"><span class="pre">inflatehd</span></tt> and
|
|
<tt class="docutils literal"><span class="pre">deflatehd</span></tt>.</p>
|
|
<p>With <tt class="docutils literal"><span class="pre">-d</span></tt> option, the extra <tt class="docutils literal"><span class="pre">header_table</span></tt> key is added and its
|
|
associated value contains the state of dyanmic header table after the
|
|
corresponding header set was processed. The value contains following
|
|
keys:</p>
|
|
<dl class="docutils">
|
|
<dt>entries</dt>
|
|
<dd>The entry in the header table. If <tt class="docutils literal"><span class="pre">referenced</span></tt> is <tt class="docutils literal"><span class="pre">true</span></tt>, it
|
|
is in the reference set. The <tt class="docutils literal"><span class="pre">size</span></tt> includes the overhead (32
|
|
bytes). The <tt class="docutils literal"><span class="pre">index</span></tt> corresponds to the index of header table.
|
|
The <tt class="docutils literal"><span class="pre">name</span></tt> is the header field name and the <tt class="docutils literal"><span class="pre">value</span></tt> is the
|
|
header field value. They may be displayed as <tt class="docutils literal"><span class="pre">**DEALLOCATED**</span></tt>,
|
|
which means that the memory for that string is freed and not
|
|
available. This will happen when the specifying smaller value in
|
|
<tt class="docutils literal"><span class="pre">-S</span></tt> than <tt class="docutils literal"><span class="pre">-s</span></tt>.</dd>
|
|
<dt>size</dt>
|
|
<dd>The sum of the spaces entries occupied, this includes the
|
|
entry overhead.</dd>
|
|
<dt>max_size</dt>
|
|
<dd>The maximum header table size.</dd>
|
|
<dt>deflate_size</dt>
|
|
<dd>The sum of the spaces entries occupied within
|
|
<tt class="docutils literal"><span class="pre">max_deflate_size</span></tt>.</dd>
|
|
<dt>max_deflate_size</dt>
|
|
<dd>The maximum header table size encoder uses. This can be smaller
|
|
than <tt class="docutils literal"><span class="pre">max_size</span></tt>. In this case, encoder only uses up to first
|
|
<tt class="docutils literal"><span class="pre">max_deflate_size</span></tt> buffer. Since the header table size is still
|
|
<tt class="docutils literal"><span class="pre">max_size</span></tt>, the encoder has to keep track of entries ouside the
|
|
<tt class="docutils literal"><span class="pre">max_deflate_size</span></tt> but inside the <tt class="docutils literal"><span class="pre">max_size</span></tt> and make sure
|
|
that they are no longer referenced.</dd>
|
|
</dl>
|
|
<p>Example:</p>
|
|
<div class="highlight-c"><div class="highlight"><pre><span class="p">{</span>
|
|
<span class="s">"context"</span><span class="o">:</span> <span class="s">"request"</span><span class="p">,</span>
|
|
<span class="s">"cases"</span><span class="o">:</span>
|
|
<span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"seq"</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span>
|
|
<span class="s">"input_length"</span><span class="o">:</span> <span class="mi">66</span><span class="p">,</span>
|
|
<span class="s">"output_length"</span><span class="o">:</span> <span class="mi">20</span><span class="p">,</span>
|
|
<span class="s">"percentage_of_original_size"</span><span class="o">:</span> <span class="mf">30.303030303030305</span><span class="p">,</span>
|
|
<span class="s">"wire"</span><span class="o">:</span> <span class="s">"01881f3468e5891afcbf83868a3d856659c62e3f"</span><span class="p">,</span>
|
|
<span class="s">"headers"</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":authority"</span><span class="o">:</span> <span class="s">"example.org"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":method"</span><span class="o">:</span> <span class="s">"GET"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":path"</span><span class="o">:</span> <span class="s">"/"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":scheme"</span><span class="o">:</span> <span class="s">"https"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"user-agent"</span><span class="o">:</span> <span class="s">"nghttp2"</span>
|
|
<span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="s">"header_table_size"</span><span class="o">:</span> <span class="mi">4096</span><span class="p">,</span>
|
|
<span class="s">"header_table"</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="s">"entries"</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"index"</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
|
|
<span class="s">"name"</span><span class="o">:</span> <span class="s">"user-agent"</span><span class="p">,</span>
|
|
<span class="s">"value"</span><span class="o">:</span> <span class="s">"nghttp2"</span><span class="p">,</span>
|
|
<span class="s">"referenced"</span><span class="o">:</span> <span class="nb">true</span><span class="p">,</span>
|
|
<span class="s">"size"</span><span class="o">:</span> <span class="mi">49</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"index"</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span>
|
|
<span class="s">"name"</span><span class="o">:</span> <span class="s">":scheme"</span><span class="p">,</span>
|
|
<span class="s">"value"</span><span class="o">:</span> <span class="s">"https"</span><span class="p">,</span>
|
|
<span class="s">"referenced"</span><span class="o">:</span> <span class="nb">true</span><span class="p">,</span>
|
|
<span class="s">"size"</span><span class="o">:</span> <span class="mi">44</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"index"</span><span class="o">:</span> <span class="mi">3</span><span class="p">,</span>
|
|
<span class="s">"name"</span><span class="o">:</span> <span class="s">":path"</span><span class="p">,</span>
|
|
<span class="s">"value"</span><span class="o">:</span> <span class="s">"/"</span><span class="p">,</span>
|
|
<span class="s">"referenced"</span><span class="o">:</span> <span class="nb">true</span><span class="p">,</span>
|
|
<span class="s">"size"</span><span class="o">:</span> <span class="mi">38</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"index"</span><span class="o">:</span> <span class="mi">4</span><span class="p">,</span>
|
|
<span class="s">"name"</span><span class="o">:</span> <span class="s">":method"</span><span class="p">,</span>
|
|
<span class="s">"value"</span><span class="o">:</span> <span class="s">"GET"</span><span class="p">,</span>
|
|
<span class="s">"referenced"</span><span class="o">:</span> <span class="nb">true</span><span class="p">,</span>
|
|
<span class="s">"size"</span><span class="o">:</span> <span class="mi">42</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"index"</span><span class="o">:</span> <span class="mi">5</span><span class="p">,</span>
|
|
<span class="s">"name"</span><span class="o">:</span> <span class="s">":authority"</span><span class="p">,</span>
|
|
<span class="s">"value"</span><span class="o">:</span> <span class="s">"example.org"</span><span class="p">,</span>
|
|
<span class="s">"referenced"</span><span class="o">:</span> <span class="nb">true</span><span class="p">,</span>
|
|
<span class="s">"size"</span><span class="o">:</span> <span class="mi">53</span>
|
|
<span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="s">"size"</span><span class="o">:</span> <span class="mi">226</span><span class="p">,</span>
|
|
<span class="s">"max_size"</span><span class="o">:</span> <span class="mi">4096</span><span class="p">,</span>
|
|
<span class="s">"deflate_size"</span><span class="o">:</span> <span class="mi">226</span><span class="p">,</span>
|
|
<span class="s">"max_deflate_size"</span><span class="o">:</span> <span class="mi">4096</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">,</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"seq"</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
|
|
<span class="s">"input_length"</span><span class="o">:</span> <span class="mi">74</span><span class="p">,</span>
|
|
<span class="s">"output_length"</span><span class="o">:</span> <span class="mi">10</span><span class="p">,</span>
|
|
<span class="s">"percentage_of_original_size"</span><span class="o">:</span> <span class="mf">13.513513513513514</span><span class="p">,</span>
|
|
<span class="s">"wire"</span><span class="o">:</span> <span class="s">"88448504252dd5918485"</span><span class="p">,</span>
|
|
<span class="s">"headers"</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":authority"</span><span class="o">:</span> <span class="s">"example.org"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":method"</span><span class="o">:</span> <span class="s">"POST"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":path"</span><span class="o">:</span> <span class="s">"/account"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":scheme"</span><span class="o">:</span> <span class="s">"https"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"user-agent"</span><span class="o">:</span> <span class="s">"nghttp2"</span>
|
|
<span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="s">"header_table_size"</span><span class="o">:</span> <span class="mi">4096</span><span class="p">,</span>
|
|
<span class="s">"header_table"</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="s">"entries"</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"index"</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
|
|
<span class="s">"name"</span><span class="o">:</span> <span class="s">":method"</span><span class="p">,</span>
|
|
<span class="s">"value"</span><span class="o">:</span> <span class="s">"POST"</span><span class="p">,</span>
|
|
<span class="s">"referenced"</span><span class="o">:</span> <span class="nb">true</span><span class="p">,</span>
|
|
<span class="s">"size"</span><span class="o">:</span> <span class="mi">43</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"index"</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span>
|
|
<span class="s">"name"</span><span class="o">:</span> <span class="s">"user-agent"</span><span class="p">,</span>
|
|
<span class="s">"value"</span><span class="o">:</span> <span class="s">"nghttp2"</span><span class="p">,</span>
|
|
<span class="s">"referenced"</span><span class="o">:</span> <span class="nb">true</span><span class="p">,</span>
|
|
<span class="s">"size"</span><span class="o">:</span> <span class="mi">49</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"index"</span><span class="o">:</span> <span class="mi">3</span><span class="p">,</span>
|
|
<span class="s">"name"</span><span class="o">:</span> <span class="s">":scheme"</span><span class="p">,</span>
|
|
<span class="s">"value"</span><span class="o">:</span> <span class="s">"https"</span><span class="p">,</span>
|
|
<span class="s">"referenced"</span><span class="o">:</span> <span class="nb">true</span><span class="p">,</span>
|
|
<span class="s">"size"</span><span class="o">:</span> <span class="mi">44</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"index"</span><span class="o">:</span> <span class="mi">4</span><span class="p">,</span>
|
|
<span class="s">"name"</span><span class="o">:</span> <span class="s">":path"</span><span class="p">,</span>
|
|
<span class="s">"value"</span><span class="o">:</span> <span class="s">"/"</span><span class="p">,</span>
|
|
<span class="s">"referenced"</span><span class="o">:</span> <span class="nb">false</span><span class="p">,</span>
|
|
<span class="s">"size"</span><span class="o">:</span> <span class="mi">38</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"index"</span><span class="o">:</span> <span class="mi">5</span><span class="p">,</span>
|
|
<span class="s">"name"</span><span class="o">:</span> <span class="s">":method"</span><span class="p">,</span>
|
|
<span class="s">"value"</span><span class="o">:</span> <span class="s">"GET"</span><span class="p">,</span>
|
|
<span class="s">"referenced"</span><span class="o">:</span> <span class="nb">false</span><span class="p">,</span>
|
|
<span class="s">"size"</span><span class="o">:</span> <span class="mi">42</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"index"</span><span class="o">:</span> <span class="mi">6</span><span class="p">,</span>
|
|
<span class="s">"name"</span><span class="o">:</span> <span class="s">":authority"</span><span class="p">,</span>
|
|
<span class="s">"value"</span><span class="o">:</span> <span class="s">"example.org"</span><span class="p">,</span>
|
|
<span class="s">"referenced"</span><span class="o">:</span> <span class="nb">true</span><span class="p">,</span>
|
|
<span class="s">"size"</span><span class="o">:</span> <span class="mi">53</span>
|
|
<span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="s">"size"</span><span class="o">:</span> <span class="mi">269</span><span class="p">,</span>
|
|
<span class="s">"max_size"</span><span class="o">:</span> <span class="mi">4096</span><span class="p">,</span>
|
|
<span class="s">"deflate_size"</span><span class="o">:</span> <span class="mi">269</span><span class="p">,</span>
|
|
<span class="s">"max_deflate_size"</span><span class="o">:</span> <span class="mi">4096</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">]</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="inflatehd-header-decompressor">
|
|
<h3>inflatehd - header decompressor<a class="headerlink" href="#inflatehd-header-decompressor" title="Permalink to this headline">¶</a></h3>
|
|
<p>The <tt class="docutils literal"><span class="pre">inflatehd</span></tt> reads JSON data from stdin and outputs decompressed
|
|
name/value pairs in JSON.</p>
|
|
<p>The root JSON object must contain <tt class="docutils literal"><span class="pre">context</span></tt> key, which indicates
|
|
which compression context is used. If it is <tt class="docutils literal"><span class="pre">request</span></tt>, request
|
|
compression context is used. Otherwise, response compression context
|
|
is used. The value of <tt class="docutils literal"><span class="pre">cases</span></tt> key contains the sequence of
|
|
compressed header block. They share the same compression context and
|
|
are processed in the order they appear. Each item in the sequence is a
|
|
JSON object and it must have at least <tt class="docutils literal"><span class="pre">wire</span></tt> key. Its value is a
|
|
string containing compressed header block in hex string.</p>
|
|
<p>Example:</p>
|
|
<div class="highlight-c"><div class="highlight"><pre><span class="p">{</span>
|
|
<span class="s">"context"</span><span class="o">:</span> <span class="s">"request"</span><span class="p">,</span>
|
|
<span class="s">"cases"</span><span class="o">:</span>
|
|
<span class="p">[</span>
|
|
<span class="p">{</span> <span class="s">"wire"</span><span class="o">:</span> <span class="s">"8285"</span> <span class="p">},</span>
|
|
<span class="p">{</span> <span class="s">"wire"</span><span class="o">:</span> <span class="s">"8583"</span> <span class="p">}</span>
|
|
<span class="p">]</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>The output is JSON object. It contains <tt class="docutils literal"><span class="pre">context</span></tt> key and its value
|
|
is <tt class="docutils literal"><span class="pre">request</span></tt> if the compression context is request, otherwise
|
|
<tt class="docutils literal"><span class="pre">response</span></tt>. The root JSON object also contains <tt class="docutils literal"><span class="pre">cases</span></tt> key and its
|
|
value is an array of JSON object, which has at least following keys:</p>
|
|
<dl class="docutils">
|
|
<dt>seq</dt>
|
|
<dd>The index of header set in the input.</dd>
|
|
<dt>headers</dt>
|
|
<dd>The JSON array contains decompressed name/value pairs.</dd>
|
|
<dt>wire</dt>
|
|
<dd>The compressed header block in hex string.</dd>
|
|
<dt>header_table_size</dt>
|
|
<dd>The header table size adjsuted before inflating compressed header
|
|
block.</dd>
|
|
</dl>
|
|
<p>Example:</p>
|
|
<div class="highlight-c"><div class="highlight"><pre><span class="p">{</span>
|
|
<span class="s">"context"</span><span class="o">:</span> <span class="s">"request"</span><span class="p">,</span>
|
|
<span class="s">"cases"</span><span class="o">:</span>
|
|
<span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"seq"</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span>
|
|
<span class="s">"wire"</span><span class="o">:</span> <span class="s">"01881f3468e5891afcbf83868a3d856659c62e3f"</span><span class="p">,</span>
|
|
<span class="s">"headers"</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":authority"</span><span class="o">:</span> <span class="s">"example.org"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":method"</span><span class="o">:</span> <span class="s">"GET"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":path"</span><span class="o">:</span> <span class="s">"/"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":scheme"</span><span class="o">:</span> <span class="s">"https"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"user-agent"</span><span class="o">:</span> <span class="s">"nghttp2"</span>
|
|
<span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="s">"header_table_size"</span><span class="o">:</span> <span class="mi">4096</span>
|
|
<span class="p">}</span>
|
|
<span class="p">,</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"seq"</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
|
|
<span class="s">"wire"</span><span class="o">:</span> <span class="s">"88448504252dd5918485"</span><span class="p">,</span>
|
|
<span class="s">"headers"</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":method"</span><span class="o">:</span> <span class="s">"POST"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":path"</span><span class="o">:</span> <span class="s">"/account"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">"user-agent"</span><span class="o">:</span> <span class="s">"nghttp2"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":scheme"</span><span class="o">:</span> <span class="s">"https"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="s">":authority"</span><span class="o">:</span> <span class="s">"example.org"</span>
|
|
<span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="s">"header_table_size"</span><span class="o">:</span> <span class="mi">4096</span>
|
|
<span class="p">}</span>
|
|
<span class="p">]</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>The output can be used as the input for <tt class="docutils literal"><span class="pre">deflatehd</span></tt> and
|
|
<tt class="docutils literal"><span class="pre">inflatehd</span></tt>.</p>
|
|
<p>With <tt class="docutils literal"><span class="pre">-d</span></tt> option, the extra <tt class="docutils literal"><span class="pre">header_table</span></tt> key is added and its
|
|
associated value contains the state of dyanmic header table after the
|
|
corresponding header set was processed. The format is the same as
|
|
<tt class="docutils literal"><span class="pre">deflatehd</span></tt>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="python-bindings">
|
|
<h2>Python bindings<a class="headerlink" href="#python-bindings" title="Permalink to this headline">¶</a></h2>
|
|
<p>This <tt class="docutils literal"><span class="pre">python</span></tt> directory contains nghttp2 Python bindings. The
|
|
bindings currently only provide HPACK compressor and decompressor
|
|
classes.</p>
|
|
<p>The extension module is called <tt class="docutils literal"><span class="pre">nghttp2</span></tt>.</p>
|
|
<p><tt class="docutils literal"><span class="pre">make</span></tt> will build the bindings and 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 <tt class="docutils literal"><span class="pre">PYTHON</span></tt>
|
|
variable as an argument to configure script (e.g., <tt class="docutils literal"><span class="pre">./configure</span>
|
|
<span class="pre">PYTHON=/usr/bin/python3.3</span></tt>).</p>
|
|
<div class="section" id="example">
|
|
<h3>Example<a class="headerlink" href="#example" title="Permalink to this headline">¶</a></h3>
|
|
<p>The following example code illustrates basic usage of HPACK compressor
|
|
and decompressor in Python:</p>
|
|
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">binascii</span>
|
|
<span class="kn">import</span> <span class="nn">nghttp2</span>
|
|
|
|
<span class="n">deflater</span> <span class="o">=</span> <span class="n">nghttp2</span><span class="o">.</span><span class="n">HDDeflater</span><span class="p">(</span><span class="n">nghttp2</span><span class="o">.</span><span class="n">HD_SIDE_REQUEST</span><span class="p">)</span>
|
|
<span class="n">inflater</span> <span class="o">=</span> <span class="n">nghttp2</span><span class="o">.</span><span class="n">HDInflater</span><span class="p">(</span><span class="n">nghttp2</span><span class="o">.</span><span class="n">HD_SIDE_REQUEST</span><span class="p">)</span>
|
|
|
|
<span class="n">data</span> <span class="o">=</span> <span class="n">deflater</span><span class="o">.</span><span class="n">deflate</span><span class="p">([(</span><span class="n">b</span><span class="s">'foo'</span><span class="p">,</span> <span class="n">b</span><span class="s">'bar'</span><span class="p">),</span>
|
|
<span class="p">(</span><span class="n">b</span><span class="s">'baz'</span><span class="p">,</span> <span class="n">b</span><span class="s">'buz'</span><span class="p">)])</span>
|
|
<span class="k">print</span><span class="p">(</span><span class="n">binascii</span><span class="o">.</span><span class="n">b2a_hex</span><span class="p">(</span><span class="n">data</span><span class="p">))</span>
|
|
|
|
<span class="n">hdrs</span> <span class="o">=</span> <span class="n">inflater</span><span class="o">.</span><span class="n">inflate</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
|
|
<span class="k">print</span><span class="p">(</span><span class="n">hdrs</span><span class="p">)</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<footer>
|
|
|
|
<div class="rst-footer-buttons">
|
|
|
|
<a href="tutorial-client.html" class="btn btn-neutral float-right" title="Tutorial: HTTP/2.0 client"/>Next <span class="icon icon-circle-arrow-right"></span></a>
|
|
|
|
|
|
<a href="index.html" class="btn btn-neutral" title="nghttp2 - HTTP/2.0 C Library"><span class="icon icon-circle-arrow-left"></span> Previous</a>
|
|
|
|
</div>
|
|
|
|
|
|
<hr/>
|
|
|
|
<p>
|
|
© Copyright 2012, 2014, Tatsuhiro Tsujikawa.
|
|
</p>
|
|
|
|
<a href="https://www.github.com/snide/sphinx_rtd_theme">Sphinx theme</a> provided by <a href="http://readthedocs.org">Read the Docs</a>
|
|
</footer>
|
|
</div>
|
|
</div>
|
|
|
|
</section>
|
|
|
|
</div>
|
|
|
|
|
|
</body>
|
|
</html> |