nghttp2/package_README.html

1178 lines
76 KiB
HTML
Raw Normal View History

2013-07-28 14:26:41 +02:00
<!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">
2014-04-05 12:26:23 +02:00
<title>nghttp2 - HTTP/2 C Library &mdash; nghttp2 0.4.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'>
2013-07-28 14:26:41 +02:00
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
2014-02-24 17:49:22 +01:00
URL_ROOT:'./',
2014-02-05 15:22:31 +01:00
VERSION:'0.4.0-DEV',
COLLAPSE_INDEX:false,
FILE_SUFFIX:'.html',
2014-02-16 07:26:13 +01:00
HAS_SOURCE: false
2013-07-28 14:26:41 +02:00
};
</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>
2014-02-02 10:36:57 +01:00
<script type="text/javascript">
jQuery(function () {
SphinxRtdTheme.StickyNav.enable();
});
</script>
2014-02-05 15:22:31 +01:00
<link rel="top" title="nghttp2 0.4.0-DEV documentation" href="index.html"/>
2014-04-05 12:26:23 +02:00
<link rel="next" title="Tutorial: HTTP/2 client" href="tutorial-client.html"/>
<link rel="prev" title="nghttp2 - HTTP/2 C Library" href="index.html"/>
2014-02-02 10:36:57 +01:00
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js"></script>
</head>
2014-02-02 10:36:57 +01:00
<body class="wy-body-for-nav" role="document">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-nav-search">
2014-02-02 10:36:57 +01:00
<a href="index.html" class="fa fa-home"> nghttp2</a>
<div role="search">
<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>
2014-02-02 10:36:57 +01:00
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<ul class="current">
2014-04-05 12:26:23 +02:00
<li class="toctree-l1 current"><a class="current reference internal" href="">nghttp2 - HTTP/2 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>
2014-03-02 15:54:42 +01:00
<li class="toctree-l2"><a class="reference internal" href="#benchmarking-tool">Benchmarking tool</a></li>
2014-01-10 17:07:30 +01:00
<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>
2014-04-05 12:26:23 +02:00
<li class="toctree-l1"><a class="reference internal" href="tutorial-client.html">Tutorial: HTTP/2 client</a><ul>
2013-12-26 15:39:18 +01:00
<li class="toctree-l2"><a class="reference internal" href="tutorial-client.html#libevent-client-c">libevent-client.c</a></li>
</ul>
</li>
2014-04-05 12:26:23 +02:00
<li class="toctree-l1"><a class="reference internal" href="tutorial-server.html">Tutorial: HTTP/2 server</a><ul>
2013-12-26 15:39:18 +01:00
<li class="toctree-l2"><a class="reference internal" href="tutorial-server.html#libevent-server-c">libevent-server.c</a></li>
</ul>
</li>
2014-04-20 16:36:21 +02:00
<li class="toctree-l1"><a class="reference internal" href="nghttpx-howto.html">nghttpx - HOW-TO</a><ul>
<li class="toctree-l2"><a class="reference internal" href="nghttpx-howto.html#default-mode">Default mode</a></li>
<li class="toctree-l2"><a class="reference internal" href="nghttpx-howto.html#http-2-proxy-mode">HTTP/2 proxy mode</a></li>
<li class="toctree-l2"><a class="reference internal" href="nghttpx-howto.html#client-mode">Client mode</a></li>
<li class="toctree-l2"><a class="reference internal" href="nghttpx-howto.html#client-proxy-mode">Client proxy mode</a></li>
<li class="toctree-l2"><a class="reference internal" href="nghttpx-howto.html#http-2-bridge-mode">HTTP/2 bridge mode</a></li>
<li class="toctree-l2"><a class="reference internal" href="nghttpx-howto.html#disable-ssl-tls">Disable SSL/TLS</a></li>
<li class="toctree-l2"><a class="reference internal" href="nghttpx-howto.html#specifying-additional-ca-certificate">Specifying additional CA certificate</a></li>
<li class="toctree-l2"><a class="reference internal" href="nghttpx-howto.html#read-write-rate-limit">Read/write rate limit</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>
2013-12-07 06:58:21 +01:00
<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>
&nbsp;
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
2014-02-02 10:36:57 +01:00
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="index.html">nghttp2</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
2014-02-02 10:36:57 +01:00
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="index.html">Docs</a> &raquo;</li>
2014-04-05 12:26:23 +02:00
<li>nghttp2 - HTTP/2 C Library</li>
2014-02-02 10:36:57 +01:00
<li class="wy-breadcrumbs-aside">
</li>
</ul>
<hr/>
</div>
<div role="main">
2014-04-05 12:26:23 +02:00
<div class="section" id="nghttp2-http-2-c-library">
<h1>nghttp2 - HTTP/2 C Library<a class="headerlink" href="#nghttp2-http-2-c-library" title="Permalink to this headline"></a></h1>
2013-07-28 14:26:41 +02:00
<p>This is an experimental implementation of Hypertext Transfer Protocol
2014-04-05 12:26:23 +02:00
version 2.</p>
2013-07-28 14:26:41 +02:00
<div class="section" id="development-status">
<h2>Development Status<a class="headerlink" href="#development-status" title="Permalink to this headline"></a></h2>
2014-04-24 18:41:11 +02:00
<p>We started to implement h2-12
(<a class="reference external" href="http://tools.ietf.org/html/draft-ietf-httpbis-http2-12">http://tools.ietf.org/html/draft-ietf-httpbis-http2-12</a>) and the
2013-08-25 15:59:06 +02:00
header compression
2014-04-05 12:26:23 +02:00
(<a class="reference external" href="http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07">http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07</a>).</p>
2013-08-25 15:59:06 +02:00
<p>The nghttp2 code base was forked from spdylay project.</p>
<table border="1" class="docutils">
<colgroup>
2014-02-16 07:51:22 +01:00
<col width="84%" />
<col width="16%" />
2013-08-25 15:59:06 +02:00
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Features</th>
2014-04-24 18:41:11 +02:00
<th class="head">h2-12</th>
2013-08-25 15:59:06 +02:00
</tr>
</thead>
<tbody valign="top">
2014-04-24 18:41:11 +02:00
<tr class="row-even"><td>Dependency based priority</td>
2013-08-25 15:59:06 +02:00
<td>Done</td>
</tr>
2014-04-24 18:41:11 +02:00
<tr class="row-odd"><td>BLOCKED frame</td>
2013-11-02 09:01:32 +01:00
<td>Done</td>
2013-08-25 15:59:06 +02:00
</tr>
2014-04-24 18:41:11 +02:00
<tr class="row-even"><td>COMPRESSED DATA</td>
2013-08-25 15:59:06 +02:00
<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
2014-02-16 07:51:22 +01:00
implementation.</p>
2013-08-25 15:59:06 +02:00
<ul>
2014-04-18 15:56:16 +02:00
<li><p class="first"><a class="reference external" href="https://nghttp2.org/">https://nghttp2.org/</a> (TLS + NPN / ALPN)</p>
2014-04-25 16:12:23 +02:00
<p>ALPN and NPN offer <tt class="docutils literal"><span class="pre">h2-12</span></tt>, <tt class="docutils literal"><span class="pre">spdy/3.1</span></tt> and <tt class="docutils literal"><span class="pre">http/1.1</span></tt>.</p>
2013-08-25 15:59:06 +02:00
</li>
2014-04-18 15:56:16 +02:00
<li><p class="first"><a class="reference external" href="http://nghttp2.org/">http://nghttp2.org/</a> (Upgrade / Direct)</p>
2014-04-25 16:12:23 +02:00
<p><tt class="docutils literal"><span class="pre">h2c-12</span></tt> and <tt class="docutils literal"><span class="pre">http/1.1</span></tt>. We configured this server to send
2014-04-06 10:25:18 +02:00
ALTSVC frame or Alt-Svc header field to announce that alternative
service is available at port 443.</p>
2013-08-25 15:59:06 +02:00
</li>
2013-07-28 14:26:41 +02:00
</ul>
</div>
<div class="section" id="requirements">
<h2>Requirements<a class="headerlink" href="#requirements" title="Permalink to this headline"></a></h2>
2014-05-06 16:23:33 +02:00
<p>The following package is required to build the libnghttp2 library:</p>
2013-07-28 14:26:41 +02:00
<ul class="simple">
<li>pkg-config &gt;= 0.20</li>
</ul>
2014-05-06 16:23:33 +02:00
<p>To build and run the unit test programs, the following package is
2013-07-28 14:26:41 +02:00
required:</p>
<ul class="simple">
<li>cunit &gt;= 2.1</li>
</ul>
2013-09-02 16:02:05 +02:00
<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>
2013-07-28 14:26:41 +02:00
<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 &gt;= 1.0.1</li>
<li>libevent-openssl &gt;= 2.0.8</li>
2014-05-06 16:23:33 +02:00
<li>zlib &gt;= 1.2.3</li>
2013-07-28 14:26:41 +02:00
</ul>
2014-01-02 05:33:27 +01:00
<p>ALPN support requires unreleased version OpenSSL &gt;= 1.0.2.</p>
2014-03-02 15:54:42 +01:00
<p>To enable SPDY protocol in the application program <tt class="docutils literal"><span class="pre">nghttpx</span></tt> and
2014-05-06 16:23:33 +02:00
<tt class="docutils literal"><span class="pre">h2load</span></tt>, the following package is required:</p>
2013-07-28 14:26:41 +02:00
<ul class="simple">
2014-01-04 03:25:17 +01:00
<li>spdylay &gt;= 1.2.3</li>
2013-07-28 14:26:41 +02:00
</ul>
<p>To enable <tt class="docutils literal"><span class="pre">-a</span></tt> option (getting linked assets from the downloaded
2014-05-06 16:23:33 +02:00
resource) in <tt class="docutils literal"><span class="pre">nghttp</span></tt>, the following package is required:</p>
2013-07-28 14:26:41 +02:00
<ul class="simple">
<li>libxml2 &gt;= 2.7.7</li>
</ul>
2014-01-10 17:07:30 +01:00
<p>The HPACK tools require the following package:</p>
2013-10-28 15:32:57 +01:00
<ul class="simple">
2014-01-08 17:49:23 +01:00
<li>jansson &gt;= 2.5</li>
2013-10-28 15:32:57 +01:00
</ul>
2014-03-05 16:20:32 +01:00
<p>To mitigate heap fragmentation in long running server programs
(<tt class="docutils literal"><span class="pre">nghttpd</span></tt> and <tt class="docutils literal"><span class="pre">nghttpx</span></tt>), jemalloc is recommended:</p>
<ul class="simple">
<li>jemalloc</li>
</ul>
2014-01-10 17:07:30 +01:00
<p>The Python bindings require the following packages:</p>
<ul class="simple">
<li>cython &gt;= 0.19</li>
<li>python &gt;= 2.7</li>
</ul>
2013-07-28 14:26:41 +02:00
<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>
2013-10-28 15:32:57 +01:00
<li>libjansson-dev</li>
2014-03-05 16:20:32 +01:00
<li>libjemalloc-dev</li>
2013-07-28 14:26:41 +02:00
</ul>
<p>spdylay is not packaged in Ubuntu, so you need to build it yourself:
2013-11-21 14:06:29 +01:00
<a class="reference external" href="http://tatsuhiro-t.github.io/spdylay/">http://tatsuhiro-t.github.io/spdylay/</a></p>
2013-07-28 14:26:41 +02:00
</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>
2014-02-24 17:49:22 +01:00
<div class="highlight-c"><div class="highlight"><pre>$ autoreconf -i
2013-07-28 14:26:41 +02:00
$ automake
$ autoconf
$ ./configure
2014-02-24 17:49:22 +01:00
$ make
</pre></div>
2013-07-28 14:26:41 +02:00
</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>
2014-02-24 17:49:22 +01:00
<div class="highlight-c"><div class="highlight"><pre>$ make html
</pre></div>
2013-07-28 14:26:41 +02:00
</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>
2013-08-03 13:03:39 +02:00
<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>
2013-07-28 14:26:41 +02:00
</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>
2014-04-05 12:26:23 +02:00
<p>The src directory contains HTTP/2 client, server and proxy programs.</p>
2013-07-28 14:26:41 +02:00
<div class="section" id="nghttp-client">
<h3>nghttp - client<a class="headerlink" href="#nghttp-client" title="Permalink to this headline"></a></h3>
2014-04-08 17:17:05 +02:00
<p><tt class="docutils literal"><span class="pre">nghttp</span></tt> is a HTTP/2 client. It can connect to the HTTP/2 server
2014-01-01 17:03:29 +01:00
with prior knowledge, HTTP Upgrade and NPN/ALPN TLS extension.</p>
2014-04-08 17:17:05 +02:00
<p>It has verbose output mode for framing information. Here is sample
2013-07-28 14:26:41 +02:00
output from <tt class="docutils literal"><span class="pre">nghttp</span></tt> client:</p>
2014-02-24 17:49:22 +01:00
<div class="highlight-c"><div class="highlight"><pre>$ src/nghttp -nv https://localhost:8443
2014-02-16 07:51:22 +01:00
[ 0.004][NPN] server offers:
2014-04-24 18:41:11 +02:00
* h2-12
2014-02-16 07:51:22 +01:00
* spdy/3.1
2013-07-28 14:26:41 +02:00
* spdy/3
* spdy/2
* http/1.1
2014-04-24 18:41:11 +02:00
The negotiated protocol: h2-12
2014-02-16 07:51:22 +01:00
[ 0.006] send SETTINGS frame &lt;length=10, flags=0x00, stream_id=0&gt;
2013-08-25 15:59:06 +02:00
(niv=2)
2014-02-16 07:51:22 +01:00
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
[ 0.007] send HEADERS frame &lt;length=48, flags=0x05, stream_id=1&gt;
2013-07-28 14:26:41 +02:00
; END_STREAM | END_HEADERS
2014-02-16 07:51:22 +01:00
(padlen=0)
2013-07-28 14:26:41 +02:00
; Open new stream
2013-10-28 15:32:57 +01:00
:authority: localhost:8443
2013-07-28 14:26:41 +02:00
:method: GET
:path: /
:scheme: https
accept: */*
accept-encoding: gzip, deflate
2014-02-16 07:51:22 +01:00
user-agent: nghttp2/0.4.0-DEV
[ 0.007] recv SETTINGS frame &lt;length=15, flags=0x00, stream_id=0&gt;
(niv=3)
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
[SETTINGS_ENABLE_PUSH(2):0]
[ 0.007] send SETTINGS frame &lt;length=0, flags=0x01, stream_id=0&gt;
2013-10-28 15:32:57 +01:00
; ACK
(niv=0)
2014-02-16 07:51:22 +01:00
[ 0.007] recv SETTINGS frame &lt;length=0, flags=0x01, stream_id=0&gt;
2013-10-28 15:32:57 +01:00
; ACK
(niv=0)
2014-02-16 07:51:22 +01:00
[ 0.008] (stream_id=1) :status: 200
[ 0.008] (stream_id=1) accept-ranges: bytes
[ 0.008] (stream_id=1) content-encoding: gzip
[ 0.008] (stream_id=1) content-length: 146
[ 0.008] (stream_id=1) content-type: text/html
[ 0.008] (stream_id=1) date: Sat, 15 Feb 2014 08:14:12 GMT
2014-02-24 17:49:22 +01:00
[ 0.008] (stream_id=1) etag: &quot;b1-4e5535a027780-gzip&quot;
2014-02-16 07:51:22 +01:00
[ 0.008] (stream_id=1) last-modified: Sun, 01 Sep 2013 14:34:22 GMT
[ 0.008] (stream_id=1) server: Apache/2.4.6 (Debian)
[ 0.008] (stream_id=1) vary: Accept-Encoding
[ 0.008] (stream_id=1) via: 1.1 nghttpx
[ 0.008] recv HEADERS frame &lt;length=141, flags=0x04, stream_id=1&gt;
2013-07-28 14:26:41 +02:00
; END_HEADERS
2014-02-16 07:51:22 +01:00
(padlen=0)
2013-07-28 14:26:41 +02:00
; First response header
2014-02-16 07:51:22 +01:00
[ 0.008] recv DATA frame &lt;length=146, flags=0x00, stream_id=1&gt;
[ 0.008] recv DATA frame &lt;length=0, flags=0x01, stream_id=1&gt;
2013-08-25 15:59:06 +02:00
; END_STREAM
2014-02-16 07:51:22 +01:00
[ 0.008] send GOAWAY frame &lt;length=8, flags=0x00, stream_id=0&gt;
2014-02-24 17:49:22 +01:00
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
</pre></div>
2013-07-28 14:26:41 +02:00
</div>
2013-08-03 13:03:39 +02:00
<p>The HTTP Upgrade is performed like this:</p>
2014-02-24 17:49:22 +01:00
<div class="highlight-c"><div class="highlight"><pre>$ src/nghttp -nvu http://localhost:8080
2013-08-03 13:03:39 +02:00
[ 0.000] HTTP Upgrade request
GET / HTTP/1.1
2013-08-25 15:59:06 +02:00
Host: localhost:8080
2013-08-03 13:03:39 +02:00
Connection: Upgrade, HTTP2-Settings
2014-04-05 12:26:23 +02:00
Upgrade: h2c-11
2014-02-16 07:51:22 +01:00
HTTP2-Settings: AwAAAGQEAAD__w
2013-08-03 13:03:39 +02:00
Accept: */*
2014-02-16 07:51:22 +01:00
User-Agent: nghttp2/0.4.0-DEV
2013-08-03 13:03:39 +02:00
2014-02-16 07:51:22 +01:00
[ 0.001] HTTP Upgrade response
2013-08-03 13:03:39 +02:00
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
2014-04-05 12:26:23 +02:00
Upgrade: h2c-11
2013-08-03 13:03:39 +02:00
2013-10-28 15:32:57 +01:00
[ 0.001] HTTP Upgrade success
2014-02-16 07:51:22 +01:00
[ 0.001] send SETTINGS frame &lt;length=10, flags=0x00, stream_id=0&gt;
2013-08-03 13:03:39 +02:00
(niv=2)
2014-02-16 07:51:22 +01:00
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
[ 0.001] recv SETTINGS frame &lt;length=15, flags=0x00, stream_id=0&gt;
(niv=3)
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
[SETTINGS_ENABLE_PUSH(2):0]
[ 0.001] (stream_id=1) :status: 200
[ 0.001] (stream_id=1) accept-ranges: bytes
[ 0.001] (stream_id=1) content-length: 177
[ 0.001] (stream_id=1) content-type: text/html
[ 0.001] (stream_id=1) date: Sat, 15 Feb 2014 08:16:23 GMT
2014-02-24 17:49:22 +01:00
[ 0.001] (stream_id=1) etag: &quot;b1-4e5535a027780&quot;
2014-02-16 07:51:22 +01:00
[ 0.001] (stream_id=1) last-modified: Sun, 01 Sep 2013 14:34:22 GMT
[ 0.001] (stream_id=1) server: Apache/2.4.6 (Debian)
[ 0.001] (stream_id=1) vary: Accept-Encoding
[ 0.001] (stream_id=1) via: 1.1 nghttpx
[ 0.001] recv HEADERS frame &lt;length=132, flags=0x04, stream_id=1&gt;
2013-08-03 13:03:39 +02:00
; END_HEADERS
2014-02-16 07:51:22 +01:00
(padlen=0)
2013-08-03 13:03:39 +02:00
; First response header
2013-10-28 15:32:57 +01:00
[ 0.001] recv DATA frame &lt;length=177, flags=0x00, stream_id=1&gt;
2013-08-25 15:59:06 +02:00
[ 0.001] recv DATA frame &lt;length=0, flags=0x01, stream_id=1&gt;
; END_STREAM
2014-02-16 07:51:22 +01:00
[ 0.002] send SETTINGS frame &lt;length=0, flags=0x01, stream_id=0&gt;
2013-10-28 15:32:57 +01:00
; ACK
(niv=0)
2014-02-16 07:51:22 +01:00
[ 0.002] send GOAWAY frame &lt;length=8, flags=0x00, stream_id=0&gt;
2013-10-28 15:32:57 +01:00
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
2014-02-16 07:51:22 +01:00
[ 0.002] recv SETTINGS frame &lt;length=0, flags=0x01, stream_id=0&gt;
2013-10-28 15:32:57 +01:00
; ACK
2014-02-24 17:49:22 +01:00
(niv=0)
</pre></div>
2013-08-03 13:03:39 +02:00
</div>
2013-07-28 14:26:41 +02:00
</div>
<div class="section" id="nghttpd-server">
<h3>nghttpd - server<a class="headerlink" href="#nghttpd-server" title="Permalink to this headline"></a></h3>
2014-03-04 15:36:05 +01:00
<p><tt class="docutils literal"><span class="pre">nghttpd</span></tt> is a multi-threaded static web server.</p>
2014-04-08 17:17:05 +02:00
<p>By default, it uses SSL/TLS connection. Use <tt class="docutils literal"><span class="pre">--no-tls</span></tt> option to
2013-07-28 14:26:41 +02:00
disable it.</p>
2014-04-05 12:26:23 +02:00
<p><tt class="docutils literal"><span class="pre">nghttpd</span></tt> only accepts the HTTP/2 connection via NPN/ALPN or direct
2014-04-08 17:17:05 +02:00
HTTP/2 connection. No HTTP Upgrade is supported.</p>
2013-12-08 16:07:37 +01:00
<p><tt class="docutils literal"><span class="pre">-p</span></tt> option allows users to configure server push.</p>
2013-07-28 14:26:41 +02:00
<p>Just like <tt class="docutils literal"><span class="pre">nghttp</span></tt>, it has verbose output mode for framing
2014-04-08 17:17:05 +02:00
information. Here is sample output from <tt class="docutils literal"><span class="pre">nghttpd</span></tt> server:</p>
2014-02-24 17:49:22 +01:00
<div class="highlight-c"><div class="highlight"><pre>$ src/nghttpd --no-tls -v 8080
2013-08-25 15:59:06 +02:00
IPv4: listen on port 8080
IPv6: listen on port 8080
2014-02-16 07:51:22 +01:00
[id=1] [ 1.027] send SETTINGS frame &lt;length=10, flags=0x00, stream_id=0&gt;
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
[SETTINGS_ENABLE_PUSH(2):0]
[id=1] [ 1.027] recv SETTINGS frame &lt;length=10, flags=0x00, stream_id=0&gt;
2013-08-25 15:59:06 +02:00
(niv=2)
2014-02-16 07:51:22 +01:00
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
[id=1] [ 1.027] (stream_id=1) :authority: localhost:8080
[id=1] [ 1.027] (stream_id=1) :method: GET
[id=1] [ 1.027] (stream_id=1) :path: /
[id=1] [ 1.027] (stream_id=1) :scheme: http
[id=1] [ 1.027] (stream_id=1) accept: */*
[id=1] [ 1.027] (stream_id=1) accept-encoding: gzip, deflate
[id=1] [ 1.027] (stream_id=1) user-agent: nghttp2/0.4.0-DEV
[id=1] [ 1.027] recv HEADERS frame &lt;length=48, flags=0x05, stream_id=1&gt;
2013-07-28 14:26:41 +02:00
; END_STREAM | END_HEADERS
2014-02-16 07:51:22 +01:00
(padlen=0)
2013-07-28 14:26:41 +02:00
; Open new stream
2014-02-16 07:51:22 +01:00
[id=1] [ 1.027] send SETTINGS frame &lt;length=0, flags=0x01, stream_id=0&gt;
2013-10-28 15:32:57 +01:00
; ACK
(niv=0)
2014-02-16 07:51:22 +01:00
[id=1] [ 1.027] send HEADERS frame &lt;length=72, flags=0x04, stream_id=1&gt;
2013-07-28 14:26:41 +02:00
; END_HEADERS
2014-02-16 07:51:22 +01:00
(padlen=0)
2013-07-28 14:26:41 +02:00
; First response header
2013-10-28 15:32:57 +01:00
:status: 404
2013-07-28 14:26:41 +02:00
content-encoding: gzip
content-type: text/html; charset=UTF-8
2014-02-16 07:51:22 +01:00
date: Sat, 15 Feb 2014 08:18:53 GMT
server: nghttpd nghttp2/0.4.0-DEV
[id=1] [ 1.028] send DATA frame &lt;length=118, flags=0x00, stream_id=1&gt;
[id=1] [ 1.028] send DATA frame &lt;length=0, flags=0x01, stream_id=1&gt;
2013-08-25 15:59:06 +02:00
; END_STREAM
2014-02-16 07:51:22 +01:00
[id=1] [ 1.028] stream_id=1 closed
[id=1] [ 1.028] recv SETTINGS frame &lt;length=0, flags=0x01, stream_id=0&gt;
2013-10-28 15:32:57 +01:00
; ACK
(niv=0)
2014-02-16 07:51:22 +01:00
[id=1] [ 1.028] recv GOAWAY frame &lt;length=8, flags=0x00, stream_id=0&gt;
2013-08-25 15:59:06 +02:00
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
2014-02-24 17:49:22 +01:00
[id=1] [ 1.028] closed
</pre></div>
2013-07-28 14:26:41 +02:00
</div>
</div>
<div class="section" id="nghttpx-proxy">
<h3>nghttpx - proxy<a class="headerlink" href="#nghttpx-proxy" title="Permalink to this headline"></a></h3>
2014-03-03 17:17:25 +01:00
<p><tt class="docutils literal"><span class="pre">nghttpx</span></tt> is a multi-threaded reverse proxy for
2014-04-24 18:41:11 +02:00
<tt class="docutils literal"><span class="pre">h2-12</span></tt>, SPDY and HTTP/1.1. It has several operation modes:</p>
2013-07-28 14:26:41 +02:00
<table border="1" class="docutils">
<colgroup>
2014-04-05 12:26:23 +02:00
<col width="25%" />
<col width="38%" />
2013-08-03 13:03:39 +02:00
<col width="19%" />
2014-04-05 12:26:23 +02:00
<col width="18%" />
2013-07-28 14:26:41 +02:00
</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">
2013-08-03 13:03:39 +02:00
<tr class="row-even"><td>default mode</td>
2014-04-05 12:26:23 +02:00
<td>HTTP/2, SPDY, HTTP/1.1 (TLS)</td>
2013-07-28 14:26:41 +02:00
<td>HTTP/1.1</td>
<td>Reverse proxy</td>
</tr>
2013-11-04 10:27:48 +01:00
<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">--http2-proxy</span></tt></td>
2014-04-05 12:26:23 +02:00
<td>HTTP/2, SPDY, HTTP/1.1 (TLS)</td>
2013-07-28 14:26:41 +02:00
<td>HTTP/1.1</td>
<td>SPDY proxy</td>
</tr>
2013-11-04 10:27:48 +01:00
<tr class="row-even"><td><tt class="docutils literal"><span class="pre">--http2-bridge</span></tt></td>
2014-04-05 12:26:23 +02:00
<td>HTTP/2, SPDY, HTTP/1.1 (TLS)</td>
<td>HTTP/2 (TLS)</td>
2013-08-03 13:03:39 +02:00
<td>&nbsp;</td>
2013-07-28 14:26:41 +02:00
</tr>
<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">--client</span></tt></td>
2014-04-05 12:26:23 +02:00
<td>HTTP/2, HTTP/1.1</td>
<td>HTTP/2 (TLS)</td>
2013-08-03 13:03:39 +02:00
<td>&nbsp;</td>
2013-07-28 14:26:41 +02:00
</tr>
<tr class="row-even"><td><tt class="docutils literal"><span class="pre">--client-proxy</span></tt></td>
2014-04-05 12:26:23 +02:00
<td>HTTP/2, HTTP/1.1</td>
<td>HTTP/2 (TLS)</td>
2013-07-28 14:26:41 +02:00
<td>Forward proxy</td>
</tr>
</tbody>
</table>
2014-04-08 17:17:05 +02:00
<p>The interesting mode at the moment is the default mode. It works like
2014-04-24 18:41:11 +02:00
a reverse proxy and listens for <tt class="docutils literal"><span class="pre">h2-12</span></tt>, SPDY and HTTP/1.1 and can
2014-04-05 12:26:23 +02:00
be deployed SSL/TLS terminator for existing web server.</p>
2013-11-04 10:27:48 +01:00
<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
2014-04-08 17:17:05 +02:00
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 through HTTP Upgrade.</p>
2013-11-04 10:27:48 +01:00
<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
2014-04-08 17:17:05 +02:00
SSL/TLS in the backend connection by deafult. To disable SSL/TLS, use
2013-08-03 13:03:39 +02:00
<tt class="docutils literal"><span class="pre">--backend-no-tls</span></tt> option.</p>
2014-04-08 17:17:05 +02:00
<p><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
2013-07-28 14:26:41 +02:00
sample configuration file <tt class="docutils literal"><span class="pre">nghttpx.conf.sample</span></tt>.</p>
2014-03-03 17:17:25 +01:00
<p><tt class="docutils literal"><span class="pre">nghttpx</span></tt> does not support server push.</p>
2013-11-04 10:27:48 +01:00
<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>
2014-04-05 12:26:23 +02:00
<div class="highlight-c"><div class="highlight"><pre><span class="n">Client</span> <span class="o">&lt;--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mi">2</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">--&gt;</span> <span class="n">nghttpx</span> <span class="o">&lt;--</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">--&gt;</span> <span class="n">Web</span> <span class="n">Server</span>
2013-08-03 13:03:39 +02:00
<span class="p">[</span><span class="n">reverse</span> <span class="n">proxy</span><span class="p">]</span>
2013-07-28 14:26:41 +02:00
</pre></div>
</div>
2013-11-04 10:27:48 +01:00
<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>
2014-04-05 12:26:23 +02:00
<div class="highlight-c"><div class="highlight"><pre><span class="n">Client</span> <span class="o">&lt;--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mi">2</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">--&gt;</span> <span class="n">nghttpx</span> <span class="o">&lt;--</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">--&gt;</span> <span class="n">Proxy</span>
2013-08-03 13:03:39 +02:00
<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>
2013-07-28 14:26:41 +02:00
</pre></div>
</div>
2013-08-03 13:03:39 +02:00
<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>
2013-07-28 14:26:41 +02:00
<p>At the time of this writing, Chrome is the only browser which supports
2014-04-08 17:17:05 +02:00
secure proxy. The one way to configure Chrome to use secure proxy is
2013-08-03 13:03:39 +02:00
create proxy.pac script like this:</p>
2014-01-11 09:13:44 +01:00
<div class="highlight-javascript"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">FindProxyForURL</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">host</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="s2">&quot;HTTPS SERVERADDR:PORT&quot;</span><span class="p">;</span>
2013-07-28 14:26:41 +02:00
<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
2013-08-03 13:03:39 +02:00
certificate for secure proxy.</p>
2014-03-03 17:17:25 +01:00
<p>Then run Chrome with the following arguments:</p>
2014-02-24 17:49:22 +01:00
<div class="highlight-c"><div class="highlight"><pre>$ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn
</pre></div>
2013-07-28 14:26:41 +02:00
</div>
2014-04-05 12:26:23 +02:00
<p>With <tt class="docutils literal"><span class="pre">--http2-bridge</span></tt>, it accepts HTTP/2, SPDY and HTTP/1.1
connections and communicates with backend in HTTP/2:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="n">Client</span> <span class="o">&lt;--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mi">2</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">--&gt;</span> <span class="n">nghttpx</span> <span class="o">&lt;--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span> <span class="o">--&gt;</span> <span class="n">Web</span> <span class="n">or</span> <span class="n">HTTP</span><span class="o">/</span><span class="mi">2</span> <span class="n">Proxy</span> <span class="n">etc</span>
2013-08-03 13:03:39 +02:00
<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>
2013-07-28 14:26:41 +02:00
</pre></div>
</div>
2013-08-03 13:03:39 +02:00
<p>With <tt class="docutils literal"><span class="pre">--client-proxy</span></tt> option, it works as forward proxy and expects
2014-04-05 12:26:23 +02:00
that the backend is HTTP/2 proxy:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="n">Client</span> <span class="o">&lt;--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mi">2</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">--&gt;</span> <span class="n">nghttpx</span> <span class="o">&lt;--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span> <span class="o">--&gt;</span> <span class="n">HTTP</span><span class="o">/</span><span class="mi">2</span> <span class="n">Proxy</span>
2013-08-03 13:03:39 +02:00
<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>
2013-07-28 14:26:41 +02:00
</pre></div>
</div>
2014-03-03 17:17:25 +01:00
<p>The <tt class="docutils literal"><span class="pre">Client</span></tt> needs to be configured to use nghttpx as forward
2014-04-05 12:26:23 +02:00
proxy. The frontend HTTP/1.1 connection can be upgraded to HTTP/2
2013-08-03 13:03:39 +02:00
through HTTP Upgrade. With the above configuration, one can use
2014-04-05 12:26:23 +02:00
HTTP/1.1 client to access and test their HTTP/2 servers.</p>
2013-07-28 14:26:41 +02:00
<p>With <tt class="docutils literal"><span class="pre">--client</span></tt> option, it works as reverse proxy and expects that
2014-04-05 12:26:23 +02:00
the backend is HTTP/2 Web server:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="n">Client</span> <span class="o">&lt;--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mi">2</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">--&gt;</span> <span class="n">nghttpx</span> <span class="o">&lt;--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span> <span class="o">--&gt;</span> <span class="n">Web</span> <span class="n">Server</span>
2013-08-03 13:03:39 +02:00
<span class="p">[</span><span class="n">reverse</span> <span class="n">proxy</span><span class="p">]</span>
2013-07-28 14:26:41 +02:00
</pre></div>
</div>
2014-04-05 12:26:23 +02:00
<p>The frontend HTTP/1.1 connection can be upgraded to HTTP/2
2013-08-03 13:03:39 +02:00
through HTTP Upgrade.</p>
2014-04-05 12:26:23 +02:00
<p>For the operation modes which talk to the backend in HTTP/2 over
2014-04-08 17:17:05 +02:00
SSL/TLS, the backend connections can be tunneled through 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> options to talk to the outside HTTP/2
proxy through HTTP proxy:</p>
2014-04-05 12:26:23 +02:00
<div class="highlight-c"><div class="highlight"><pre><span class="n">Client</span> <span class="o">&lt;--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mi">2</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">--&gt;</span> <span class="n">nghttpx</span> <span class="o">&lt;--</span> <span class="p">(</span><span class="n">HTTP</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span> <span class="o">--</span>
2013-07-28 14:26:41 +02:00
2014-04-05 12:26:23 +02:00
<span class="o">--===================---&gt;</span> <span class="n">HTTP</span><span class="o">/</span><span class="mi">2</span> <span class="n">Proxy</span>
2013-07-28 14:26:41 +02:00
<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>
2014-03-02 15:54:42 +01:00
<div class="section" id="benchmarking-tool">
<h2>Benchmarking tool<a class="headerlink" href="#benchmarking-tool" title="Permalink to this headline"></a></h2>
<p>The <tt class="docutils literal"><span class="pre">h2load</span></tt> program is a benchmarking tool for HTTP/2 and SPDY.
The SPDY support is enabled if the program was built with spdylay
2014-04-08 17:17:05 +02:00
library. The UI of <tt class="docutils literal"><span class="pre">h2load</span></tt> is heavily inspired by <tt class="docutils literal"><span class="pre">weighttp</span></tt>
(<a class="reference external" href="https://github.com/lighttpd/weighttp">https://github.com/lighttpd/weighttp</a>). The typical usage is as
follows:</p>
2014-03-02 15:54:42 +01:00
<div class="highlight-c"><div class="highlight"><pre>$ src/h2load -n1000 -c10 -m10 https://127.0.0.1:8443/
starting benchmark...
progress: 10% done
progress: 20% done
progress: 30% done
progress: 40% done
progress: 50% done
progress: 60% done
progress: 70% done
progress: 80% done
progress: 90% done
progress: 100% done
finished in 0 sec, 152 millisec and 152 microsec, 6572 req/s, 749 kbytes/s
requests: 1000 total, 1000 started, 1000 done, 0 succeeded, 1000 failed, 0 errored
status codes: 0 2xx, 0 3xx, 1000 4xx, 0 5xx
traffic: 141100 bytes total, 840 bytes headers, 116000 bytes data
</pre></div>
</div>
<p>The above example issued total 1000 requests, using 10 concurrent
2014-03-03 17:17:25 +01:00
clients (thus 10 HTTP/2 sessions), and maximum 10 streams per client.
With <tt class="docutils literal"><span class="pre">-t</span></tt> option, <tt class="docutils literal"><span class="pre">h2load</span></tt> will use multiple native threads to
avoid saturating single core on client side.</p>
2014-03-02 15:54:42 +01:00
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
2014-04-08 17:17:05 +02:00
<p class="last"><strong>Don&#8217;t use this tool against publicly available servers.</strong> That is
considered a DOS attack. Please only use against your private
2014-03-03 17:17:25 +01:00
servers.</p>
2014-03-02 15:54:42 +01:00
</div>
</div>
2014-01-10 17:07:30 +01:00
<div class="section" id="hpack-tools">
<h2>HPACK tools<a class="headerlink" href="#hpack-tools" title="Permalink to this headline"></a></h2>
2014-04-08 17:17:05 +02:00
<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 a
command-line header compression tool. The <tt class="docutils literal"><span class="pre">inflatehd</span></tt> is
2014-01-10 17:07:30 +01:00
command-line header decompression tool. Both tools read input from
2014-04-08 17:17:05 +02:00
stdin and write output to stdout. The errors are written to stderr.
They take JSON as input and output. We use (mostly) same JSON data
format described at <a class="reference external" href="https://github.com/http2jp/hpack-test-case">https://github.com/http2jp/hpack-test-case</a></p>
2013-10-28 16:24:56 +01:00
<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>
2014-01-11 09:08:37 +01:00
<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>
2014-04-08 17:17:05 +02:00
<p>For the JSON input, the root JSON object must include <tt class="docutils literal"><span class="pre">cases</span></tt> key.
Its value has to include the sequence of input header set. They share
the same compression context and are processed in the order they
2014-02-16 07:51:22 +01:00
appear. Each item in the sequence is a JSON object and it must
2014-04-08 17:17:05 +02:00
include <tt class="docutils literal"><span class="pre">headers</span></tt> key. Its value is an array of a JSON object,
2014-02-16 07:51:22 +01:00
which includes exactly one name/value pair.</p>
2013-10-28 16:24:56 +01:00
<p>Example:</p>
2014-01-11 09:13:44 +01:00
<div class="highlight-json"><div class="highlight"><pre><span class="p">{</span>
<span class="nt">&quot;cases&quot;</span><span class="p">:</span>
2014-01-11 09:08:37 +01:00
<span class="p">[</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;headers&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span> <span class="nt">&quot;:method&quot;</span><span class="p">:</span> <span class="s2">&quot;GET&quot;</span> <span class="p">},</span>
<span class="p">{</span> <span class="nt">&quot;:path&quot;</span><span class="p">:</span> <span class="s2">&quot;/&quot;</span> <span class="p">}</span>
2014-01-11 09:08:37 +01:00
<span class="p">]</span>
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;headers&quot;</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span> <span class="nt">&quot;:method&quot;</span><span class="p">:</span> <span class="s2">&quot;POST&quot;</span> <span class="p">},</span>
<span class="p">{</span> <span class="nt">&quot;:path&quot;</span><span class="p">:</span> <span class="s2">&quot;/&quot;</span> <span class="p">}</span>
2014-01-11 09:08:37 +01:00
<span class="p">]</span>
<span class="p">}</span>
<span class="p">]</span>
<span class="p">}</span>
2013-10-28 16:24:56 +01:00
</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
2014-04-08 17:17:05 +02:00
header field block. Each header set is delimited by empty line:</p>
2013-10-28 16:24:56 +01:00
<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>
2014-04-08 17:17:05 +02:00
<p>The output is JSON object. It should include <tt class="docutils literal"><span class="pre">cases</span></tt> key and its
2014-01-11 09:08:37 +01:00
value is an array of JSON object, which has at least following keys:</p>
2013-10-28 16:24:56 +01:00
<dl class="docutils">
<dt>seq</dt>
<dd>The index of header set in the input.</dd>
2014-01-11 09:08:37 +01:00
<dt>input_length</dt>
2013-10-28 16:24:56 +01:00
<dd>The sum of length of name/value pair in the input.</dd>
2014-01-11 09:08:37 +01:00
<dt>output_length</dt>
2013-10-28 16:24:56 +01:00
<dd>The length of compressed header block.</dd>
2014-01-11 09:08:37 +01:00
<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>
2013-10-28 16:24:56 +01:00
<dd>The compressed header block in hex string.</dd>
2014-01-11 09:08:37 +01:00
<dt>headers</dt>
<dd>The input header set.</dd>
<dt>header_table_size</dt>
2014-03-03 17:17:25 +01:00
<dd>The header table size adjusted before deflating header set.</dd>
2013-10-28 16:24:56 +01:00
</dl>
<p>Examples:</p>
2014-01-11 09:13:44 +01:00
<div class="highlight-json"><div class="highlight"><pre><span class="p">{</span>
<span class="nt">&quot;cases&quot;</span><span class="p">:</span>
2014-01-11 09:08:37 +01:00
<span class="p">[</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;seq&quot;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="nt">&quot;input_length&quot;</span><span class="p">:</span> <span class="mi">66</span><span class="p">,</span>
<span class="nt">&quot;output_length&quot;</span><span class="p">:</span> <span class="mi">20</span><span class="p">,</span>
<span class="nt">&quot;percentage_of_original_size&quot;</span><span class="p">:</span> <span class="mf">30.303030303030305</span><span class="p">,</span>
<span class="nt">&quot;wire&quot;</span><span class="p">:</span> <span class="s2">&quot;01881f3468e5891afcbf83868a3d856659c62e3f&quot;</span><span class="p">,</span>
<span class="nt">&quot;headers&quot;</span><span class="p">:</span> <span class="p">[</span>
2014-01-11 09:08:37 +01:00
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:authority&quot;</span><span class="p">:</span> <span class="s2">&quot;example.org&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:method&quot;</span><span class="p">:</span> <span class="s2">&quot;GET&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:path&quot;</span><span class="p">:</span> <span class="s2">&quot;/&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:scheme&quot;</span><span class="p">:</span> <span class="s2">&quot;https&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;user-agent&quot;</span><span class="p">:</span> <span class="s2">&quot;nghttp2&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">}</span>
<span class="p">],</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;header_table_size&quot;</span><span class="p">:</span> <span class="mi">4096</span>
2014-01-11 09:08:37 +01:00
<span class="p">}</span>
<span class="p">,</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;seq&quot;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="nt">&quot;input_length&quot;</span><span class="p">:</span> <span class="mi">74</span><span class="p">,</span>
<span class="nt">&quot;output_length&quot;</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span>
<span class="nt">&quot;percentage_of_original_size&quot;</span><span class="p">:</span> <span class="mf">13.513513513513514</span><span class="p">,</span>
<span class="nt">&quot;wire&quot;</span><span class="p">:</span> <span class="s2">&quot;88448504252dd5918485&quot;</span><span class="p">,</span>
<span class="nt">&quot;headers&quot;</span><span class="p">:</span> <span class="p">[</span>
2014-01-11 09:08:37 +01:00
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:authority&quot;</span><span class="p">:</span> <span class="s2">&quot;example.org&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:method&quot;</span><span class="p">:</span> <span class="s2">&quot;POST&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:path&quot;</span><span class="p">:</span> <span class="s2">&quot;/account&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:scheme&quot;</span><span class="p">:</span> <span class="s2">&quot;https&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;user-agent&quot;</span><span class="p">:</span> <span class="s2">&quot;nghttp2&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">}</span>
<span class="p">],</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;header_table_size&quot;</span><span class="p">:</span> <span class="mi">4096</span>
2014-01-11 09:08:37 +01:00
<span class="p">}</span>
<span class="p">]</span>
<span class="p">}</span>
2013-10-28 16:24:56 +01:00
</pre></div>
</div>
2014-01-11 09:08:37 +01:00
<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
2014-03-03 17:17:25 +01:00
associated value includes the state of dynamic header table after the
2014-04-08 17:17:05 +02:00
corresponding header set was processed. The value includes at least
the following keys:</p>
2013-10-28 16:24:56 +01:00
<dl class="docutils">
<dt>entries</dt>
2014-04-08 17:17:05 +02:00
<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.
2013-10-28 16:24:56 +01:00
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
2014-04-08 17:17:05 +02:00
header field value.</dd>
2013-10-28 16:24:56 +01:00
<dt>size</dt>
<dd>The sum of the spaces entries occupied, this includes the
entry overhead.</dd>
2014-01-11 09:08:37 +01:00
<dt>max_size</dt>
2013-10-28 16:24:56 +01:00
<dd>The maximum header table size.</dd>
2014-01-11 09:08:37 +01:00
<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>
2014-04-08 17:17:05 +02:00
<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
2014-01-11 09:08:37 +01:00
<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>
2013-10-28 16:24:56 +01:00
</dl>
<p>Example:</p>
2014-01-11 09:13:44 +01:00
<div class="highlight-json"><div class="highlight"><pre><span class="p">{</span>
<span class="nt">&quot;cases&quot;</span><span class="p">:</span>
2014-01-11 09:08:37 +01:00
<span class="p">[</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;seq&quot;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="nt">&quot;input_length&quot;</span><span class="p">:</span> <span class="mi">66</span><span class="p">,</span>
<span class="nt">&quot;output_length&quot;</span><span class="p">:</span> <span class="mi">20</span><span class="p">,</span>
<span class="nt">&quot;percentage_of_original_size&quot;</span><span class="p">:</span> <span class="mf">30.303030303030305</span><span class="p">,</span>
<span class="nt">&quot;wire&quot;</span><span class="p">:</span> <span class="s2">&quot;01881f3468e5891afcbf83868a3d856659c62e3f&quot;</span><span class="p">,</span>
<span class="nt">&quot;headers&quot;</span><span class="p">:</span> <span class="p">[</span>
2013-10-28 16:24:56 +01:00
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:authority&quot;</span><span class="p">:</span> <span class="s2">&quot;example.org&quot;</span>
2013-10-28 16:24:56 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:method&quot;</span><span class="p">:</span> <span class="s2">&quot;GET&quot;</span>
2013-10-28 16:24:56 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:path&quot;</span><span class="p">:</span> <span class="s2">&quot;/&quot;</span>
2013-10-28 16:24:56 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:scheme&quot;</span><span class="p">:</span> <span class="s2">&quot;https&quot;</span>
2013-10-28 16:24:56 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;user-agent&quot;</span><span class="p">:</span> <span class="s2">&quot;nghttp2&quot;</span>
2013-10-28 16:24:56 +01:00
<span class="p">}</span>
<span class="p">],</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;header_table_size&quot;</span><span class="p">:</span> <span class="mi">4096</span><span class="p">,</span>
<span class="nt">&quot;header_table&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;entries&quot;</span><span class="p">:</span> <span class="p">[</span>
2014-01-11 09:08:37 +01:00
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;index&quot;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;user-agent&quot;</span><span class="p">,</span>
<span class="nt">&quot;value&quot;</span><span class="p">:</span> <span class="s2">&quot;nghttp2&quot;</span><span class="p">,</span>
<span class="nt">&quot;referenced&quot;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="nt">&quot;size&quot;</span><span class="p">:</span> <span class="mi">49</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;index&quot;</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;:scheme&quot;</span><span class="p">,</span>
<span class="nt">&quot;value&quot;</span><span class="p">:</span> <span class="s2">&quot;https&quot;</span><span class="p">,</span>
<span class="nt">&quot;referenced&quot;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="nt">&quot;size&quot;</span><span class="p">:</span> <span class="mi">44</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;index&quot;</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;:path&quot;</span><span class="p">,</span>
<span class="nt">&quot;value&quot;</span><span class="p">:</span> <span class="s2">&quot;/&quot;</span><span class="p">,</span>
<span class="nt">&quot;referenced&quot;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="nt">&quot;size&quot;</span><span class="p">:</span> <span class="mi">38</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;index&quot;</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;:method&quot;</span><span class="p">,</span>
<span class="nt">&quot;value&quot;</span><span class="p">:</span> <span class="s2">&quot;GET&quot;</span><span class="p">,</span>
<span class="nt">&quot;referenced&quot;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="nt">&quot;size&quot;</span><span class="p">:</span> <span class="mi">42</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;index&quot;</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;:authority&quot;</span><span class="p">,</span>
<span class="nt">&quot;value&quot;</span><span class="p">:</span> <span class="s2">&quot;example.org&quot;</span><span class="p">,</span>
<span class="nt">&quot;referenced&quot;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="nt">&quot;size&quot;</span><span class="p">:</span> <span class="mi">53</span>
2014-01-11 09:08:37 +01:00
<span class="p">}</span>
<span class="p">],</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;size&quot;</span><span class="p">:</span> <span class="mi">226</span><span class="p">,</span>
<span class="nt">&quot;max_size&quot;</span><span class="p">:</span> <span class="mi">4096</span><span class="p">,</span>
<span class="nt">&quot;deflate_size&quot;</span><span class="p">:</span> <span class="mi">226</span><span class="p">,</span>
<span class="nt">&quot;max_deflate_size&quot;</span><span class="p">:</span> <span class="mi">4096</span>
2014-01-11 09:08:37 +01:00
<span class="p">}</span>
2013-10-28 16:24:56 +01:00
<span class="p">}</span>
2014-01-11 09:08:37 +01:00
<span class="p">,</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;seq&quot;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="nt">&quot;input_length&quot;</span><span class="p">:</span> <span class="mi">74</span><span class="p">,</span>
<span class="nt">&quot;output_length&quot;</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span>
<span class="nt">&quot;percentage_of_original_size&quot;</span><span class="p">:</span> <span class="mf">13.513513513513514</span><span class="p">,</span>
<span class="nt">&quot;wire&quot;</span><span class="p">:</span> <span class="s2">&quot;88448504252dd5918485&quot;</span><span class="p">,</span>
<span class="nt">&quot;headers&quot;</span><span class="p">:</span> <span class="p">[</span>
2013-10-28 16:24:56 +01:00
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:authority&quot;</span><span class="p">:</span> <span class="s2">&quot;example.org&quot;</span>
2013-10-28 16:24:56 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:method&quot;</span><span class="p">:</span> <span class="s2">&quot;POST&quot;</span>
2013-10-28 16:24:56 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:path&quot;</span><span class="p">:</span> <span class="s2">&quot;/account&quot;</span>
2013-10-28 16:24:56 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:scheme&quot;</span><span class="p">:</span> <span class="s2">&quot;https&quot;</span>
2013-10-28 16:24:56 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;user-agent&quot;</span><span class="p">:</span> <span class="s2">&quot;nghttp2&quot;</span>
2013-10-28 16:24:56 +01:00
<span class="p">}</span>
<span class="p">],</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;header_table_size&quot;</span><span class="p">:</span> <span class="mi">4096</span><span class="p">,</span>
<span class="nt">&quot;header_table&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;entries&quot;</span><span class="p">:</span> <span class="p">[</span>
2014-01-11 09:08:37 +01:00
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;index&quot;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;:method&quot;</span><span class="p">,</span>
<span class="nt">&quot;value&quot;</span><span class="p">:</span> <span class="s2">&quot;POST&quot;</span><span class="p">,</span>
<span class="nt">&quot;referenced&quot;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="nt">&quot;size&quot;</span><span class="p">:</span> <span class="mi">43</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;index&quot;</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;user-agent&quot;</span><span class="p">,</span>
<span class="nt">&quot;value&quot;</span><span class="p">:</span> <span class="s2">&quot;nghttp2&quot;</span><span class="p">,</span>
<span class="nt">&quot;referenced&quot;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="nt">&quot;size&quot;</span><span class="p">:</span> <span class="mi">49</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;index&quot;</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;:scheme&quot;</span><span class="p">,</span>
<span class="nt">&quot;value&quot;</span><span class="p">:</span> <span class="s2">&quot;https&quot;</span><span class="p">,</span>
<span class="nt">&quot;referenced&quot;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="nt">&quot;size&quot;</span><span class="p">:</span> <span class="mi">44</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;index&quot;</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;:path&quot;</span><span class="p">,</span>
<span class="nt">&quot;value&quot;</span><span class="p">:</span> <span class="s2">&quot;/&quot;</span><span class="p">,</span>
<span class="nt">&quot;referenced&quot;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="nt">&quot;size&quot;</span><span class="p">:</span> <span class="mi">38</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;index&quot;</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;:method&quot;</span><span class="p">,</span>
<span class="nt">&quot;value&quot;</span><span class="p">:</span> <span class="s2">&quot;GET&quot;</span><span class="p">,</span>
<span class="nt">&quot;referenced&quot;</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="nt">&quot;size&quot;</span><span class="p">:</span> <span class="mi">42</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;index&quot;</span><span class="p">:</span> <span class="mi">6</span><span class="p">,</span>
<span class="nt">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;:authority&quot;</span><span class="p">,</span>
<span class="nt">&quot;value&quot;</span><span class="p">:</span> <span class="s2">&quot;example.org&quot;</span><span class="p">,</span>
<span class="nt">&quot;referenced&quot;</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="nt">&quot;size&quot;</span><span class="p">:</span> <span class="mi">53</span>
2014-01-11 09:08:37 +01:00
<span class="p">}</span>
<span class="p">],</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;size&quot;</span><span class="p">:</span> <span class="mi">269</span><span class="p">,</span>
<span class="nt">&quot;max_size&quot;</span><span class="p">:</span> <span class="mi">4096</span><span class="p">,</span>
<span class="nt">&quot;deflate_size&quot;</span><span class="p">:</span> <span class="mi">269</span><span class="p">,</span>
<span class="nt">&quot;max_deflate_size&quot;</span><span class="p">:</span> <span class="mi">4096</span>
2014-01-11 09:08:37 +01:00
<span class="p">}</span>
2013-10-28 16:24:56 +01:00
<span class="p">}</span>
2014-01-11 09:08:37 +01:00
<span class="p">]</span>
<span class="p">}</span>
2013-10-28 16:24:56 +01:00
</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>
2014-01-11 09:08:37 +01:00
<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>
2014-04-08 17:17:05 +02:00
<p>The root JSON object must include <tt class="docutils literal"><span class="pre">cases</span></tt> key. Its value has to
include the sequence of compressed header block. They share the same
compression context and are processed in the order they appear. Each
2014-02-16 07:51:22 +01:00
item in the sequence is a JSON object and it must have at least
2014-04-08 17:17:05 +02:00
<tt class="docutils literal"><span class="pre">wire</span></tt> key. Its value is a compressed header block in hex string.</p>
2013-10-28 16:24:56 +01:00
<p>Example:</p>
2014-01-11 09:13:44 +01:00
<div class="highlight-json"><div class="highlight"><pre><span class="p">{</span>
<span class="nt">&quot;cases&quot;</span><span class="p">:</span>
2014-01-11 09:08:37 +01:00
<span class="p">[</span>
2014-01-11 09:13:44 +01:00
<span class="p">{</span> <span class="nt">&quot;wire&quot;</span><span class="p">:</span> <span class="s2">&quot;8285&quot;</span> <span class="p">},</span>
<span class="p">{</span> <span class="nt">&quot;wire&quot;</span><span class="p">:</span> <span class="s2">&quot;8583&quot;</span> <span class="p">}</span>
2014-01-11 09:08:37 +01:00
<span class="p">]</span>
<span class="p">}</span>
2013-10-28 16:24:56 +01:00
</pre></div>
</div>
2014-04-08 17:17:05 +02:00
<p>The output is JSON object. It should include <tt class="docutils literal"><span class="pre">cases</span></tt> key and its
2014-01-11 09:08:37 +01:00
value is an array of JSON object, which has at least following keys:</p>
2013-10-28 16:24:56 +01:00
<dl class="docutils">
<dt>seq</dt>
<dd>The index of header set in the input.</dd>
<dt>headers</dt>
2014-02-16 07:51:22 +01:00
<dd>The JSON array includes decompressed name/value pairs.</dd>
2014-01-11 09:08:37 +01:00
<dt>wire</dt>
<dd>The compressed header block in hex string.</dd>
<dt>header_table_size</dt>
2014-03-03 17:17:25 +01:00
<dd>The header table size adjusted before inflating compressed header
2014-01-11 09:08:37 +01:00
block.</dd>
2013-10-28 16:24:56 +01:00
</dl>
<p>Example:</p>
2014-01-11 09:13:44 +01:00
<div class="highlight-json"><div class="highlight"><pre><span class="p">{</span>
<span class="nt">&quot;cases&quot;</span><span class="p">:</span>
2014-01-11 09:08:37 +01:00
<span class="p">[</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;seq&quot;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="nt">&quot;wire&quot;</span><span class="p">:</span> <span class="s2">&quot;01881f3468e5891afcbf83868a3d856659c62e3f&quot;</span><span class="p">,</span>
<span class="nt">&quot;headers&quot;</span><span class="p">:</span> <span class="p">[</span>
2014-01-11 09:08:37 +01:00
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:authority&quot;</span><span class="p">:</span> <span class="s2">&quot;example.org&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:method&quot;</span><span class="p">:</span> <span class="s2">&quot;GET&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:path&quot;</span><span class="p">:</span> <span class="s2">&quot;/&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:scheme&quot;</span><span class="p">:</span> <span class="s2">&quot;https&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;user-agent&quot;</span><span class="p">:</span> <span class="s2">&quot;nghttp2&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">}</span>
<span class="p">],</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;header_table_size&quot;</span><span class="p">:</span> <span class="mi">4096</span>
2014-01-11 09:08:37 +01:00
<span class="p">}</span>
<span class="p">,</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;seq&quot;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="nt">&quot;wire&quot;</span><span class="p">:</span> <span class="s2">&quot;88448504252dd5918485&quot;</span><span class="p">,</span>
<span class="nt">&quot;headers&quot;</span><span class="p">:</span> <span class="p">[</span>
2014-01-11 09:08:37 +01:00
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:method&quot;</span><span class="p">:</span> <span class="s2">&quot;POST&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:path&quot;</span><span class="p">:</span> <span class="s2">&quot;/account&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;user-agent&quot;</span><span class="p">:</span> <span class="s2">&quot;nghttp2&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:scheme&quot;</span><span class="p">:</span> <span class="s2">&quot;https&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">},</span>
<span class="p">{</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;:authority&quot;</span><span class="p">:</span> <span class="s2">&quot;example.org&quot;</span>
2014-01-11 09:08:37 +01:00
<span class="p">}</span>
<span class="p">],</span>
2014-01-11 09:13:44 +01:00
<span class="nt">&quot;header_table_size&quot;</span><span class="p">:</span> <span class="mi">4096</span>
2014-01-11 09:08:37 +01:00
<span class="p">}</span>
<span class="p">]</span>
<span class="p">}</span>
2013-10-28 16:24:56 +01:00
</pre></div>
</div>
2014-01-11 09:08:37 +01:00
<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
2014-03-03 17:17:25 +01:00
associated value includes the state of dynamic header table after the
2014-04-08 17:17:05 +02:00
corresponding header set was processed. The format is the same as
2013-10-28 16:24:56 +01:00
<tt class="docutils literal"><span class="pre">deflatehd</span></tt>.</p>
</div>
</div>
2014-01-10 17:07:30 +01:00
<div class="section" id="python-bindings">
<h2>Python bindings<a class="headerlink" href="#python-bindings" title="Permalink to this headline"></a></h2>
2014-04-08 17:17:05 +02:00
<p>This <tt class="docutils literal"><span class="pre">python</span></tt> directory contains nghttp2 Python bindings. The
bindings currently provide HPACK compressor and decompressor classes
and HTTP/2 server.</p>
2014-01-10 17:07:30 +01:00
<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
2014-04-08 17:17:05 +02:00
determined by configure script. If the detected Python version is not
2014-01-10 17:07:30 +01:00
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>
<p>The following example code illustrates basic usage of HPACK compressor
and decompressor in Python:</p>
2014-01-10 18:03:15 +01:00
<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>
2014-01-10 17:07:30 +01:00
2014-02-16 07:51:22 +01:00
<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">inflater</span> <span class="o">=</span> <span class="n">nghttp2</span><span class="o">.</span><span class="n">HDInflater</span><span class="p">()</span>
2014-01-10 17:07:30 +01:00
2014-01-10 18:03:15 +01:00
<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">&#39;foo&#39;</span><span class="p">,</span> <span class="n">b</span><span class="s">&#39;bar&#39;</span><span class="p">),</span>
<span class="p">(</span><span class="n">b</span><span class="s">&#39;baz&#39;</span><span class="p">,</span> <span class="n">b</span><span class="s">&#39;buz&#39;</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>
2014-01-10 17:07:30 +01:00
2014-01-10 18:03:15 +01:00
<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>
2014-01-10 17:07:30 +01:00
</div>
2014-02-24 17:49:22 +01:00
<p>The <tt class="docutils literal"><span class="pre">nghttp2.HTTP2Server</span></tt> class builds on top of the asyncio event
2014-04-08 17:17:05 +02:00
loop. On construction, <em>RequestHandlerClass</em> must be given, which
must be a subclass of <tt class="docutils literal"><span class="pre">nghttp2.BaseRequestHandler</span></tt> class.</p>
<p>The <tt class="docutils literal"><span class="pre">BaseRequestHandler</span></tt> class is used to handle the HTTP/2 stream.
By default, it does nothing. It must be subclassed to handle each
event callback method.</p>
<p>The first callback method invoked is <tt class="docutils literal"><span class="pre">on_headers()</span></tt>. It is called
2014-03-03 17:17:25 +01:00
when HEADERS frame, which includes request header fields, has arrived.</p>
2014-02-24 17:49:22 +01:00
<p>If request has request body, <tt class="docutils literal"><span class="pre">on_data(data)</span></tt> is invoked for each
chunk of received data.</p>
<p>When whole request is received, <tt class="docutils literal"><span class="pre">on_request_done()</span></tt> is invoked.</p>
<p>When stream is closed, <tt class="docutils literal"><span class="pre">on_close(error_code)</span></tt> is called.</p>
2014-04-08 17:17:05 +02:00
<p>The application can send response using <tt class="docutils literal"><span class="pre">send_response()</span></tt> method.
It can be used in <tt class="docutils literal"><span class="pre">on_headers()</span></tt>, <tt class="docutils literal"><span class="pre">on_data()</span></tt> or
2014-02-24 17:49:22 +01:00
<tt class="docutils literal"><span class="pre">on_request_done()</span></tt>.</p>
2014-04-08 17:17:05 +02:00
<p>The application can push resource using <tt class="docutils literal"><span class="pre">push()</span></tt> method. It must be
2014-02-24 17:49:22 +01:00
used before <tt class="docutils literal"><span class="pre">send_response()</span></tt> call.</p>
<p>The following instance variables are available:</p>
<dl class="docutils">
<dt>client_address</dt>
<dd>Contains a tuple of the form (host, port) referring to the
client&#8217;s address.</dd>
<dt>stream_id</dt>
2014-03-03 17:17:25 +01:00
<dd>Stream ID of this stream.</dd>
2014-02-24 17:49:22 +01:00
<dt>scheme</dt>
2014-04-08 17:17:05 +02:00
<dd>Scheme of the request URI. This is a value of :scheme header
field.</dd>
2014-02-24 17:49:22 +01:00
<dt>method</dt>
2014-04-08 17:17:05 +02:00
<dd>Method of this stream. This is a value of :method header field.</dd>
2014-02-24 17:49:22 +01:00
<dt>host</dt>
<dd>This is a value of :authority or host header field.</dd>
<dt>path</dt>
<dd>This is a value of :path header field.</dd>
</dl>
<p>The following example illustrates the HTTP2Server and
BaseRequestHandler usage:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c">#!/usr/bin/env python</span>
<span class="kn">import</span> <span class="nn">io</span><span class="o">,</span> <span class="nn">ssl</span>
<span class="kn">import</span> <span class="nn">nghttp2</span>
<span class="k">class</span> <span class="nc">Handler</span><span class="p">(</span><span class="n">nghttp2</span><span class="o">.</span><span class="n">BaseRequestHandler</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">on_headers</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">push</span><span class="p">(</span><span class="n">path</span><span class="o">=</span><span class="s">&#39;/css/bootstrap.css&#39;</span><span class="p">,</span>
2014-02-25 16:02:26 +01:00
<span class="n">request_headers</span> <span class="o">=</span> <span class="p">[(</span><span class="s">&#39;content-length&#39;</span><span class="p">,</span> <span class="s">&#39;3&#39;</span><span class="p">)],</span>
2014-02-24 17:49:22 +01:00
<span class="n">status</span><span class="o">=</span><span class="mi">200</span><span class="p">,</span>
<span class="n">body</span><span class="o">=</span><span class="s">&#39;foo&#39;</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">push</span><span class="p">(</span><span class="n">path</span><span class="o">=</span><span class="s">&#39;/js/bootstrap.js&#39;</span><span class="p">,</span>
<span class="n">method</span><span class="o">=</span><span class="s">&#39;GET&#39;</span><span class="p">,</span>
2014-02-25 16:02:26 +01:00
<span class="n">request_headers</span> <span class="o">=</span> <span class="p">[(</span><span class="s">&#39;content-length&#39;</span><span class="p">,</span> <span class="s">&#39;10&#39;</span><span class="p">)],</span>
2014-02-24 17:49:22 +01:00
<span class="n">status</span><span class="o">=</span><span class="mi">200</span><span class="p">,</span>
<span class="n">body</span><span class="o">=</span><span class="s">&#39;foobarbuzz&#39;</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">send_response</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="mi">200</span><span class="p">,</span>
2014-02-25 16:02:26 +01:00
<span class="n">headers</span> <span class="o">=</span> <span class="p">[(</span><span class="s">&#39;content-type&#39;</span><span class="p">,</span> <span class="s">&#39;text/plain&#39;</span><span class="p">)],</span>
2014-02-24 17:49:22 +01:00
<span class="n">body</span><span class="o">=</span><span class="n">io</span><span class="o">.</span><span class="n">BytesIO</span><span class="p">(</span><span class="n">b</span><span class="s">&#39;nghttp2-python FTW&#39;</span><span class="p">))</span>
<span class="n">ctx</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">SSLContext</span><span class="p">(</span><span class="n">ssl</span><span class="o">.</span><span class="n">PROTOCOL_SSLv23</span><span class="p">)</span>
<span class="n">ctx</span><span class="o">.</span><span class="n">options</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">OP_ALL</span> <span class="o">|</span> <span class="n">ssl</span><span class="o">.</span><span class="n">OP_NO_SSLv2</span>
<span class="n">ctx</span><span class="o">.</span><span class="n">load_cert_chain</span><span class="p">(</span><span class="s">&#39;server.crt&#39;</span><span class="p">,</span> <span class="s">&#39;server.key&#39;</span><span class="p">)</span>
<span class="c"># give None to ssl to make the server non-SSL/TLS</span>
<span class="n">server</span> <span class="o">=</span> <span class="n">nghttp2</span><span class="o">.</span><span class="n">HTTP2Server</span><span class="p">((</span><span class="s">&#39;127.0.0.1&#39;</span><span class="p">,</span> <span class="mi">8443</span><span class="p">),</span> <span class="n">Handler</span><span class="p">,</span> <span class="n">ssl</span><span class="o">=</span><span class="n">ctx</span><span class="p">)</span>
<span class="n">server</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span>
</pre></div>
2014-01-10 17:07:30 +01:00
</div>
</div>
2013-07-28 14:26:41 +02:00
</div>
2014-02-02 10:36:57 +01:00
</div>
<footer>
2014-02-02 10:36:57 +01:00
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
2014-04-05 12:26:23 +02:00
<a href="tutorial-client.html" class="btn btn-neutral float-right" title="Tutorial: HTTP/2 client"/>Next <span class="fa fa-arrow-circle-right"></span></a>
2014-04-05 12:26:23 +02:00
<a href="index.html" class="btn btn-neutral" title="nghttp2 - HTTP/2 C Library"><span class="fa fa-arrow-circle-left"></span> Previous</a>
</div>
<hr/>
2014-02-02 10:36:57 +01:00
<div role="contentinfo">
<p>
&copy; Copyright 2012, 2014, Tatsuhiro Tsujikawa.
</p>
</div>
2013-07-28 14:26:41 +02:00
2014-02-02 10:36:57 +01:00
<a href="https://github.com/snide/sphinx_rtd_theme">Sphinx theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>
</footer>
2013-07-28 14:26:41 +02:00
</div>
</div>
</section>
</div>
</body>
2013-07-28 14:26:41 +02:00
</html>