1265 lines
81 KiB
HTML
1265 lines
81 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 C Library — nghttp2 0.4.2-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'>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
|
|
|
|
|
|
|
|
<link rel="top" title="nghttp2 0.4.2-DEV documentation" href="index.html"/>
|
|
<link rel="next" title="Tutorial: HTTP/2 client" href="tutorial-client.html"/>
|
|
<link rel="prev" title="nghttp2 - HTTP/2 C Library" href="index.html"/>
|
|
|
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js"></script>
|
|
|
|
</head>
|
|
|
|
<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">
|
|
<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>
|
|
|
|
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
|
|
|
|
|
|
<ul class="current">
|
|
<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>
|
|
<li class="toctree-l2"><a class="reference internal" href="#benchmarking-tool">Benchmarking tool</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 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 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="tutorial-hpack.html">Tutorial: HPACK API</a><ul>
|
|
<li class="toctree-l2"><a class="reference internal" href="tutorial-hpack.html#deflating-encoding-headers">Deflating (encoding) headers</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="tutorial-hpack.html#inflating-decoding-headers">Inflating (decoding) headers</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="tutorial-hpack.html#deflate-c">deflate.c</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="toctree-l1"><a class="reference internal" href="nghttpx-howto.html">nghttpx - HTTP/2 proxy - 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>
|
|
<li class="toctree-l2"><a class="reference internal" href="nghttpx-howto.html#rewriting-location-header-field">Rewriting location header field</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="toctree-l1"><a class="reference internal" href="h2load-howto.html">h2load - HTTP/2 benchmarking tool - HOW-TO</a><ul>
|
|
<li class="toctree-l2"><a class="reference internal" href="h2load-howto.html#basic-usage">Basic Usage</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="h2load-howto.html#flow-control">Flow Control</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="h2load-howto.html#multi-threading">Multi-Threading</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="h2load-howto.html#selecting-protocol-for-clear-text">Selecting protocol for clear text</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="h2load-howto.html#multiple-uris">Multiple URIs</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="python-apiref.html">Python API Reference</a><ul>
|
|
<li class="toctree-l2"><a class="reference internal" href="python-apiref.html#hpack-api">HPACK API</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="python-apiref.html#http-2-servers">HTTP/2 servers</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" 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">
|
|
<div role="navigation" aria-label="breadcrumbs navigation">
|
|
<ul class="wy-breadcrumbs">
|
|
<li><a href="index.html">Docs</a> »</li>
|
|
|
|
<li>nghttp2 - HTTP/2 C Library</li>
|
|
<li class="wy-breadcrumbs-aside">
|
|
|
|
</li>
|
|
</ul>
|
|
<hr/>
|
|
</div>
|
|
<div role="main">
|
|
|
|
<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>
|
|
<p>This is an implementation of Hypertext Transfer Protocol version 2
|
|
in C.</p>
|
|
<p>The framing layer of HTTP/2 is implemented as form of reusable C
|
|
library. On top of that, we have implemented HTTP/2 client, server
|
|
and proxy. Also we have developed load test/benchmarking tool for
|
|
HTTP/2 and SPDY.</p>
|
|
<p>HPACK encoding and decoding are available as public API.</p>
|
|
<p>We didn’t cover everything, but we have Python binding of this libary.</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 h2-13
|
|
(<a class="reference external" href="http://tools.ietf.org/html/draft-ietf-httpbis-http2-13">http://tools.ietf.org/html/draft-ietf-httpbis-http2-13</a>) and the
|
|
header compression
|
|
(<a class="reference external" href="http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08">http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08</a>).</p>
|
|
<p>The nghttp2 code base was forked from spdylay project.</p>
|
|
<table border="1" class="docutils">
|
|
<colgroup>
|
|
<col width="79%" />
|
|
<col width="21%" />
|
|
</colgroup>
|
|
<thead valign="bottom">
|
|
<tr class="row-odd"><th class="head">HTTP/2 Features</th>
|
|
<th class="head">Support</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody valign="top">
|
|
<tr class="row-even"><td>Core frames handling</td>
|
|
<td>Yes</td>
|
|
</tr>
|
|
<tr class="row-odd"><td>Dependency Tree</td>
|
|
<td>Yes</td>
|
|
</tr>
|
|
<tr class="row-even"><td>Large header (CONTINUATION)</td>
|
|
<td>Yes</td>
|
|
</tr>
|
|
<tr class="row-odd"><td>ALTSVC extension</td>
|
|
<td>Yes *1</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<ul class="simple">
|
|
<li>*1 As described in draft-12, but reserved byte was removed. ALTSVC
|
|
may be removed from nghttp2 public API since it is not stabilized
|
|
yet.</li>
|
|
</ul>
|
|
<p>BLOCKED frame, which once existed in h2-12, was removed in h2-13.</p>
|
|
</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.</p>
|
|
<ul>
|
|
<li><p class="first"><a class="reference external" href="https://nghttp2.org/">https://nghttp2.org/</a> (TLS + NPN)</p>
|
|
<p>NPN offer <tt class="docutils literal"><span class="pre">h2-13</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>.
|
|
ALPN is currently disabled.</p>
|
|
<p>This endpoint requires TLSv1.2 and DHE or EDCHE with GCM cipher
|
|
suite for HTTP/2 connection.</p>
|
|
</li>
|
|
<li><p class="first"><a class="reference external" href="http://nghttp2.org/">http://nghttp2.org/</a> (Upgrade / Direct)</p>
|
|
<p><tt class="docutils literal"><span class="pre">h2c-13</span></tt> and <tt class="docutils literal"><span class="pre">http/1.1</span></tt>. We configured this server to send
|
|
ALTSVC frame or Alt-Svc header field to announce that alternative
|
|
service is available at port 443.</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 package is required to build the libnghttp2 library:</p>
|
|
<ul class="simple">
|
|
<li>pkg-config >= 0.20</li>
|
|
</ul>
|
|
<p>To build and run the unit test programs, the following package is
|
|
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>
|
|
<li>zlib >= 1.2.3</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> and
|
|
<tt class="docutils literal"><span class="pre">h2load</span></tt>, the following package is 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 package is required:</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>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>
|
|
<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 14.04 LTS, 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>
|
|
<li>libjemalloc-dev</li>
|
|
<li>cython</li>
|
|
<li>python3.4-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"><div class="highlight"><pre>$ autoreconf -i
|
|
$ automake
|
|
$ autoconf
|
|
$ ./configure
|
|
$ make
|
|
</pre></div>
|
|
</div>
|
|
<div class="admonition note">
|
|
<p class="first admonition-title">Note</p>
|
|
<p class="last">Mac OS X users may need <tt class="docutils literal"><span class="pre">--disable-threads</span></tt> configure option to
|
|
disable multi threading in nghttpd, nghttpx and h2load to prevent
|
|
them from crashing. Patch is welcome to make multi threading work
|
|
on Mac OS X platform.</p>
|
|
</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"><div class="highlight"><pre>$ make html
|
|
</pre></div>
|
|
</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="https://nghttp2.org/documentation/">https://nghttp2.org/documentation/</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 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 client. It can connect to the HTTP/2 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"><div class="highlight"><pre>$ src/nghttp -nv https://nghttp2.org
|
|
[ 0.033][NPN] server offers:
|
|
* h2-13
|
|
* spdy/3.1
|
|
* http/1.1
|
|
The negotiated protocol: h2-13
|
|
[ 0.068] send SETTINGS frame <length=15, flags=0x00, stream_id=0>
|
|
(niv=3)
|
|
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
|
|
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
|
|
[SETTINGS_COMPRESS_DATA(5):1]
|
|
[ 0.068] send HEADERS frame <length=46, flags=0x05, stream_id=1>
|
|
; END_STREAM | END_HEADERS
|
|
(padlen=0)
|
|
; Open new stream
|
|
:authority: nghttp2.org
|
|
:method: GET
|
|
:path: /
|
|
:scheme: https
|
|
accept: */*
|
|
accept-encoding: gzip, deflate
|
|
user-agent: nghttp2/0.4.0-DEV
|
|
[ 0.068] recv SETTINGS frame <length=10, flags=0x00, stream_id=0>
|
|
(niv=2)
|
|
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
|
|
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
|
|
[ 0.068] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
|
; ACK
|
|
(niv=0)
|
|
[ 0.079] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
|
; ACK
|
|
(niv=0)
|
|
[ 0.080] (stream_id=1, noind=0) :status: 200
|
|
[ 0.080] (stream_id=1, noind=0) accept-ranges: bytes
|
|
[ 0.080] (stream_id=1, noind=0) age: 15
|
|
[ 0.080] (stream_id=1, noind=0) content-length: 40243
|
|
[ 0.080] (stream_id=1, noind=0) content-type: text/html
|
|
[ 0.080] (stream_id=1, noind=0) date: Wed, 14 May 2014 15:14:30 GMT
|
|
[ 0.080] (stream_id=1, noind=0) etag: "535d0eea-9d33"
|
|
[ 0.080] (stream_id=1, noind=0) last-modified: Sun, 27 Apr 2014 14:06:34 GMT
|
|
[ 0.080] (stream_id=1, noind=0) server: nginx/1.4.6 (Ubuntu)
|
|
[ 0.080] (stream_id=1, noind=0) x-varnish: 2114900538 2114900537
|
|
[ 0.080] (stream_id=1, noind=0) via: 1.1 varnish, 1.1 nghttpx
|
|
[ 0.080] (stream_id=1, noind=0) strict-transport-security: max-age=31536000
|
|
[ 0.080] recv HEADERS frame <length=162, flags=0x04, stream_id=1>
|
|
; END_HEADERS
|
|
(padlen=0)
|
|
; First response header
|
|
[ 0.080] recv DATA frame <length=3786, flags=0x00, stream_id=1>
|
|
[ 0.080] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
|
[ 0.081] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
|
[ 0.093] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
|
[ 0.093] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
|
[ 0.094] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
|
[ 0.094] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
|
[ 0.094] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
|
[ 0.096] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
|
[ 0.096] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
|
|
(window_size_increment=36554)
|
|
[ 0.096] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=1>
|
|
(window_size_increment=36554)
|
|
[ 0.108] recv DATA frame <length=3689, flags=0x00, stream_id=1>
|
|
[ 0.108] recv DATA frame <length=0, flags=0x01, stream_id=1>
|
|
; END_STREAM
|
|
[ 0.108] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
|
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
|
|
</pre></div>
|
|
</div>
|
|
<p>The HTTP Upgrade is performed like this:</p>
|
|
<div class="highlight-c"><div class="highlight"><pre>$ src/nghttp -nvu http://nghttp2.org
|
|
[ 0.013] HTTP Upgrade request
|
|
GET / HTTP/1.1
|
|
Host: nghttp2.org
|
|
Connection: Upgrade, HTTP2-Settings
|
|
Upgrade: h2c-13
|
|
HTTP2-Settings: AwAAAGQEAAD__wUAAAAB
|
|
Accept: */*
|
|
User-Agent: nghttp2/0.4.0-DEV
|
|
|
|
|
|
[ 0.024] HTTP Upgrade response
|
|
HTTP/1.1 101 Switching Protocols
|
|
Connection: Upgrade
|
|
Upgrade: h2c-13
|
|
|
|
|
|
[ 0.024] HTTP Upgrade success
|
|
[ 0.024] send SETTINGS frame <length=15, flags=0x00, stream_id=0>
|
|
(niv=3)
|
|
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
|
|
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
|
|
[SETTINGS_COMPRESS_DATA(5):1]
|
|
[ 0.024] recv SETTINGS frame <length=10, flags=0x00, stream_id=0>
|
|
(niv=2)
|
|
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
|
|
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
|
|
[ 0.024] recv ALTSVC frame <length=43, flags=0x00, stream_id=0>
|
|
(max-age=86400, port=443, protocol_id=h2-13, host=nghttp2.org, origin=http://nghttp2.org)
|
|
[ 0.024] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
|
; ACK
|
|
(niv=0)
|
|
[ 0.024] (stream_id=1, noind=0) :status: 200
|
|
[ 0.024] (stream_id=1, noind=0) accept-ranges: bytes
|
|
[ 0.024] (stream_id=1, noind=0) age: 10
|
|
[ 0.024] (stream_id=1, noind=0) content-length: 40243
|
|
[ 0.024] (stream_id=1, noind=0) content-type: text/html
|
|
[ 0.024] (stream_id=1, noind=0) date: Wed, 14 May 2014 15:16:34 GMT
|
|
[ 0.024] (stream_id=1, noind=0) etag: "535d0eea-9d33"
|
|
[ 0.024] (stream_id=1, noind=0) last-modified: Sun, 27 Apr 2014 14:06:34 GMT
|
|
[ 0.024] (stream_id=1, noind=0) server: nginx/1.4.6 (Ubuntu)
|
|
[ 0.024] (stream_id=1, noind=0) x-varnish: 2114900541 2114900540
|
|
[ 0.024] (stream_id=1, noind=0) via: 1.1 varnish, 1.1 nghttpx
|
|
[ 0.024] recv HEADERS frame <length=148, flags=0x04, stream_id=1>
|
|
; END_HEADERS
|
|
(padlen=0)
|
|
; First response header
|
|
[ 0.024] recv DATA frame <length=3786, flags=0x00, stream_id=1>
|
|
[ 0.025] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
|
[ 0.031] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
|
[ 0.031] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
|
[ 0.032] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
|
[ 0.032] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
|
[ 0.033] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
|
[ 0.033] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
|
[ 0.033] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
|
|
(window_size_increment=33164)
|
|
[ 0.033] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=1>
|
|
(window_size_increment=33164)
|
|
[ 0.038] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
|
[ 0.038] recv DATA frame <length=3689, flags=0x00, stream_id=1>
|
|
[ 0.038] recv DATA frame <length=0, flags=0x01, stream_id=1>
|
|
; END_STREAM
|
|
[ 0.038] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
|
; ACK
|
|
(niv=0)
|
|
[ 0.038] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
|
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
|
|
</pre></div>
|
|
</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 a multi-threaded static web server.</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 accepts the HTTP/2 connection via NPN/ALPN or direct
|
|
HTTP/2 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"><div class="highlight"><pre>$ src/nghttpd --no-tls -v 8080
|
|
IPv4: listen on port 8080
|
|
IPv6: listen on port 8080
|
|
[id=1] [ 15.921] send SETTINGS frame <length=10, flags=0x00, stream_id=0>
|
|
(niv=2)
|
|
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
|
|
[SETTINGS_COMPRESS_DATA(5):1]
|
|
[id=1] [ 15.921] recv SETTINGS frame <length=15, flags=0x00, stream_id=0>
|
|
(niv=3)
|
|
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
|
|
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
|
|
[SETTINGS_COMPRESS_DATA(5):1]
|
|
[id=1] [ 15.921] (stream_id=1, noind=0) :authority: localhost:8080
|
|
[id=1] [ 15.921] (stream_id=1, noind=0) :method: GET
|
|
[id=1] [ 15.921] (stream_id=1, noind=0) :path: /
|
|
[id=1] [ 15.921] (stream_id=1, noind=0) :scheme: http
|
|
[id=1] [ 15.921] (stream_id=1, noind=0) accept: */*
|
|
[id=1] [ 15.921] (stream_id=1, noind=0) accept-encoding: gzip, deflate
|
|
[id=1] [ 15.921] (stream_id=1, noind=0) user-agent: nghttp2/0.4.0-DEV
|
|
[id=1] [ 15.921] recv HEADERS frame <length=48, flags=0x05, stream_id=1>
|
|
; END_STREAM | END_HEADERS
|
|
(padlen=0)
|
|
; Open new stream
|
|
[id=1] [ 15.921] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
|
; ACK
|
|
(niv=0)
|
|
[id=1] [ 15.921] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
|
; ACK
|
|
(niv=0)
|
|
[id=1] [ 15.921] send HEADERS frame <length=82, flags=0x04, stream_id=1>
|
|
; END_HEADERS
|
|
(padlen=0)
|
|
; First response header
|
|
:status: 200
|
|
cache-control: max-age=3600
|
|
content-length: 612
|
|
date: Wed, 14 May 2014 15:19:03 GMT
|
|
last-modified: Sat, 08 Mar 2014 16:04:06 GMT
|
|
server: nghttpd nghttp2/0.4.0-DEV
|
|
[id=1] [ 15.922] send DATA frame <length=381, flags=0x20, stream_id=1>
|
|
; COMPRESSED
|
|
[id=1] [ 15.922] send DATA frame <length=0, flags=0x01, stream_id=1>
|
|
; END_STREAM
|
|
[id=1] [ 15.922] stream_id=1 closed
|
|
[id=1] [ 15.922] recv GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
|
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
|
|
[id=1] [ 15.922] closed
|
|
</pre></div>
|
|
</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><tt class="docutils literal"><span class="pre">nghttpx</span></tt> is a multi-threaded reverse proxy for <tt class="docutils literal"><span class="pre">h2-13</span></tt>, SPDY and
|
|
HTTP/1.1 and powers nghttp2.org site. It has several operation modes:</p>
|
|
<table border="1" class="docutils">
|
|
<colgroup>
|
|
<col width="25%" />
|
|
<col width="38%" />
|
|
<col width="19%" />
|
|
<col width="18%" />
|
|
</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, 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, 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, SPDY, HTTP/1.1 (TLS)</td>
|
|
<td>HTTP/2 (TLS)</td>
|
|
<td> </td>
|
|
</tr>
|
|
<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">--client</span></tt></td>
|
|
<td>HTTP/2, HTTP/1.1</td>
|
|
<td>HTTP/2 (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, HTTP/1.1</td>
|
|
<td>HTTP/2 (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 for <tt class="docutils literal"><span class="pre">h2-13</span></tt>, 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 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><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><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="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">--></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="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">--></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> <span class="n">ATS</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-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">"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"><div class="highlight"><pre>$ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn
|
|
</pre></div>
|
|
</div>
|
|
<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"><--</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">--></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="mi">2</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="mi">2</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 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="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">--></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="mi">2</span><span class="p">)</span> <span class="o">--></span> <span class="n">HTTP</span><span class="o">/</span><span class="mi">2</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> needs to be configured to use nghttpx as forward
|
|
proxy. The frontend HTTP/1.1 connection can be upgraded to HTTP/2
|
|
through HTTP Upgrade. With the above configuration, one can use
|
|
HTTP/1.1 client to access and test their HTTP/2 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 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="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">--></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="mi">2</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
|
|
through HTTP Upgrade.</p>
|
|
<p>For the operation modes which talk to the backend in HTTP/2 over
|
|
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>
|
|
<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="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">--></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="mi">2</span><span class="p">)</span> <span class="o">--</span>
|
|
|
|
<span class="o">--===================---></span> <span class="n">HTTP</span><span class="o">/</span><span class="mi">2</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="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
|
|
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>
|
|
<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
|
|
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>
|
|
<div class="admonition warning">
|
|
<p class="first admonition-title">Warning</p>
|
|
<p class="last"><strong>Don’t use this tool against publicly available servers.</strong> That is
|
|
considered a DOS attack. Please only use against your private
|
|
servers.</p>
|
|
</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 a
|
|
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 (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>
|
|
<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 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
|
|
appear. Each item in the sequence is a JSON object and it must
|
|
include <tt class="docutils literal"><span class="pre">headers</span></tt> key. Its value is an array of a JSON object,
|
|
which includes exactly one name/value pair.</p>
|
|
<p>Example:</p>
|
|
<div class="highlight-json"><div class="highlight"><pre><span class="p">{</span>
|
|
<span class="nt">"cases"</span><span class="p">:</span>
|
|
<span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"headers"</span><span class="p">:</span> <span class="p">[</span>
|
|
<span class="p">{</span> <span class="nt">":method"</span><span class="p">:</span> <span class="s2">"GET"</span> <span class="p">},</span>
|
|
<span class="p">{</span> <span class="nt">":path"</span><span class="p">:</span> <span class="s2">"/"</span> <span class="p">}</span>
|
|
<span class="p">]</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"headers"</span><span class="p">:</span> <span class="p">[</span>
|
|
<span class="p">{</span> <span class="nt">":method"</span><span class="p">:</span> <span class="s2">"POST"</span> <span class="p">},</span>
|
|
<span class="p">{</span> <span class="nt">":path"</span><span class="p">:</span> <span class="s2">"/"</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 should include <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 adjusted before deflating header set.</dd>
|
|
</dl>
|
|
<p>Examples:</p>
|
|
<div class="highlight-json"><div class="highlight"><pre><span class="p">{</span>
|
|
<span class="nt">"cases"</span><span class="p">:</span>
|
|
<span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"seq"</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
|
|
<span class="nt">"input_length"</span><span class="p">:</span> <span class="mi">66</span><span class="p">,</span>
|
|
<span class="nt">"output_length"</span><span class="p">:</span> <span class="mi">20</span><span class="p">,</span>
|
|
<span class="nt">"percentage_of_original_size"</span><span class="p">:</span> <span class="mf">30.303030303030305</span><span class="p">,</span>
|
|
<span class="nt">"wire"</span><span class="p">:</span> <span class="s2">"01881f3468e5891afcbf83868a3d856659c62e3f"</span><span class="p">,</span>
|
|
<span class="nt">"headers"</span><span class="p">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":authority"</span><span class="p">:</span> <span class="s2">"example.org"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":method"</span><span class="p">:</span> <span class="s2">"GET"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":path"</span><span class="p">:</span> <span class="s2">"/"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":scheme"</span><span class="p">:</span> <span class="s2">"https"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"user-agent"</span><span class="p">:</span> <span class="s2">"nghttp2"</span>
|
|
<span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="nt">"header_table_size"</span><span class="p">:</span> <span class="mi">4096</span>
|
|
<span class="p">}</span>
|
|
<span class="p">,</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"seq"</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
|
|
<span class="nt">"input_length"</span><span class="p">:</span> <span class="mi">74</span><span class="p">,</span>
|
|
<span class="nt">"output_length"</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span>
|
|
<span class="nt">"percentage_of_original_size"</span><span class="p">:</span> <span class="mf">13.513513513513514</span><span class="p">,</span>
|
|
<span class="nt">"wire"</span><span class="p">:</span> <span class="s2">"88448504252dd5918485"</span><span class="p">,</span>
|
|
<span class="nt">"headers"</span><span class="p">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":authority"</span><span class="p">:</span> <span class="s2">"example.org"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":method"</span><span class="p">:</span> <span class="s2">"POST"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":path"</span><span class="p">:</span> <span class="s2">"/account"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":scheme"</span><span class="p">:</span> <span class="s2">"https"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"user-agent"</span><span class="p">:</span> <span class="s2">"nghttp2"</span>
|
|
<span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="nt">"header_table_size"</span><span class="p">:</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 includes the state of dynamic header table after the
|
|
corresponding header set was processed. The value includes at least
|
|
the 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.</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-json"><div class="highlight"><pre><span class="p">{</span>
|
|
<span class="nt">"cases"</span><span class="p">:</span>
|
|
<span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"seq"</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
|
|
<span class="nt">"input_length"</span><span class="p">:</span> <span class="mi">66</span><span class="p">,</span>
|
|
<span class="nt">"output_length"</span><span class="p">:</span> <span class="mi">20</span><span class="p">,</span>
|
|
<span class="nt">"percentage_of_original_size"</span><span class="p">:</span> <span class="mf">30.303030303030305</span><span class="p">,</span>
|
|
<span class="nt">"wire"</span><span class="p">:</span> <span class="s2">"01881f3468e5891afcbf83868a3d856659c62e3f"</span><span class="p">,</span>
|
|
<span class="nt">"headers"</span><span class="p">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":authority"</span><span class="p">:</span> <span class="s2">"example.org"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":method"</span><span class="p">:</span> <span class="s2">"GET"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":path"</span><span class="p">:</span> <span class="s2">"/"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":scheme"</span><span class="p">:</span> <span class="s2">"https"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"user-agent"</span><span class="p">:</span> <span class="s2">"nghttp2"</span>
|
|
<span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="nt">"header_table_size"</span><span class="p">:</span> <span class="mi">4096</span><span class="p">,</span>
|
|
<span class="nt">"header_table"</span><span class="p">:</span> <span class="p">{</span>
|
|
<span class="nt">"entries"</span><span class="p">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"index"</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
|
|
<span class="nt">"name"</span><span class="p">:</span> <span class="s2">"user-agent"</span><span class="p">,</span>
|
|
<span class="nt">"value"</span><span class="p">:</span> <span class="s2">"nghttp2"</span><span class="p">,</span>
|
|
<span class="nt">"referenced"</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
|
|
<span class="nt">"size"</span><span class="p">:</span> <span class="mi">49</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"index"</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
|
|
<span class="nt">"name"</span><span class="p">:</span> <span class="s2">":scheme"</span><span class="p">,</span>
|
|
<span class="nt">"value"</span><span class="p">:</span> <span class="s2">"https"</span><span class="p">,</span>
|
|
<span class="nt">"referenced"</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
|
|
<span class="nt">"size"</span><span class="p">:</span> <span class="mi">44</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"index"</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
|
|
<span class="nt">"name"</span><span class="p">:</span> <span class="s2">":path"</span><span class="p">,</span>
|
|
<span class="nt">"value"</span><span class="p">:</span> <span class="s2">"/"</span><span class="p">,</span>
|
|
<span class="nt">"referenced"</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
|
|
<span class="nt">"size"</span><span class="p">:</span> <span class="mi">38</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"index"</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span>
|
|
<span class="nt">"name"</span><span class="p">:</span> <span class="s2">":method"</span><span class="p">,</span>
|
|
<span class="nt">"value"</span><span class="p">:</span> <span class="s2">"GET"</span><span class="p">,</span>
|
|
<span class="nt">"referenced"</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
|
|
<span class="nt">"size"</span><span class="p">:</span> <span class="mi">42</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"index"</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
|
|
<span class="nt">"name"</span><span class="p">:</span> <span class="s2">":authority"</span><span class="p">,</span>
|
|
<span class="nt">"value"</span><span class="p">:</span> <span class="s2">"example.org"</span><span class="p">,</span>
|
|
<span class="nt">"referenced"</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
|
|
<span class="nt">"size"</span><span class="p">:</span> <span class="mi">53</span>
|
|
<span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="nt">"size"</span><span class="p">:</span> <span class="mi">226</span><span class="p">,</span>
|
|
<span class="nt">"max_size"</span><span class="p">:</span> <span class="mi">4096</span><span class="p">,</span>
|
|
<span class="nt">"deflate_size"</span><span class="p">:</span> <span class="mi">226</span><span class="p">,</span>
|
|
<span class="nt">"max_deflate_size"</span><span class="p">:</span> <span class="mi">4096</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">,</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"seq"</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
|
|
<span class="nt">"input_length"</span><span class="p">:</span> <span class="mi">74</span><span class="p">,</span>
|
|
<span class="nt">"output_length"</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span>
|
|
<span class="nt">"percentage_of_original_size"</span><span class="p">:</span> <span class="mf">13.513513513513514</span><span class="p">,</span>
|
|
<span class="nt">"wire"</span><span class="p">:</span> <span class="s2">"88448504252dd5918485"</span><span class="p">,</span>
|
|
<span class="nt">"headers"</span><span class="p">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":authority"</span><span class="p">:</span> <span class="s2">"example.org"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":method"</span><span class="p">:</span> <span class="s2">"POST"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":path"</span><span class="p">:</span> <span class="s2">"/account"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":scheme"</span><span class="p">:</span> <span class="s2">"https"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"user-agent"</span><span class="p">:</span> <span class="s2">"nghttp2"</span>
|
|
<span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="nt">"header_table_size"</span><span class="p">:</span> <span class="mi">4096</span><span class="p">,</span>
|
|
<span class="nt">"header_table"</span><span class="p">:</span> <span class="p">{</span>
|
|
<span class="nt">"entries"</span><span class="p">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"index"</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
|
|
<span class="nt">"name"</span><span class="p">:</span> <span class="s2">":method"</span><span class="p">,</span>
|
|
<span class="nt">"value"</span><span class="p">:</span> <span class="s2">"POST"</span><span class="p">,</span>
|
|
<span class="nt">"referenced"</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
|
|
<span class="nt">"size"</span><span class="p">:</span> <span class="mi">43</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"index"</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
|
|
<span class="nt">"name"</span><span class="p">:</span> <span class="s2">"user-agent"</span><span class="p">,</span>
|
|
<span class="nt">"value"</span><span class="p">:</span> <span class="s2">"nghttp2"</span><span class="p">,</span>
|
|
<span class="nt">"referenced"</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
|
|
<span class="nt">"size"</span><span class="p">:</span> <span class="mi">49</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"index"</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
|
|
<span class="nt">"name"</span><span class="p">:</span> <span class="s2">":scheme"</span><span class="p">,</span>
|
|
<span class="nt">"value"</span><span class="p">:</span> <span class="s2">"https"</span><span class="p">,</span>
|
|
<span class="nt">"referenced"</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
|
|
<span class="nt">"size"</span><span class="p">:</span> <span class="mi">44</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"index"</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span>
|
|
<span class="nt">"name"</span><span class="p">:</span> <span class="s2">":path"</span><span class="p">,</span>
|
|
<span class="nt">"value"</span><span class="p">:</span> <span class="s2">"/"</span><span class="p">,</span>
|
|
<span class="nt">"referenced"</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
|
|
<span class="nt">"size"</span><span class="p">:</span> <span class="mi">38</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"index"</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
|
|
<span class="nt">"name"</span><span class="p">:</span> <span class="s2">":method"</span><span class="p">,</span>
|
|
<span class="nt">"value"</span><span class="p">:</span> <span class="s2">"GET"</span><span class="p">,</span>
|
|
<span class="nt">"referenced"</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
|
|
<span class="nt">"size"</span><span class="p">:</span> <span class="mi">42</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"index"</span><span class="p">:</span> <span class="mi">6</span><span class="p">,</span>
|
|
<span class="nt">"name"</span><span class="p">:</span> <span class="s2">":authority"</span><span class="p">,</span>
|
|
<span class="nt">"value"</span><span class="p">:</span> <span class="s2">"example.org"</span><span class="p">,</span>
|
|
<span class="nt">"referenced"</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
|
|
<span class="nt">"size"</span><span class="p">:</span> <span class="mi">53</span>
|
|
<span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="nt">"size"</span><span class="p">:</span> <span class="mi">269</span><span class="p">,</span>
|
|
<span class="nt">"max_size"</span><span class="p">:</span> <span class="mi">4096</span><span class="p">,</span>
|
|
<span class="nt">"deflate_size"</span><span class="p">:</span> <span class="mi">269</span><span class="p">,</span>
|
|
<span class="nt">"max_deflate_size"</span><span class="p">:</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 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
|
|
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 compressed header block in hex string.</p>
|
|
<p>Example:</p>
|
|
<div class="highlight-json"><div class="highlight"><pre><span class="p">{</span>
|
|
<span class="nt">"cases"</span><span class="p">:</span>
|
|
<span class="p">[</span>
|
|
<span class="p">{</span> <span class="nt">"wire"</span><span class="p">:</span> <span class="s2">"8285"</span> <span class="p">},</span>
|
|
<span class="p">{</span> <span class="nt">"wire"</span><span class="p">:</span> <span class="s2">"8583"</span> <span class="p">}</span>
|
|
<span class="p">]</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>The output is JSON object. It should include <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 includes 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 adjusted before inflating compressed header
|
|
block.</dd>
|
|
</dl>
|
|
<p>Example:</p>
|
|
<div class="highlight-json"><div class="highlight"><pre><span class="p">{</span>
|
|
<span class="nt">"cases"</span><span class="p">:</span>
|
|
<span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"seq"</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
|
|
<span class="nt">"wire"</span><span class="p">:</span> <span class="s2">"01881f3468e5891afcbf83868a3d856659c62e3f"</span><span class="p">,</span>
|
|
<span class="nt">"headers"</span><span class="p">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":authority"</span><span class="p">:</span> <span class="s2">"example.org"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":method"</span><span class="p">:</span> <span class="s2">"GET"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":path"</span><span class="p">:</span> <span class="s2">"/"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":scheme"</span><span class="p">:</span> <span class="s2">"https"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"user-agent"</span><span class="p">:</span> <span class="s2">"nghttp2"</span>
|
|
<span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="nt">"header_table_size"</span><span class="p">:</span> <span class="mi">4096</span>
|
|
<span class="p">}</span>
|
|
<span class="p">,</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"seq"</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
|
|
<span class="nt">"wire"</span><span class="p">:</span> <span class="s2">"88448504252dd5918485"</span><span class="p">,</span>
|
|
<span class="nt">"headers"</span><span class="p">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":method"</span><span class="p">:</span> <span class="s2">"POST"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":path"</span><span class="p">:</span> <span class="s2">"/account"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">"user-agent"</span><span class="p">:</span> <span class="s2">"nghttp2"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":scheme"</span><span class="p">:</span> <span class="s2">"https"</span>
|
|
<span class="p">},</span>
|
|
<span class="p">{</span>
|
|
<span class="nt">":authority"</span><span class="p">:</span> <span class="s2">"example.org"</span>
|
|
<span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="nt">"header_table_size"</span><span class="p">:</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 includes the state of dynamic 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 provide HPACK compressor and decompressor classes
|
|
and HTTP/2 server.</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.4</span></tt>).</p>
|
|
<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">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">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>
|
|
<p>The <tt class="docutils literal"><span class="pre">nghttp2.HTTP2Server</span></tt> class builds on top of the asyncio event
|
|
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
|
|
when HEADERS frame, which includes request header fields, has arrived.</p>
|
|
<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>
|
|
<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
|
|
<tt class="docutils literal"><span class="pre">on_request_done()</span></tt>.</p>
|
|
<p>The application can push resource using <tt class="docutils literal"><span class="pre">push()</span></tt> method. It must be
|
|
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’s address.</dd>
|
|
<dt>stream_id</dt>
|
|
<dd>Stream ID of this stream.</dd>
|
|
<dt>scheme</dt>
|
|
<dd>Scheme of the request URI. This is a value of :scheme header
|
|
field.</dd>
|
|
<dt>method</dt>
|
|
<dd>Method of this stream. This is a value of :method header field.</dd>
|
|
<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">'/css/bootstrap.css'</span><span class="p">,</span>
|
|
<span class="n">request_headers</span> <span class="o">=</span> <span class="p">[(</span><span class="s">'content-length'</span><span class="p">,</span> <span class="s">'3'</span><span class="p">)],</span>
|
|
<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">'foo'</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">'/js/bootstrap.js'</span><span class="p">,</span>
|
|
<span class="n">method</span><span class="o">=</span><span class="s">'GET'</span><span class="p">,</span>
|
|
<span class="n">request_headers</span> <span class="o">=</span> <span class="p">[(</span><span class="s">'content-length'</span><span class="p">,</span> <span class="s">'10'</span><span class="p">)],</span>
|
|
<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">'foobarbuzz'</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>
|
|
<span class="n">headers</span> <span class="o">=</span> <span class="p">[(</span><span class="s">'content-type'</span><span class="p">,</span> <span class="s">'text/plain'</span><span class="p">)],</span>
|
|
<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">'nghttp2-python FTW'</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">'server.crt'</span><span class="p">,</span> <span class="s">'server.key'</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">'127.0.0.1'</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>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
<footer>
|
|
|
|
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
|
|
|
|
<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>
|
|
|
|
|
|
<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/>
|
|
|
|
<div role="contentinfo">
|
|
<p>
|
|
© Copyright 2012, 2014, Tatsuhiro Tsujikawa.
|
|
</p>
|
|
</div>
|
|
|
|
<a href="https://github.com/snide/sphinx_rtd_theme">Sphinx theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>
|
|
</footer>
|
|
</div>
|
|
</div>
|
|
|
|
</section>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
|
var DOCUMENTATION_OPTIONS = {
|
|
URL_ROOT:'./',
|
|
VERSION:'0.4.2-DEV',
|
|
COLLAPSE_INDEX:false,
|
|
FILE_SUFFIX:'.html',
|
|
HAS_SOURCE: false
|
|
};
|
|
</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>
|
|
|
|
|
|
|
|
|
|
|
|
<script type="text/javascript" src="_static/js/theme.js"></script>
|
|
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
|
jQuery(function () {
|
|
SphinxRtdTheme.StickyNav.enable();
|
|
});
|
|
</script>
|
|
|
|
|
|
</body>
|
|
</html> |