nghttp2/README.rst

1286 lines
40 KiB
ReStructuredText
Raw Normal View History

2014-03-30 12:09:21 +02:00
nghttp2 - HTTP/2 C Library
2014-06-14 15:42:18 +02:00
==========================
2012-01-26 17:38:35 +01:00
2015-03-16 07:42:19 +01:00
This is an implementation of the Hypertext Transfer Protocol version 2
2014-06-14 15:42:18 +02:00
in C.
2015-03-16 07:42:19 +01:00
The framing layer of HTTP/2 is implemented as a reusable C
library. On top of that, we have implemented an HTTP/2 client, server
and proxy. We have also developed load test and benchmarking tools for
2014-06-14 15:42:18 +02:00
HTTP/2 and SPDY.
2015-03-16 07:42:19 +01:00
An HPACK encoder and decoder are available as a public API.
2014-06-14 15:42:18 +02:00
2015-03-16 07:42:19 +01:00
An experimental high level C++ library is also available.
2014-09-23 17:25:37 +02:00
2015-03-16 07:42:19 +01:00
We have Python bindings of this libary, but we do not have full
code coverage yet.
2012-09-12 15:37:05 +02:00
2012-04-25 14:25:51 +02:00
Development Status
------------------
2012-03-26 16:46:02 +02:00
2014-07-31 16:16:52 +02:00
We started to implement h2-14
2015-03-16 07:42:19 +01:00
(http://tools.ietf.org/html/draft-ietf-httpbis-http2-14), and header
2014-07-31 16:16:52 +02:00
compression
2014-12-02 15:18:51 +01:00
(http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09).
2013-08-22 20:45:55 +02:00
2015-03-16 07:42:19 +01:00
The nghttp2 code base was forked from the spdylay project.
2013-07-12 17:19:03 +02:00
2014-06-14 15:42:18 +02:00
=========================== =======
HTTP/2 Features Support
=========================== =======
Core frames handling Yes
Dependency Tree Yes
Large header (CONTINUATION) Yes
=========================== =======
2013-08-10 12:06:33 +02:00
Public Test Server
------------------
2015-03-16 07:42:19 +01:00
The following endpoints are available to try out our nghttp2
2014-02-16 07:50:36 +01:00
implementation.
2013-08-10 12:06:33 +02:00
2014-08-02 17:52:40 +02:00
* https://nghttp2.org/ (TLS + ALPN/NPN)
2013-08-30 17:50:09 +02:00
2015-02-26 17:02:48 +01:00
This endpoint supports ``h2``, ``h2-16``, ``h2-14``, ``spdy/3.1``
and ``http/1.1`` via ALPN/NPN and requires TLSv1.2 for HTTP/2
connection.
2014-06-18 05:13:01 +02:00
2014-04-18 15:55:21 +02:00
* http://nghttp2.org/ (Upgrade / Direct)
2014-02-16 07:50:36 +01:00
2014-12-02 15:18:51 +01:00
``h2c-14`` and ``http/1.1``.
2013-08-10 12:06:33 +02:00
2013-07-27 14:56:46 +02:00
Requirements
------------
2013-07-16 17:08:05 +02:00
2014-05-06 16:18:12 +02:00
The following package is required to build the libnghttp2 library:
2013-07-19 19:05:07 +02:00
2013-07-27 14:56:46 +02:00
* pkg-config >= 0.20
2013-07-19 19:05:07 +02:00
2014-05-06 16:18:12 +02:00
To build and run the unit test programs, the following package is
2013-07-27 14:56:46 +02:00
required:
* cunit >= 2.1
To build the documentation, you need to install:
* sphinx (http://sphinx-doc.org/)
2013-07-27 14:56:46 +02:00
To build and run the application programs (``nghttp``, ``nghttpd`` and
2015-03-16 07:42:19 +01:00
``nghttpx``) in the ``src`` directory, the following packages are
2013-07-27 14:56:46 +02:00
required:
* OpenSSL >= 1.0.1
2015-01-02 13:54:52 +01:00
* libev >= 4.15
2014-05-06 16:18:12 +02:00
* zlib >= 1.2.3
2013-07-27 14:56:46 +02:00
ALPN support requires OpenSSL >= 1.0.2 (released 22 January 2015).
2014-01-02 05:32:43 +01:00
2015-03-16 07:42:19 +01:00
To enable the SPDY protocol in the application program ``nghttpx`` and
2014-05-06 16:18:12 +02:00
``h2load``, the following package is required:
2013-07-27 14:56:46 +02:00
2014-08-21 15:50:19 +02:00
* spdylay >= 1.3.0
2013-07-27 14:56:46 +02:00
To enable ``-a`` option (getting linked assets from the downloaded
2014-05-06 16:18:12 +02:00
resource) in ``nghttp``, the following package is required:
2013-07-27 14:56:46 +02:00
* libxml2 >= 2.7.7
2014-01-10 13:53:48 +01:00
The HPACK tools require the following package:
2013-10-27 08:23:24 +01:00
2014-01-08 17:48:34 +01:00
* jansson >= 2.5
2013-10-27 08:23:24 +01:00
2015-03-16 07:42:19 +01:00
To build sources under the examples directory, libevent is required:
2015-01-02 13:54:52 +01:00
* libevent-openssl >= 2.0.8
2014-03-05 13:46:26 +01:00
To mitigate heap fragmentation in long running server programs
(``nghttpd`` and ``nghttpx``), jemalloc is recommended:
* jemalloc
2014-09-23 17:25:37 +02:00
libnghttp2_asio C++ library requires the following packages:
2014-09-24 19:08:09 +02:00
* libboost-dev >= 1.54.0
* libboost-thread-dev >= 1.54.0
2014-09-23 17:25:37 +02:00
The Python bindings require the following packages:
* cython >= 0.19
* python >= 2.7
2015-03-20 16:37:06 +01:00
If you are using Ubuntu 14.04 LTS (trusty), run the following to install the needed packages::
2015-01-27 16:58:08 +01:00
2015-03-20 16:37:06 +01:00
sudo apt-get install make binutils autoconf automake autotools-dev libtool pkg-config \
zlib1g-dev libcunit1-dev libssl-dev libxml2-dev libev-dev libevent-dev libjansson-dev \
libjemalloc-dev cython python3.4-dev
2013-07-27 14:56:46 +02:00
spdylay is not packaged in Ubuntu, so you need to build it yourself:
2013-11-21 14:03:18 +01:00
http://tatsuhiro-t.github.io/spdylay/
2013-07-27 14:56:46 +02:00
2015-03-16 07:42:19 +01:00
Building from git
-----------------
2013-07-27 15:46:22 +02:00
Building from git is easy, but please be sure that at least autoconf 2.68 is
used::
$ autoreconf -i
$ automake
$ autoconf
$ ./configure
$ make
2015-03-16 07:42:19 +01:00
To compile the source code, gcc >= 4.8.3 or clang >= 3.4 is required.
2014-07-18 14:15:28 +02:00
2014-05-21 16:01:21 +02:00
.. note::
2015-03-16 07:42:19 +01:00
Mac OS X users may need the ``--disable-threads`` configure option to
disable multi-threading in nghttpd, nghttpx and h2load to prevent
them from crashing. A patch is welcome to make multi threading work
2014-05-21 16:01:21 +02:00
on Mac OS X platform.
2014-05-17 15:20:48 +02:00
Notes for building on Windows (Mingw/Cygwin)
2015-03-31 14:32:25 +02:00
--------------------------------------------
2015-03-31 14:32:25 +02:00
Under Mingw environment, you can only compile the library, it's
``libnghttp2-X.dll`` and ``libnghttp2.a``.
2015-03-31 14:32:25 +02:00
If you want to compile the applications(``h2load``, ``nghttp``,
``nghttpx``, ``nghttpd``), you need to use the Cygwin environment.
2015-03-31 14:32:25 +02:00
Under Cygwin environment, to compile the applications you need to
compile and install the libev first.
2015-03-31 14:32:25 +02:00
Secondly, you need to undefine the macro ``__STRICT_ANSI__``, if you
not, the functions ``fdopen``, ``fileno`` and ``strptime`` will not
available.
the sample command like this::
2015-03-31 14:32:25 +02:00
$ export CFLAGS="-U__STRICT_ANSI__ -I$libev_PREFIX/include -L$libev_PREFIX/lib"
$ export CXXFLAGS=$CFLAGS
$ ./configure
$ make
2015-03-31 14:32:25 +02:00
If you want to compile the applications under ``examples/``, you need
to remove or rename the ``event.h`` from libev's installation, because
it conflicts with libevent's installation.
2015-03-16 07:42:19 +01:00
Building the documentation
--------------------------
2013-07-27 14:56:46 +02:00
.. note::
Documentation is still incomplete.
2015-03-16 07:42:19 +01:00
To build the documentation, run::
2013-07-27 14:56:46 +02:00
$ make html
The documents will be generated under ``doc/manual/html/``.
The generated documents will not be installed with ``make install``.
2013-07-28 16:00:12 +02:00
The online documentation is available at
2014-05-14 17:11:40 +02:00
https://nghttp2.org/documentation/
2013-07-28 16:00:12 +02:00
Unit tests
----------
Unit tests are done by simply running ``make check``.
Integration tests
-----------------
2015-03-16 07:42:19 +01:00
We have the integration tests for the nghttpx proxy server. The tests are
written in the `Go programming language <http://golang.org/>`_ and uses
2015-01-21 05:54:22 +01:00
its testing framework. We depend on the following libraries:
* https://github.com/bradfitz/http2
* https://github.com/tatsuhiro-t/go-nghttp2
2015-01-20 17:06:28 +01:00
* https://golang.org/x/net/spdy
2015-01-23 17:05:20 +01:00
To download the above packages, after settings ``GOPATH``, run the
following command under ``integration-tests`` directory::
$ make itprep
To run the tests, run the following command under
``integration-tests`` directory::
$ make it
2015-03-16 07:42:19 +01:00
Inside the tests, we use port 3009 to run the test subject server.
2013-07-27 14:56:46 +02:00
Client, Server and Proxy programs
---------------------------------
2015-03-16 07:42:19 +01:00
The ``src`` directory contains the HTTP/2 client, server and proxy programs.
2013-07-27 14:56:46 +02:00
nghttp - client
+++++++++++++++
2014-04-08 16:12:02 +02:00
``nghttp`` is a HTTP/2 client. It can connect to the HTTP/2 server
2014-01-01 17:00:11 +01:00
with prior knowledge, HTTP Upgrade and NPN/ALPN TLS extension.
2013-07-27 14:56:46 +02:00
2014-04-08 16:12:02 +02:00
It has verbose output mode for framing information. Here is sample
2013-07-27 14:56:46 +02:00
output from ``nghttp`` client::
2015-02-01 10:08:21 +01:00
$ nghttp -nv https://nghttp2.org
[ 0.033][NPN] server offers:
2014-07-31 16:16:52 +02:00
* h2-14
2014-02-15 09:19:49 +01:00
* spdy/3.1
2014-01-11 09:06:26 +01:00
* http/1.1
2014-07-31 16:16:52 +02:00
The negotiated protocol: h2-14
[ 0.068] send SETTINGS frame <length=15, flags=0x00, stream_id=0>
(niv=3)
2014-02-15 09:19:49 +01:00
[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>
2014-01-11 09:06:26 +01:00
; END_STREAM | END_HEADERS
2014-02-15 09:19:49 +01:00
(padlen=0)
2014-01-11 09:06:26 +01:00
; Open new stream
:authority: nghttp2.org
2014-01-11 09:06:26 +01:00
:method: GET
:path: /
:scheme: https
accept: */*
accept-encoding: gzip, deflate
2014-02-15 09:19:49 +01:00
user-agent: nghttp2/0.4.0-DEV
[ 0.068] recv SETTINGS frame <length=10, flags=0x00, stream_id=0>
(niv=2)
2014-02-15 09:19:49 +01:00
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
[ 0.068] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
2014-01-11 09:06:26 +01:00
; ACK
(niv=0)
[ 0.079] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
2014-01-11 09:06:26 +01:00
; 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>
2014-01-11 09:06:26 +01:00
; END_HEADERS
2014-02-15 09:19:49 +01:00
(padlen=0)
2014-01-11 09:06:26 +01:00
; 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>
2014-01-11 09:06:26 +01:00
; END_STREAM
[ 0.108] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
2014-01-11 09:06:26 +01:00
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
2013-07-27 14:56:46 +02:00
2013-08-03 12:44:13 +02:00
The HTTP Upgrade is performed like this::
2015-02-01 10:08:21 +01:00
$ nghttp -nvu http://nghttp2.org
[ 0.013] HTTP Upgrade request
2013-08-03 12:44:13 +02:00
GET / HTTP/1.1
Host: nghttp2.org
2013-08-03 12:44:13 +02:00
Connection: Upgrade, HTTP2-Settings
2014-08-02 18:08:42 +02:00
Upgrade: h2c-14
HTTP2-Settings: AwAAAGQEAAD__wUAAAAB
2013-08-03 12:44:13 +02:00
Accept: */*
2014-02-15 09:19:49 +01:00
User-Agent: nghttp2/0.4.0-DEV
2013-08-03 12:44:13 +02:00
[ 0.024] HTTP Upgrade response
2013-08-03 12:44:13 +02:00
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
2014-08-02 18:08:42 +02:00
Upgrade: h2c-14
2013-08-03 12:44:13 +02:00
[ 0.024] HTTP Upgrade success
[ 0.024] send SETTINGS frame <length=15, flags=0x00, stream_id=0>
(niv=3)
2014-02-15 09:19:49 +01:00
[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)
2014-02-15 09:19:49 +01:00
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
[ 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>
2014-01-11 09:06:26 +01:00
; END_HEADERS
2014-02-15 09:19:49 +01:00
(padlen=0)
2014-01-11 09:06:26 +01:00
; 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>
2014-01-11 09:06:26 +01:00
; END_STREAM
[ 0.038] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
2014-01-11 09:06:26 +01:00
; ACK
(niv=0)
[ 0.038] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
2014-01-11 09:06:26 +01:00
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
2013-08-03 12:44:13 +02:00
2015-03-16 07:42:19 +01:00
Using the ``-s`` option, ``nghttp`` prints out some timing information for
2015-02-01 10:08:21 +01:00
requests, sorted by completion time::
$ nghttp -nas https://nghttp2.org/
***** Statistics *****
Request timing:
complete: relative time from protocol handshake to stream close
request: relative time from protocol handshake to request
2015-02-15 05:00:19 +01:00
transmission. If '*' is shown, this was pushed by server.
2015-02-01 10:08:21 +01:00
process: time for request and response
2015-02-15 05:00:19 +01:00
code: HTTP status code
size: number of bytes received as response body without
inflation.
URI: request URI
2015-02-01 10:08:21 +01:00
sorted by 'complete'
2015-02-15 08:48:37 +01:00
complete request process code size request path
2015-02-15 05:00:19 +01:00
+11.07ms +120us 10.95ms 200 9K /
+16.77ms * +8.80ms 7.98ms 200 8K /stylesheets/screen.css
+27.00ms +11.16ms 15.84ms 200 3K /javascripts/octopress.js
+27.40ms +11.16ms 16.24ms 200 3K /javascripts/modernizr-2.0.js
+76.14ms +11.17ms 64.97ms 200 171K /images/posts/with-pri-blog.png
+88.52ms +11.17ms 77.36ms 200 174K /images/posts/without-pri-blog.png
2015-02-01 10:08:21 +01:00
2015-03-16 07:42:19 +01:00
Using the ``-r`` option, ``nghttp`` writes more detailed timing data to
the given file in HAR format.
2015-02-01 10:08:21 +01:00
2013-07-27 14:56:46 +02:00
nghttpd - server
++++++++++++++++
2014-03-04 15:16:46 +01:00
``nghttpd`` is a multi-threaded static web server.
2013-07-27 14:56:46 +02:00
2014-04-08 16:12:02 +02:00
By default, it uses SSL/TLS connection. Use ``--no-tls`` option to
2013-07-27 15:40:44 +02:00
disable it.
2015-03-16 07:42:19 +01:00
``nghttpd`` only accepts HTTP/2 connections via NPN/ALPN or direct
HTTP/2 connections. No HTTP Upgrade is supported.
2013-08-03 12:44:13 +02:00
2015-03-16 07:42:19 +01:00
The ``-p`` option allows users to configure server push.
2013-12-08 16:06:53 +01:00
2015-03-16 07:42:19 +01:00
Just like ``nghttp``, it has a verbose output mode for framing
information. Here is sample output from ``nghttpd``::
2013-07-27 14:56:46 +02:00
2015-02-01 10:08:21 +01:00
$ nghttpd --no-tls -v 8080
2013-08-22 20:45:55 +02:00
IPv4: listen on port 8080
IPv6: listen on port 8080
[id=1] [ 15.921] send SETTINGS frame <length=10, flags=0x00, stream_id=0>
2014-02-15 09:19:49 +01:00
(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)
2014-02-15 09:19:49 +01:00
[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>
2014-01-11 09:06:26 +01:00
; END_STREAM | END_HEADERS
2014-02-15 09:19:49 +01:00
(padlen=0)
2014-01-11 09:06:26 +01:00
; Open new stream
[id=1] [ 15.921] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
2014-01-11 09:06:26 +01:00
; 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>
2014-01-11 09:06:26 +01:00
; END_HEADERS
2014-02-15 09:19:49 +01:00
(padlen=0)
2014-01-11 09:06:26 +01:00
; 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
2014-02-15 09:19:49 +01:00
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>
2014-01-11 09:06:26 +01:00
; END_STREAM
[id=1] [ 15.922] stream_id=1 closed
[id=1] [ 15.922] recv GOAWAY frame <length=8, flags=0x00, stream_id=0>
2014-01-11 09:06:26 +01:00
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
[id=1] [ 15.922] closed
2013-07-27 14:56:46 +02:00
nghttpx - proxy
+++++++++++++++
2014-07-31 16:16:52 +02:00
``nghttpx`` is a multi-threaded reverse proxy for ``h2-14``, SPDY and
2015-03-16 07:42:19 +01:00
HTTP/1.1, and powers http://nghttp2.org and supports HTTP/2 server push.
2015-03-31 16:31:24 +02:00
``nghttpx`` implements `important performance-oriented features
<https://istlsfastyet.com/#server-performance>`_ in TLS, such as
session IDs, session tickets (with automatic key rotation), OCSP
stapling, dynamic record sizing, ALPN/NPN, forward secrecy and SPDY &
HTTP/2.
``nghttpx`` has several operational modes:
2013-08-03 12:44:13 +02:00
2014-03-30 12:09:21 +02:00
================== ============================ ============== =============
Mode option Frontend Backend Note
================== ============================ ============== =============
default mode HTTP/2, SPDY, HTTP/1.1 (TLS) HTTP/1.1 Reverse proxy
``--http2-proxy`` HTTP/2, SPDY, HTTP/1.1 (TLS) HTTP/1.1 SPDY proxy
``--http2-bridge`` HTTP/2, SPDY, HTTP/1.1 (TLS) HTTP/2 (TLS)
``--client`` HTTP/2, HTTP/1.1 HTTP/2 (TLS)
``--client-proxy`` HTTP/2, HTTP/1.1 HTTP/2 (TLS) Forward proxy
================== ============================ ============== =============
2013-07-27 14:56:46 +02:00
2014-04-08 16:12:02 +02:00
The interesting mode at the moment is the default mode. It works like
2014-07-31 16:16:52 +02:00
a reverse proxy and listens for ``h2-14``, SPDY and HTTP/1.1 and can
2015-03-16 07:42:19 +01:00
be deployed as a SSL/TLS terminator for existing web server.
2013-07-27 14:56:46 +02:00
2013-11-04 10:26:08 +01:00
The default mode, ``--http2-proxy`` and ``--http2-bridge`` modes use
2014-04-08 16:12:02 +02:00
SSL/TLS in the frontend connection by default. To disable SSL/TLS,
2015-03-16 07:42:19 +01:00
use the ``--frontend-no-tls`` option. If that option is used, SPDY is
disabled in the frontend and incoming HTTP/1.1 connections can be
2014-04-08 16:12:02 +02:00
upgraded to HTTP/2 through HTTP Upgrade.
2013-08-03 12:44:13 +02:00
2013-11-04 10:26:08 +01:00
The ``--http2-bridge``, ``--client`` and ``--client-proxy`` modes use
2014-04-08 16:12:02 +02:00
SSL/TLS in the backend connection by deafult. To disable SSL/TLS, use
2015-03-16 07:42:19 +01:00
the ``--backend-no-tls`` option.
2013-07-27 15:40:44 +02:00
2015-03-16 07:42:19 +01:00
``nghttpx`` supports a configuration file. See the ``--conf`` option and
2013-07-27 14:56:46 +02:00
sample configuration file ``nghttpx.conf.sample``.
2013-11-04 10:26:08 +01:00
In the default mode, (without any of ``--http2-proxy``,
``--http2-bridge``, ``--client-proxy`` and ``--client`` options),
``nghttpx`` works as reverse proxy to the backend server::
2013-07-27 14:56:46 +02:00
2014-03-30 12:09:21 +02:00
Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> Web Server
2013-08-03 12:44:13 +02:00
[reverse proxy]
2013-07-27 14:56:46 +02:00
2015-03-16 07:42:19 +01:00
With the ``--http2-proxy`` option, it works as a so called secure proxy (aka
2013-11-04 10:26:08 +01:00
SPDY proxy)::
2013-07-27 14:56:46 +02:00
2014-03-30 12:09:21 +02:00
Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> Proxy
2014-06-27 17:25:23 +02:00
[secure proxy] (e.g., Squid, ATS)
2013-07-27 14:56:46 +02:00
2015-03-16 07:42:19 +01:00
The ``Client`` in the above example needs to be configured to use
2013-08-03 12:44:13 +02:00
``nghttpx`` as secure proxy.
2013-07-27 14:56:46 +02:00
At the time of this writing, Chrome is the only browser which supports
2015-03-16 07:42:19 +01:00
secure proxy. One way to configure Chrome to use a secure proxy is
to create a proxy.pac script like this:
2014-01-11 09:13:24 +01:00
.. code-block:: javascript
2013-07-27 14:56:46 +02:00
function FindProxyForURL(url, host) {
return "HTTPS SERVERADDR:PORT";
}
``SERVERADDR`` and ``PORT`` is the hostname/address and port of the
2015-03-16 07:42:19 +01:00
machine nghttpx is running on. Please note that Chrome requires a valid
2013-08-03 12:44:13 +02:00
certificate for secure proxy.
2013-07-27 14:56:46 +02:00
Then run Chrome with the following arguments::
2013-07-27 14:56:46 +02:00
$ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn
2014-03-30 12:09:21 +02:00
With ``--http2-bridge``, it accepts HTTP/2, SPDY and HTTP/1.1
2015-03-16 07:42:19 +01:00
connections and communicates with the backend in HTTP/2::
2013-07-27 14:56:46 +02:00
2014-03-30 12:09:21 +02:00
Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/2) --> Web or HTTP/2 Proxy etc
2013-08-03 12:44:13 +02:00
(e.g., nghttpx -s)
2013-07-27 14:56:46 +02:00
2015-03-16 07:42:19 +01:00
With ``--client-proxy``, it works as a forward proxy and expects
that the backend is an HTTP/2 proxy::
2013-07-27 14:56:46 +02:00
2014-03-30 12:09:21 +02:00
Client <-- (HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/2) --> HTTP/2 Proxy
2013-08-03 12:44:13 +02:00
[forward proxy] (e.g., nghttpx -s)
2013-07-27 14:56:46 +02:00
2015-03-16 07:42:19 +01:00
The ``Client`` needs to be configured to use nghttpx as a forward
2014-03-30 12:09:21 +02:00
proxy. The frontend HTTP/1.1 connection can be upgraded to HTTP/2
2013-08-03 12:44:13 +02:00
through HTTP Upgrade. With the above configuration, one can use
2014-03-30 12:09:21 +02:00
HTTP/1.1 client to access and test their HTTP/2 servers.
2013-07-27 14:56:46 +02:00
2015-03-16 07:42:19 +01:00
With ``--client``, it works as a reverse proxy and expects that
the backend is an HTTP/2 Web server::
2013-07-27 14:56:46 +02:00
2014-03-30 12:09:21 +02:00
Client <-- (HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/2) --> Web Server
2013-08-03 12:44:13 +02:00
[reverse proxy]
2014-03-30 12:09:21 +02:00
The frontend HTTP/1.1 connection can be upgraded to HTTP/2
2013-08-03 12:44:13 +02:00
through HTTP Upgrade.
2013-07-27 14:56:46 +02:00
2014-03-30 12:09:21 +02:00
For the operation modes which talk to the backend in HTTP/2 over
2015-03-16 07:42:19 +01:00
SSL/TLS, the backend connections can be tunneled through an HTTP proxy.
The proxy is specified using ``--backend-http-proxy-uri``. The
following figure illustrates the example of the ``--http2-bridge`` and
2014-04-08 16:12:02 +02:00
``--backend-http-proxy-uri`` options to talk to the outside HTTP/2
2015-03-16 07:42:19 +01:00
proxy through an HTTP proxy::
2013-07-27 14:56:46 +02:00
2014-03-30 12:09:21 +02:00
Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/2) --
2013-07-27 14:56:46 +02:00
2014-03-30 12:09:21 +02:00
--===================---> HTTP/2 Proxy
2013-07-27 14:56:46 +02:00
(HTTP proxy tunnel) (e.g., nghttpx -s)
2013-10-28 16:22:18 +01:00
2014-03-02 15:44:43 +01:00
Benchmarking tool
-----------------
The ``h2load`` program is a benchmarking tool for HTTP/2 and SPDY.
2015-03-16 07:42:19 +01:00
The SPDY support is enabled if the program was built with the spdylay
2014-04-08 16:12:02 +02:00
library. The UI of ``h2load`` is heavily inspired by ``weighttp``
(https://github.com/lighttpd/weighttp). The typical usage is as
follows::
2014-03-02 15:44:43 +01:00
2015-02-01 10:08:21 +01:00
$ h2load -n100000 -c100 -m100 https://localhost:8443/
2014-03-02 15:44:43 +01:00
starting benchmark...
spawning thread #0: 100 concurrent clients, 100000 total requests
Protocol: TLSv1.2
Cipher: ECDHE-RSA-AES128-GCM-SHA256
2014-03-02 15:44:43 +01:00
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 7.10s, 14092 req/s, 55.67MB/s
requests: 100000 total, 100000 started, 100000 done, 100000 succeeded, 0 failed, 0 errored
status codes: 100000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 414200800 bytes total, 2723100 bytes headers, 409600000 bytes data
2015-02-15 08:38:42 +01:00
min max mean sd +/- sd
time for request: 283.86ms 1.46s 659.70ms 150.87ms 84.68%
2015-03-16 07:42:19 +01:00
The above example issued total 100,000 requests, using 100 concurrent
clients (in other words, 100 HTTP/2 sessions), and a maximum of 100 streams
per client. With the ``-t`` option, ``h2load`` will use multiple native
threads to avoid saturating a single core on client side.
2014-03-02 15:44:43 +01:00
.. warning::
2014-04-08 16:12:02 +02:00
**Don't use this tool against publicly available servers.** That is
2015-03-16 07:42:19 +01:00
considered a DOS attack. Please only use it against your private
servers.
2014-03-02 15:44:43 +01:00
2014-01-10 13:53:48 +01:00
HPACK tools
-----------
2013-10-28 16:22:18 +01:00
2015-03-16 07:42:19 +01:00
The ``src`` directory contains the HPACK tools. The ``deflatehd`` program is a
command-line header compression tool. The ``inflatehd`` program is a
2014-01-10 13:53:48 +01:00
command-line header decompression tool. Both tools read input from
2015-03-16 07:42:19 +01:00
stdin and write output to stdout. Errors are written to stderr.
They take JSON as input and output. We (mostly) use the same JSON data
format described at https://github.com/http2jp/hpack-test-case.
2013-10-28 16:22:18 +01:00
deflatehd - header compressor
+++++++++++++++++++++++++++++
2015-03-16 07:42:19 +01:00
The ``deflatehd`` program reads JSON data or HTTP/1-style header fields from
2014-01-11 09:06:26 +01:00
stdin and outputs compressed header block in JSON.
2013-10-28 16:22:18 +01:00
2015-03-16 07:42:19 +01:00
For the JSON input, the root JSON object must include a ``cases`` key.
2014-04-08 16:12:02 +02:00
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-15 12:00:51 +01:00
appear. Each item in the sequence is a JSON object and it must
2015-03-16 07:42:19 +01:00
include a ``headers`` key. Its value is an array of JSON objects,
2014-02-15 12:00:51 +01:00
which includes exactly one name/value pair.
2013-10-28 16:22:18 +01:00
2014-01-11 09:13:24 +01:00
Example:
.. code-block:: json
2013-10-28 16:22:18 +01:00
2014-01-11 09:06:26 +01:00
{
"cases":
[
{
"headers": [
{ ":method": "GET" },
{ ":path": "/" }
]
},
{
"headers": [
{ ":method": "POST" },
{ ":path": "/" }
]
}
]
}
2013-10-28 16:22:18 +01:00
2015-03-16 07:42:19 +01:00
With the ``-t`` option, the program can accept more familiar HTTP/1 style
header field blocks. Each header set is delimited by an empty line:
2013-10-28 16:22:18 +01:00
Example::
:method: GET
:scheme: https
:path: /
:method: POST
user-agent: nghttp2
2015-03-16 07:42:19 +01:00
The output is in JSON object. It should include a ``cases`` key and its
value is an array of JSON objects, which has at least the following keys:
2013-10-28 16:22:18 +01:00
seq
The index of header set in the input.
2014-01-11 09:06:26 +01:00
input_length
2015-03-16 07:42:19 +01:00
The sum of the length of the name/value pairs in the input.
2013-10-28 16:22:18 +01:00
2014-01-11 09:06:26 +01:00
output_length
2015-03-16 07:42:19 +01:00
The length of the compressed header block.
2013-10-28 16:22:18 +01:00
2014-01-11 09:06:26 +01:00
percentage_of_original_size
``input_length`` / ``output_length`` * 100
2013-10-28 16:22:18 +01:00
2014-01-11 09:06:26 +01:00
wire
2015-03-16 07:42:19 +01:00
The compressed header block as a hex string.
2013-10-28 16:22:18 +01:00
2014-01-11 09:06:26 +01:00
headers
The input header set.
header_table_size
2015-03-16 07:42:19 +01:00
The header table size adjusted before deflating the header set.
2014-01-11 09:06:26 +01:00
2014-01-11 09:13:24 +01:00
Examples:
.. code-block:: json
2013-10-28 16:22:18 +01:00
2014-01-11 09:06:26 +01:00
{
"cases":
[
{
"seq": 0,
"input_length": 66,
"output_length": 20,
"percentage_of_original_size": 30.303030303030305,
"wire": "01881f3468e5891afcbf83868a3d856659c62e3f",
"headers": [
{
":authority": "example.org"
},
{
":method": "GET"
},
{
":path": "/"
},
{
":scheme": "https"
},
{
"user-agent": "nghttp2"
}
],
"header_table_size": 4096
}
,
{
"seq": 1,
"input_length": 74,
"output_length": 10,
"percentage_of_original_size": 13.513513513513514,
"wire": "88448504252dd5918485",
"headers": [
{
":authority": "example.org"
},
{
":method": "POST"
},
{
":path": "/account"
},
{
":scheme": "https"
},
{
"user-agent": "nghttp2"
}
],
"header_table_size": 4096
}
]
}
The output can be used as the input for ``inflatehd`` and
``deflatehd``.
2015-03-16 07:42:19 +01:00
With the ``-d`` option, the extra ``header_table`` key is added and its
associated value includes the state of dynamic header table after the
2014-04-08 16:12:02 +02:00
corresponding header set was processed. The value includes at least
the following keys:
2013-10-28 16:22:18 +01:00
entries
2014-04-08 16:12:02 +02:00
The entry in the header table. If ``referenced`` is ``true``, it
is in the reference set. The ``size`` includes the overhead (32
bytes). The ``index`` corresponds to the index of header table.
2013-10-28 16:22:18 +01:00
The ``name`` is the header field name and the ``value`` is the
2014-04-08 16:12:02 +02:00
header field value.
2013-10-28 16:22:18 +01:00
size
The sum of the spaces entries occupied, this includes the
entry overhead.
2014-01-11 09:06:26 +01:00
max_size
2013-10-28 16:22:18 +01:00
The maximum header table size.
2014-01-11 09:06:26 +01:00
deflate_size
The sum of the spaces entries occupied within
``max_deflate_size``.
2013-10-28 16:22:18 +01:00
2014-01-11 09:06:26 +01:00
max_deflate_size
2015-03-16 07:42:19 +01:00
The maximum header table size the encoder uses. This can be smaller
than ``max_size``. In this case, the encoder only uses up to first
2014-04-08 16:12:02 +02:00
``max_deflate_size`` buffer. Since the header table size is still
2014-01-11 09:06:26 +01:00
``max_size``, the encoder has to keep track of entries ouside the
``max_deflate_size`` but inside the ``max_size`` and make sure
that they are no longer referenced.
2013-10-28 16:22:18 +01:00
2014-01-11 09:13:24 +01:00
Example:
.. code-block:: json
2013-10-28 16:22:18 +01:00
2014-01-11 09:06:26 +01:00
{
"cases":
[
{
"seq": 0,
"input_length": 66,
"output_length": 20,
"percentage_of_original_size": 30.303030303030305,
"wire": "01881f3468e5891afcbf83868a3d856659c62e3f",
"headers": [
{
":authority": "example.org"
},
{
":method": "GET"
},
{
":path": "/"
},
{
":scheme": "https"
},
{
"user-agent": "nghttp2"
}
],
"header_table_size": 4096,
"header_table": {
"entries": [
{
"index": 1,
"name": "user-agent",
"value": "nghttp2",
"referenced": true,
"size": 49
},
{
"index": 2,
"name": ":scheme",
"value": "https",
"referenced": true,
"size": 44
},
{
"index": 3,
"name": ":path",
"value": "/",
"referenced": true,
"size": 38
},
{
"index": 4,
"name": ":method",
"value": "GET",
"referenced": true,
"size": 42
},
{
"index": 5,
"name": ":authority",
"value": "example.org",
"referenced": true,
"size": 53
}
],
"size": 226,
"max_size": 4096,
"deflate_size": 226,
"max_deflate_size": 4096
}
}
,
{
"seq": 1,
"input_length": 74,
"output_length": 10,
"percentage_of_original_size": 13.513513513513514,
"wire": "88448504252dd5918485",
"headers": [
{
":authority": "example.org"
},
{
":method": "POST"
},
{
":path": "/account"
},
{
":scheme": "https"
},
{
"user-agent": "nghttp2"
}
],
"header_table_size": 4096,
"header_table": {
"entries": [
{
"index": 1,
"name": ":method",
"value": "POST",
"referenced": true,
"size": 43
},
{
"index": 2,
"name": "user-agent",
"value": "nghttp2",
"referenced": true,
"size": 49
},
{
"index": 3,
"name": ":scheme",
"value": "https",
"referenced": true,
"size": 44
},
{
"index": 4,
"name": ":path",
"value": "/",
"referenced": false,
"size": 38
},
{
"index": 5,
"name": ":method",
"value": "GET",
"referenced": false,
"size": 42
},
{
"index": 6,
"name": ":authority",
"value": "example.org",
"referenced": true,
"size": 53
}
],
"size": 269,
"max_size": 4096,
"deflate_size": 269,
"max_deflate_size": 4096
}
}
]
}
2013-10-28 16:22:18 +01:00
inflatehd - header decompressor
+++++++++++++++++++++++++++++++
2015-03-16 07:42:19 +01:00
The ``inflatehd`` program reads JSON data from stdin and outputs decompressed
2014-01-11 09:06:26 +01:00
name/value pairs in JSON.
2013-10-28 16:22:18 +01:00
2015-03-16 07:42:19 +01:00
The root JSON object must include the ``cases`` key. Its value has to
include the sequence of compressed header blocks. They share the same
2014-04-08 16:12:02 +02:00
compression context and are processed in the order they appear. Each
2015-03-16 07:42:19 +01:00
item in the sequence is a JSON object and it must have at least a
``wire`` key. Its value is a compressed header block as a hex string.
2013-10-28 16:22:18 +01:00
2014-01-11 09:13:24 +01:00
Example:
.. code-block:: json
2013-10-28 16:22:18 +01:00
2014-01-11 09:06:26 +01:00
{
"cases":
[
{ "wire": "8285" },
{ "wire": "8583" }
]
}
2013-10-28 16:22:18 +01:00
2015-03-16 07:42:19 +01:00
The output is a JSON object. It should include a ``cases`` key and its
value is an array of JSON objects, which has at least following keys:
2013-10-28 16:22:18 +01:00
seq
2015-03-16 07:42:19 +01:00
The index of the header set in the input.
2013-10-28 16:22:18 +01:00
headers
2015-03-16 07:42:19 +01:00
A JSON array that includes decompressed name/value pairs.
2014-01-11 09:06:26 +01:00
wire
2015-03-16 07:42:19 +01:00
The compressed header block as a hex string.
2014-01-11 09:06:26 +01:00
header_table_size
The header table size adjusted before inflating compressed header
2014-01-11 09:06:26 +01:00
block.
2013-10-28 16:22:18 +01:00
2014-01-11 09:13:24 +01:00
Example:
.. code-block:: json
2013-10-28 16:22:18 +01:00
2014-01-11 09:06:26 +01:00
{
"cases":
[
{
"seq": 0,
"wire": "01881f3468e5891afcbf83868a3d856659c62e3f",
"headers": [
{
":authority": "example.org"
},
{
":method": "GET"
},
{
":path": "/"
},
{
":scheme": "https"
},
{
"user-agent": "nghttp2"
}
],
"header_table_size": 4096
}
,
{
"seq": 1,
"wire": "88448504252dd5918485",
"headers": [
{
":method": "POST"
},
{
":path": "/account"
},
{
"user-agent": "nghttp2"
},
{
":scheme": "https"
},
{
":authority": "example.org"
}
],
"header_table_size": 4096
}
]
}
The output can be used as the input for ``deflatehd`` and
``inflatehd``.
2015-03-16 07:42:19 +01:00
With the ``-d`` option, the extra ``header_table`` key is added and its
associated value includes the state of the dynamic header table after the
2014-04-08 16:12:02 +02:00
corresponding header set was processed. The format is the same as
2013-10-28 16:22:18 +01:00
``deflatehd``.
2014-09-23 17:25:37 +02:00
libnghttp2_asio: High level HTTP/2 C++ library
----------------------------------------------
libnghttp2_asio is C++ library built on top of libnghttp2 and provides
high level abstraction API to build HTTP/2 applications. It depends
2015-03-16 07:42:19 +01:00
on the Boost::ASIO library and OpenSSL. Currently libnghttp2_asio
provides both client and server APIs.
2014-09-23 17:25:37 +02:00
2015-03-16 07:42:19 +01:00
libnghttp2_asio is not built by default. Use the ``--enable-asio-lib``
2014-09-23 17:25:37 +02:00
configure flag to build libnghttp2_asio. The required Boost libraries
are:
* Boost::Asio
* Boost::System
* Boost::Thread
2015-03-16 07:42:19 +01:00
The server API is designed to build an HTTP/2 server very easily to utilize
C++11 anonymous functions and closures. The bare minimum example of
an HTTP/2 server looks like this:
2014-09-23 17:25:37 +02:00
.. code-block:: cpp
2015-03-05 18:23:17 +01:00
#include <nghttp2/asio_http2_server.h>
2014-09-23 17:25:37 +02:00
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
2014-11-30 14:54:55 +01:00
int main(int argc, char *argv[]) {
2015-03-06 16:39:35 +01:00
boost::system::error_code ec;
2014-09-23 17:25:37 +02:00
http2 server;
2015-03-05 18:23:17 +01:00
server.handle("/", [](const request &req, const response &res) {
res.write_head(200);
res.end("hello, world\n");
2014-11-30 14:54:55 +01:00
});
2015-03-05 18:23:17 +01:00
2015-03-06 16:39:35 +01:00
if (server.listen_and_serve(ec, "localhost", "3000")) {
std::cerr << "error: " << ec.message() << std::endl;
}
2014-09-23 17:25:37 +02:00
}
2015-03-16 07:42:19 +01:00
Here is sample code to use the client API:
.. code-block:: cpp
#include <iostream>
#include <nghttp2/asio_http2_client.h>
using boost::asio::ip::tcp;
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::client;
int main(int argc, char *argv[]) {
boost::system::error_code ec;
boost::asio::io_service io_service;
// connect to localhost:3000
session sess(io_service, "localhost", "3000");
sess.on_connect([&sess](tcp::resolver::iterator endpoint_it) {
boost::system::error_code ec;
auto req = sess.submit(ec, "GET", "http://localhost:3000/");
req->on_response([](const response &res) {
// print status code and response header fields.
std::cerr << "HTTP/2 " << res.status_code() << std::endl;
for (auto &kv : res.header()) {
std::cerr << kv.first << ": " << kv.second.value << "\n";
}
std::cerr << std::endl;
res.on_data([](const uint8_t *data, std::size_t len) {
std::cerr.write(reinterpret_cast<const char *>(data), len);
std::cerr << std::endl;
});
});
req->on_close([&sess](uint32_t error_code) {
// shutdown session after first request was done.
sess.shutdown();
});
});
sess.on_error([](const boost::system::error_code &ec) {
std::cerr << "error: " << ec.message() << std::endl;
});
io_service.run();
}
2014-09-23 17:25:37 +02:00
For more details, see the documentation of libnghttp2_asio.
Python bindings
---------------
2015-03-16 07:42:19 +01:00
The ``python`` directory contains nghttp2 Python bindings. The
2014-04-08 16:12:02 +02:00
bindings currently provide HPACK compressor and decompressor classes
2015-03-16 07:42:19 +01:00
and an HTTP/2 server.
The extension module is called ``nghttp2``.
``make`` will build the bindings and target Python version is
2015-03-16 07:42:19 +01:00
determined by the ``configure`` script. If the detected Python version is not
what you expect, specify a path to Python executable in a ``PYTHON``
variable as an argument to configure script (e.g., ``./configure
PYTHON=/usr/bin/python3.4``).
2015-03-16 07:42:19 +01:00
The following example code illustrates basic usage of the HPACK compressor
2014-01-10 18:02:53 +01:00
and decompressor in Python:
.. code-block:: python
import binascii
import nghttp2
2014-02-16 07:30:46 +01:00
deflater = nghttp2.HDDeflater()
inflater = nghttp2.HDInflater()
data = deflater.deflate([(b'foo', b'bar'),
2014-01-11 09:06:26 +01:00
(b'baz', b'buz')])
print(binascii.b2a_hex(data))
hdrs = inflater.inflate(data)
print(hdrs)
2014-02-24 17:46:38 +01:00
The ``nghttp2.HTTP2Server`` class builds on top of the asyncio event
2014-04-08 16:12:02 +02:00
loop. On construction, *RequestHandlerClass* must be given, which
must be a subclass of ``nghttp2.BaseRequestHandler`` class.
2014-02-24 17:46:38 +01:00
2014-04-08 16:12:02 +02:00
The ``BaseRequestHandler`` class is used to handle the HTTP/2 stream.
By default, it does nothing. It must be subclassed to handle each
event callback method.
2014-02-24 17:46:38 +01:00
2014-04-08 16:12:02 +02:00
The first callback method invoked is ``on_headers()``. It is called
2015-03-16 07:42:19 +01:00
when HEADERS frame, which includes the request header fields, has arrived.
2014-02-24 17:46:38 +01:00
2015-03-16 07:42:19 +01:00
If the request has a request body, ``on_data(data)`` is invoked for each
2014-02-24 17:46:38 +01:00
chunk of received data.
2015-03-16 07:42:19 +01:00
Once the entire request is received, ``on_request_done()`` is invoked.
2014-02-24 17:46:38 +01:00
2015-03-16 07:42:19 +01:00
When the stream is closed, ``on_close(error_code)`` is called.
2014-02-24 17:46:38 +01:00
2015-03-16 07:42:19 +01:00
The application can send a response using ``send_response()`` method.
2014-04-08 16:12:02 +02:00
It can be used in ``on_headers()``, ``on_data()`` or
2014-02-24 17:46:38 +01:00
``on_request_done()``.
2015-03-16 07:42:19 +01:00
The application can push resources using the ``push()`` method. It must be
used before the ``send_response()`` call.
2014-02-24 17:46:38 +01:00
The following instance variables are available:
client_address
Contains a tuple of the form (host, port) referring to the
client's address.
stream_id
Stream ID of this stream.
2014-02-24 17:46:38 +01:00
scheme
2014-04-08 16:12:02 +02:00
Scheme of the request URI. This is a value of :scheme header
field.
2014-02-24 17:46:38 +01:00
method
2014-04-08 16:12:02 +02:00
Method of this stream. This is a value of :method header field.
2014-02-24 17:46:38 +01:00
host
This is a value of :authority or host header field.
path
This is a value of :path header field.
The following example illustrates the HTTP2Server and
BaseRequestHandler usage:
.. code-block:: python
#!/usr/bin/env python
import io, ssl
import nghttp2
class Handler(nghttp2.BaseRequestHandler):
def on_headers(self):
self.push(path='/css/bootstrap.css',
2014-02-25 13:25:51 +01:00
request_headers = [('content-length', '3')],
2014-02-24 17:46:38 +01:00
status=200,
body='foo')
self.push(path='/js/bootstrap.js',
method='GET',
2014-02-25 13:25:51 +01:00
request_headers = [('content-length', '10')],
2014-02-24 17:46:38 +01:00
status=200,
body='foobarbuzz')
self.send_response(status=200,
2014-02-25 13:25:51 +01:00
headers = [('content-type', 'text/plain')],
2014-02-24 17:46:38 +01:00
body=io.BytesIO(b'nghttp2-python FTW'))
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ctx.options = ssl.OP_ALL | ssl.OP_NO_SSLv2
ctx.load_cert_chain('server.crt', 'server.key')
# give None to ssl to make the server non-SSL/TLS
server = nghttp2.HTTP2Server(('127.0.0.1', 8443), Handler, ssl=ctx)
server.serve_forever()
2014-08-16 16:23:52 +02:00
Contribution
------------
[This text was composed based on 1.2. License section of curl/libcurl
project.]
When contributing with code, you agree to put your changes and new
code under the same license nghttp2 is already using unless stated and
agreed otherwise.
2015-03-16 07:42:19 +01:00
When changing existing source code, do not alter the copyright of
2014-08-16 16:23:52 +02:00
the original file(s). The copyright will still be owned by the
original creator(s) or those who have been assigned copyright by the
original author(s).
2015-03-16 07:42:19 +01:00
By submitting a patch to the nghttp2 project, you (or your employer, as
the case may be) agree to assign the copyright of your submission to us.
2015-03-16 07:42:19 +01:00
.. the above really needs to be reworded to pass legal muster.
We will credit you for your
2014-08-16 16:23:52 +02:00
changes as far as possible, to give credit but also to keep a trace
back to who made what changes. Please always provide us with your
full real name when contributing!
2014-11-26 15:43:20 +01:00
See `Contribution Guidelines
<https://nghttp2.org/documentation/contribute.html>`_ for more
details.