Compare commits

..

740 Commits

Author SHA1 Message Date
Tatsuhiro Tsujikawa
7f12f0671c Update bash_completion 2015-09-12 22:53:05 +09:00
Tatsuhiro Tsujikawa
39fb5972d4 Update man pages 2015-09-12 22:51:40 +09:00
Tatsuhiro Tsujikawa
063e1d7606 Bump up version number to 1.3.1, LT revision to 15:1:1 2015-09-12 22:43:21 +09:00
Tatsuhiro Tsujikawa
57aee184ca Update doc 2015-09-12 18:33:07 +09:00
Tatsuhiro Tsujikawa
4ae2850aa6 Add sphinx rubydomain files to EXTRA_DIST 2015-09-12 17:51:19 +09:00
Tatsuhiro Tsujikawa
f586797f7d Use INSTALL_DIR to customize mruby local installation directory
This change effectively makes `make distcheck` succeed.
2015-09-12 17:36:01 +09:00
Tatsuhiro Tsujikawa
0d8c8ca033 h2load: Record TTFB on first byte of response body, rather than first socket read 2015-09-12 11:18:54 +09:00
Tatsuhiro Tsujikawa
5ea90ba6bd nghttpx: Fix crash with signal QUIT if mruby is not initialized 2015-09-12 02:40:55 +09:00
Tatsuhiro Tsujikawa
fd8067be94 Merge branch 'thinred-fix-sysv-service' 2015-09-12 02:35:12 +09:00
Tatsuhiro Tsujikawa
ad34b45782 Merge branch 'fix-sysv-service' of https://github.com/thinred/nghttp2 into thinred-fix-sysv-service 2015-09-12 02:34:54 +09:00
Tatsuhiro Tsujikawa
d0f96da2c0 src: Cleanup 2015-09-12 02:10:07 +09:00
Tomasz Buchert
da57989cf6 start nghttpx with --daemon 2015-09-11 18:59:37 +02:00
Tatsuhiro Tsujikawa
f086b7b67e nghttpx: Fix busy loop 2015-09-12 01:22:40 +09:00
Tatsuhiro Tsujikawa
471fd688b9 Update mruby 2015-09-12 00:29:13 +09:00
Tatsuhiro Tsujikawa
02adaac368 nghttpx: Write h1 header into downstream buffer directly 2015-09-11 23:49:47 +09:00
Tatsuhiro Tsujikawa
1bbef4be74 Avoid usage of typeof and replace __builtin_offsetof with offsetof 2015-09-10 21:27:14 +09:00
Tatsuhiro Tsujikawa
918f8cca36 Honor stream->weight even if stream->last_writelen is 0 2015-09-09 21:20:59 +09:00
Tatsuhiro Tsujikawa
22b39f0337 Revert "last_write_len must not be 0, which makes weight useless"
This reverts commit e260006182.
2015-09-09 21:16:53 +09:00
Tatsuhiro Tsujikawa
e282462e1f Set have_mruby=no so that we can show it in summary 2015-09-09 21:16:11 +09:00
Tatsuhiro Tsujikawa
e4843201b0 Compile third-party libraries if hpack-tools is enabled 2015-09-09 21:11:42 +09:00
Tatsuhiro Tsujikawa
753f6d4a3e src: Fix compiler warning 2015-09-09 21:01:13 +09:00
Tatsuhiro Tsujikawa
aba2dbddc2 nghttpx: Don't allow partial PROXY protocol line 2015-09-09 00:21:54 +09:00
Tatsuhiro Tsujikawa
510dff4c39 Add mruby requirements 2015-09-08 02:37:51 +09:00
Tatsuhiro Tsujikawa
e260006182 last_write_len must not be 0, which makes weight useless 2015-09-08 02:27:59 +09:00
Tatsuhiro Tsujikawa
7d481db248 Merge branch 'nghttpx-proxyprotocol' 2015-09-07 23:52:39 +09:00
Tatsuhiro Tsujikawa
4f52f60b3c src: Inline some single character categorization functions 2015-09-07 23:28:31 +09:00
Tatsuhiro Tsujikawa
5afc25623e Pass CFLAGS, CXXFLAGS and LDFLAGS to mruby build 2015-09-07 23:28:31 +09:00
Tatsuhiro Tsujikawa
3ce1c1d39f nghttpx: Add date header field to error_reply and send_reply 2015-09-07 23:11:23 +09:00
Tatsuhiro Tsujikawa
21a3edfc60 nghttpx: Use 's' for param of Response::return 2015-09-07 23:00:01 +09:00
Tatsuhiro Tsujikawa
026ab797eb src: util::numeric_host: Use inet_pton instead of getaddrinfo 2015-09-07 22:40:37 +09:00
Tatsuhiro Tsujikawa
79945c0c45 nghttpx: Robust PROXY protocol implementation 2015-09-07 22:37:25 +09:00
Tatsuhiro Tsujikawa
f8c1da7f3c nghttpx: Add --accept-proxy-protocol usage to help message 2015-09-06 23:27:07 +09:00
Tatsuhiro Tsujikawa
a1bb48770c nghttpx: Add tests for PROXY protocol handling 2015-09-06 23:11:07 +09:00
Tatsuhiro Tsujikawa
d05b77b36c nghttpx: More logging for PROXY protocol handling 2015-09-06 21:44:45 +09:00
Tatsuhiro Tsujikawa
ce53bd239e nghttpx: Implement PROXY protocol version 1
Use --accept-proxy-protocol to enable PROXY protocol handling
2015-09-06 21:30:19 +09:00
Tatsuhiro Tsujikawa
39287314d3 nghttpx: Fix missing break 2015-09-06 18:34:10 +09:00
Tatsuhiro Tsujikawa
231db4a3e6 Update man pages 2015-09-06 17:41:37 +09:00
Tatsuhiro Tsujikawa
c30d252f94 nghttpx: Show warning if certain feature is not compiled in 2015-09-06 16:59:57 +09:00
Tatsuhiro Tsujikawa
6d46249b7b Merge branch 'nghttpx-mruby' 2015-09-06 16:39:21 +09:00
Tatsuhiro Tsujikawa
1b63e6d478 nghttpx: Call request phase hook for pushed resource as well 2015-09-06 15:21:36 +09:00
Tatsuhiro Tsujikawa
28defbfb4a nghttpx: Allow link header server push for HTTP/2 backend as well 2015-09-06 15:12:20 +09:00
Tatsuhiro Tsujikawa
75b98662be Don't use git submodule update --init in Makefile
This is because when we make tar ball, we are no longer under git
control.  git submodule does not work there.  We instead bundle mruby
source tree in archive.  git submodule command is only required when
building from git repository.
2015-09-06 01:23:11 +09:00
Tatsuhiro Tsujikawa
1df682140c nghttpx: Don't do mruby push with --no-server-push option 2015-09-06 00:06:48 +09:00
Tatsuhiro Tsujikawa
7273c7d688 Document mruby push 2015-09-06 00:05:07 +09:00
Tatsuhiro Tsujikawa
ef1595672c nghttpx: Add Request#push in mruby scripting
Refactor Http2Upstream so that we can share code between link header
field based push and mruby push.
2015-09-06 00:05:07 +09:00
Tatsuhiro Tsujikawa
98c959291f Update README.rst 2015-09-05 22:46:55 +09:00
Tatsuhiro Tsujikawa
2135c87f94 Update README.rst 2015-09-05 21:39:26 +09:00
Tatsuhiro Tsujikawa
e1106e0f91 Update doc 2015-09-05 21:28:43 +09:00
Tatsuhiro Tsujikawa
7b0113ac77 Remove \r 2015-09-05 21:26:58 +09:00
Tatsuhiro Tsujikawa
6f0c88580f Add *.pyc to .gitignore 2015-09-05 21:24:54 +09:00
Tatsuhiro Tsujikawa
18064d1626 Document nghttpx mruby extension 2015-09-05 21:23:27 +09:00
Tatsuhiro Tsujikawa
3029e5c530 Bundle sphinxcontrib.rubydomain
Source files were downloaded from
https://bitbucket.org/birkenfeld/sphinx-contrib/src/default/rubydomain/
2015-09-05 21:22:50 +09:00
Tatsuhiro Tsujikawa
be77b47ab5 integration: Add ruby scripts to EXTRA_DIST 2015-09-05 19:10:55 +09:00
Tatsuhiro Tsujikawa
77958eab46 Merge branch 'master' into nghttpx-mruby 2015-09-05 19:04:04 +09:00
Tatsuhiro Tsujikawa
8f41accf41 nghttpx: Don't initiate push if client disabled push 2015-09-05 19:02:55 +09:00
Tatsuhiro Tsujikawa
e19d5efced nghttpx: Allow absolute URI in Link header field for push 2015-09-05 19:01:02 +09:00
Tatsuhiro Tsujikawa
69c3e2114a Again fix mruby build properly; pass CC, CXX and LD to build_config.rb 2015-09-05 18:22:46 +09:00
Tatsuhiro Tsujikawa
6dcfe1c3f8 Add missing build_config.rb 2015-09-05 18:10:10 +09:00
Tatsuhiro Tsujikawa
d076d54f67 nghttpx: Don't add mruby related CPPFLAGS and LDFLAGS if it is disabled
Setting unused -L really makes libtool get angry
2015-09-05 18:03:05 +09:00
Tatsuhiro Tsujikawa
aba7e9e7f9 Add mruby as submodule; disable mruby by default for now 2015-09-05 17:49:10 +09:00
Tatsuhiro Tsujikawa
4ac7152f94 nghttpx: Fix build failure without mruby 2015-09-05 01:32:26 +09:00
Tatsuhiro Tsujikawa
d348ea3384 integration: Fix test failures 2015-09-05 01:24:43 +09:00
Tatsuhiro Tsujikawa
b4709b9e8c nghttpx: Fix crash without mruby script 2015-09-05 01:20:32 +09:00
Tatsuhiro Tsujikawa
21e1af2ae7 nghttpx: Delete replaced header fields 2015-09-05 01:18:18 +09:00
Tatsuhiro Tsujikawa
226a09b04a nghttpx: Use gc arena save/restore when creating headers hash 2015-09-05 01:14:17 +09:00
Tatsuhiro Tsujikawa
587f37a597 nghttpx: Remove unused includes 2015-09-05 01:12:51 +09:00
Tatsuhiro Tsujikawa
97f488a5c7 nghttpx: Add Env.phase method 2015-09-05 01:11:20 +09:00
Tatsuhiro Tsujikawa
45e0d42c51 nghttpx: Check allowed operations per phase 2015-09-05 01:07:29 +09:00
Tatsuhiro Tsujikawa
bddc4a0a04 nghttpx: Rewrite API; introduce Env object 2015-09-05 00:53:42 +09:00
Tatsuhiro Tsujikawa
a9338f1c0e nghttpx: Fix hang when error page is sent on response phase hook error 2015-09-04 22:34:40 +09:00
Tatsuhiro Tsujikawa
4ad00200a2 Merge branch 'master' into nghttpx-mruby 2015-09-04 22:22:06 +09:00
Tatsuhiro Tsujikawa
6b38f7e0d2 nghttpx: Fix crash with multi workers and QUIT signal 2015-09-04 22:21:10 +09:00
Tatsuhiro Tsujikawa
4872c9b4c9 Use C++ compiler to detect mruby since we have to enable C++ ABI mode
Since default Debian/Ubuntu mruby package does not enable C++ ABI
mode, it cannot be used with our C++ code, since mruby exception does
not properly cleanup C++ object allocated on stack.  We have to build
mruby with conf.enable_cxx_abi explicitly.  It is safe for us to build
our own mruby.
2015-09-04 22:10:49 +09:00
Tatsuhiro Tsujikawa
d8ca0a8d47 nghttpx: Add clear_headers and add_header methods to Request and Response 2015-09-04 02:53:02 +09:00
Tatsuhiro Tsujikawa
2222a898a1 integration: Add mruby tests 2015-09-04 02:52:19 +09:00
Tatsuhiro Tsujikawa
9e685a2734 nghttpx: Various test failures 2015-09-04 02:47:25 +09:00
Tatsuhiro Tsujikawa
c86e839091 nghttpx: Fix mruby detection 2015-09-04 01:33:20 +09:00
Tatsuhiro Tsujikawa
d722a09581 nghttpx: Rename mruby script options 2015-09-04 01:19:57 +09:00
Tatsuhiro Tsujikawa
5967667e9e nghttpx: Allow empty path assignment in mruby code 2015-09-04 01:00:27 +09:00
Tatsuhiro Tsujikawa
d044c58558 nghttpx: Detect mruby presence and guard mruby related code with ifdef 2015-09-04 00:54:41 +09:00
Tatsuhiro Tsujikawa
200217d8ea nghttpx: Store empty string to path for server-wide OPTIONS request
This change is required to show path attribute to mruby script.  It is
desirable to construct URI from parts.  Just checking method and path
is "*" is awkward.
2015-09-04 00:14:09 +09:00
Tatsuhiro Tsujikawa
02bb2c3e83 nghttpx: Create authority from host or authority-form for CONNECT request 2015-09-03 23:36:49 +09:00
Tatsuhiro Tsujikawa
64c754e2c5 Merge branch 'master' into nghttpx-mruby 2015-09-03 22:53:16 +09:00
Tatsuhiro Tsujikawa
ad65121496 nghttpx: Fix assertion error because of empty scheme 2015-09-03 22:52:33 +09:00
Tatsuhiro Tsujikawa
3235b88253 nghttpx: Fix assertion error because of empty scheme 2015-09-03 22:51:24 +09:00
Tatsuhiro Tsujikawa
5e3ab6da5a nghttpx: Perhaps this looks right, but not sure 2015-09-03 22:44:41 +09:00
Tatsuhiro Tsujikawa
6f9c9f8518 nghttpx: Fix assertion failure when response was commited early 2015-09-03 22:41:51 +09:00
Tatsuhiro Tsujikawa
65f2b16132 nghttpx: More freedom for custom response headers 2015-09-03 22:29:16 +09:00
Tatsuhiro Tsujikawa
05a761b628 nghttpx: Add Request.remote_addr which returns client remote address 2015-09-03 02:02:28 +09:00
Tatsuhiro Tsujikawa
14f5240d8f nghttpx: Update doc 2015-09-03 01:37:47 +09:00
Tatsuhiro Tsujikawa
baadec5ef4 nghttpx: Add response mruby hook 2015-09-03 01:33:52 +09:00
Tatsuhiro Tsujikawa
d20229d9b9 nghttpx: Handle block is not passed 2015-09-03 00:43:42 +09:00
Tatsuhiro Tsujikawa
e06af02573 nghttpx: Add Response mruby object 2015-09-03 00:40:14 +09:00
Tatsuhiro Tsujikawa
5cd34920b7 nghttpx: Add Request class accessors 2015-09-02 23:22:33 +09:00
Tatsuhiro Tsujikawa
e436caf0bb nghttpx: Don't forward request if response was commited in mruby hook 2015-09-02 23:22:26 +09:00
Tatsuhiro Tsujikawa
f0d41a5ac2 nghttpx: Handle nil given to request.set_header as value 2015-09-02 22:41:48 +09:00
Tatsuhiro Tsujikawa
068529586d nghttpx: Split up request class definition to dedicated files 2015-09-02 22:38:57 +09:00
Tatsuhiro Tsujikawa
45cdb10c46 nghttpx: Use ruby block to run request hook 2015-09-02 22:25:04 +09:00
Tatsuhiro Tsujikawa
2170d958d5 nghttpx: Return copied string for safety 2015-09-02 21:14:49 +09:00
Tatsuhiro Tsujikawa
9d78691936 nghttpx: Fix copy-and-paste bug 2015-09-02 21:14:20 +09:00
Tatsuhiro Tsujikawa
1508c50a45 nghttpx: Add basic infrastructure for mruby support 2015-09-02 02:45:15 +09:00
Tatsuhiro Tsujikawa
dd0a72579f Merge branch 'LPardue-issue-339' 2015-09-02 02:37:19 +09:00
Tatsuhiro Tsujikawa
e7bc269e97 Merge branch 'master' into LPardue-issue-339 2015-09-02 02:35:36 +09:00
Tatsuhiro Tsujikawa
e2557059e5 h2load: Fix crash with --timing-script option 2015-09-02 02:34:32 +09:00
Tatsuhiro Tsujikawa
0c4e26fd24 Merge branch 'issue-339' of https://github.com/LPardue/nghttp2 into LPardue-issue-339 2015-09-02 02:24:10 +09:00
Lucas Pardue
3002674bac h2load: Improve checking for timing script imput, prevent false positive in certain situations 2015-09-01 17:15:41 +00:00
Tatsuhiro Tsujikawa
e1f7643c92 nghttpx: Fix memory leak 2015-09-02 02:07:29 +09:00
Tatsuhiro Tsujikawa
d70eb14ce0 nghttpx: Drop connection before TLS finish if h2 requirement is not fulfilled 2015-08-31 23:30:40 +09:00
Tatsuhiro Tsujikawa
31c19cbda4 Bump up version number to 1.3.1-DEV 2015-08-30 19:04:31 +09:00
Tatsuhiro Tsujikawa
6d6ed16ab9 Update bash_completion 2015-08-30 18:59:44 +09:00
Tatsuhiro Tsujikawa
5a0f8b1f1f Update man pages 2015-08-30 18:59:30 +09:00
Tatsuhiro Tsujikawa
666308d8f6 Bump up version number to 1.3.0, LT revision to 15:0:1 2015-08-30 18:48:01 +09:00
Tatsuhiro Tsujikawa
789eb8a590 Update man pages 2015-08-30 00:24:11 +09:00
Tatsuhiro Tsujikawa
4cad48da16 Reset cycle to 0 if stream has only 1 direct descendant 2015-08-29 23:44:58 +09:00
Tatsuhiro Tsujikawa
e6566a1e3a Fix parallel make distcheck 2015-08-27 02:20:22 +09:00
Tatsuhiro Tsujikawa
fb4b152a73 Merge branch 'bxshi-add_header_to_nghttp2_asio_barebone_server' 2015-08-27 02:09:42 +09:00
bxshi
4f090d90c0 add iostream library to the example code snippet of nghttp2_asio server. 2015-08-24 02:59:25 -04:00
Tatsuhiro Tsujikawa
891134eba9 Define it and itprep recursive target if AM_EXTRA_RECURSIVE_TARGETS is defined 2015-08-23 23:04:19 +09:00
Tatsuhiro Tsujikawa
36d562927f nghttpx: Use nghttp2::ssl::DEFAULT_CIPHER_LIST for backend TLS connection 2015-08-23 23:03:29 +09:00
Tatsuhiro Tsujikawa
928a81885c Limit the number of incoming reserved (remote) streams
RFC 7540 does not enforce any limit on the number of incoming reserved
streams (in RFC 7540 terms, streams in reserved (remote) state).  This
only affects client side, since only server can push streams.
Malicious server can push arbitrary number of streams, and make
client's memory exhausted.  The new option,
nghttp2_set_max_reserved_remote_streams, can set the maximum number of
such incoming streams to avoid possible memory exhaustion.  If this
option is set, and pushed streams are automatically closed on
reception, without calling user provided callback, if they exceed the
given limit.  The default value is 200.  If session is configured as
server side, this option has no effect.  Server can control the number
of streams to push.
2015-08-23 21:43:41 +09:00
Tatsuhiro Tsujikawa
647e30619f Remove nghttp2_pq_increase_key 2015-08-21 23:35:17 +09:00
Tatsuhiro Tsujikawa
a4156cded3 fetch-ocsp-response: Handle spurious openssl exist status 0
With OpenSSL <= 1.0.1, openssl ocsp command still returns exit code 0,
even if verification was failed.  If that happens certain string is
emitted in stderr, so check that string and if exists, treat it as
error.  This issue was fixed in OpenSSL 1.0.2.

At least OpenSSL 1.0.2, openssl ocsp command still returns exit code
0, even if responder returned non-successful status code (e.g.,
trylater(3)).  We are not sure this is intentional or not.  To handle
this, we again check certain error string in stdout, and if it is
found, treat it as error.
2015-08-21 23:28:45 +09:00
Tatsuhiro Tsujikawa
4a99853021 nghttpd: Fix crash without SSL/TLS 2015-08-21 22:50:15 +09:00
Tatsuhiro Tsujikawa
176411aada Update doc 2015-08-20 23:31:22 +09:00
Tatsuhiro Tsujikawa
4b4a0f7492 nghttpd: GOAWAY if SSL/TLS requirements for HTTP/2 are not met 2015-08-20 21:21:56 +09:00
Tatsuhiro Tsujikawa
fe4efb0a5e Merge branch 'thinred-master' 2015-08-20 19:12:40 +09:00
Tatsuhiro Tsujikawa
1006caf8e9 Merge branch 'master' of https://github.com/thinred/nghttp2 into thinred-master 2015-08-20 19:11:07 +09:00
Tatsuhiro Tsujikawa
780a0381ba h2load: Exit if --timing-script and -r option is used together 2015-08-20 19:07:03 +09:00
Tatsuhiro Tsujikawa
e8ec7867b2 Merge branch 'LPardue-issue-332' 2015-08-20 19:02:56 +09:00
Tatsuhiro Tsujikawa
2423b21c71 Merge branch 'issue-332' of https://github.com/LPardue/nghttp2 into LPardue-issue-332 2015-08-20 18:53:10 +09:00
Lucas Pardue
08bf8a8f1a Move input file validation. Timing script auto nreqs scale correctly with nclients. 2015-08-19 15:23:43 +00:00
Tatsuhiro Tsujikawa
1c12606e70 nghttpx: Don't allow blacked listed cipher suites for HTTP/2 connection 2015-08-19 23:42:43 +09:00
Tatsuhiro Tsujikawa
059280d1a5 Add stream public API
The intention of this stream API is give server application about
stream dependency information, so that it can utilize it for better
scheduling of stream processing.  We have no plan to add object
oriented API based on stream object.
2015-08-19 23:04:06 +09:00
Tatsuhiro Tsujikawa
836b1de0d5 h2load: Remove trailing white spaces 2015-08-19 21:19:42 +09:00
Tatsuhiro Tsujikawa
12cecaa030 h2load: Remove trailing spaces and left conflict marker 2015-08-19 00:32:11 +09:00
Tatsuhiro Tsujikawa
50ae0ce739 Merge branch 'LPardue-h2load' 2015-08-19 00:29:14 +09:00
Lucas Pardue
cd4758227d Add Timing-script and base URI support 2015-08-18 15:16:50 +00:00
Tatsuhiro Tsujikawa
2e643424ac Remove unused nghttp2_stream_roots declaration 2015-08-18 22:38:28 +09:00
Tatsuhiro Tsujikawa
9da6c88d25 h2load: Use ev_timer_init 2015-08-18 21:34:33 +09:00
Tatsuhiro Tsujikawa
04aaaa3821 h2load: Remove trailing white spaces 2015-08-18 21:32:47 +09:00
Tatsuhiro Tsujikawa
da3bd559a9 Merge branch 'nshoemaker-time' 2015-08-18 21:22:24 +09:00
Nora
727ba4906c h2load adding timeout options 2015-08-18 01:52:22 -04:00
Tatsuhiro Tsujikawa
71623b674e Optimize pq 2015-08-18 00:26:20 +09:00
Tatsuhiro Tsujikawa
6a511aef0a Use remove/push combination instead of <= for performance 2015-08-18 00:21:42 +09:00
Tatsuhiro Tsujikawa
627d04fe6b nghttpd: Return date header field for 304 2015-08-17 23:49:01 +09:00
Tatsuhiro Tsujikawa
165cab7a29 nghttpd: Support HEAD request 2015-08-17 23:47:35 +09:00
Tatsuhiro Tsujikawa
5b59e46e2b Rewrite priority handling
We now use priority queue per stream, which contains the stream which
has ready to send a frame, or one of its descendants have a frame to
send.  We maintain invariant that if a stream is queued, then its
ancestors are also queued (except for root).  When we re-schedule
stream after transmission, we re-schedule all ancestors, so that
streams on the other path can get a chance to send.  This is basically
the same mechanism h2o project uses, but there are differences in the
details.
2015-08-17 22:35:50 +09:00
Tatsuhiro Tsujikawa
73b77964ef Reset last_cycle to 0 if queue gets empty 2015-08-15 01:08:20 +09:00
Tatsuhiro Tsujikawa
8ce8b2af46 src: Remove unused Memchunk::shrink 2015-08-15 00:57:58 +09:00
Tatsuhiro Tsujikawa
d1e49a196d Remove restriction in regard to number of stream in dependency tree
Previously, the number of stream in one dependency tree (not including
root) is limited to 120.  This is due to the fact that we use
recursive calls to traverse trees.  Now we replaced recursive calls
with loop, we can remove this limitation.  Also now all streams are
descendant of root stream, rather than linked list of individual
subtree root.
2015-08-15 00:53:09 +09:00
Tatsuhiro Tsujikawa
8c8d1f6e14 Bump up version number to 1.2.2-DEV 2015-08-15 00:13:37 +09:00
Tatsuhiro Tsujikawa
48244b9aca Update man pages 2015-08-14 23:59:47 +09:00
Tatsuhiro Tsujikawa
eb42fb4f49 Bump up version number to 1.2.1, LT revision to 14:8:0 2015-08-14 23:55:08 +09:00
Tatsuhiro Tsujikawa
b37834c584 h2load: Use default Config values to show help 2015-08-14 23:22:26 +09:00
Tatsuhiro Tsujikawa
d197d115dc h2load: Use floating point duration cast 2015-08-14 22:44:14 +09:00
Tatsuhiro Tsujikawa
3a1c37248a Update doc 2015-08-14 22:38:23 +09:00
Tatsuhiro Tsujikawa
f7fa9eb21b Fix sum_norest_weight calculation bug in stream dependency tree 2015-08-14 01:27:50 +09:00
Tatsuhiro Tsujikawa
4839d6d513 Merge branch 'nshoemaker-r_n' 2015-08-14 00:04:21 +09:00
nshoemaker
e1621584fa Fixing -r > -n check for when -n is not specified. 2015-08-13 05:09:40 -07:00
Tomasz Buchert
97566ce4e3 nghttpx: make early copy of stderr 2015-08-13 11:01:37 +02:00
Tomasz Buchert
900dcf4ced nghttpx: remove Android-specific code 2015-08-12 20:17:03 +02:00
Tomasz Buchert
06a0f3480e nghttpx: better handle /dev/stderr and /dev/stdout 2015-08-12 20:16:57 +02:00
Tatsuhiro Tsujikawa
473311269d nghttpx: Drop connection if client TLS handshake packet is too large 2015-08-13 01:24:59 +09:00
Tatsuhiro Tsujikawa
0c4cbc800b Document that previous OCSP response is continued to be used 2015-08-13 00:47:32 +09:00
Tatsuhiro Tsujikawa
b8f05c89bd nghttpx: App data in SSL is Connection, not ClientHandler 2015-08-13 00:42:59 +09:00
Tatsuhiro Tsujikawa
e91a576179 nghttpx: Rewrite TLS async handshake using memchunk buffers 2015-08-13 00:42:59 +09:00
Tatsuhiro Tsujikawa
72c661f1dd Merge branch 'yuki-kodama-openssl_no_ec' 2015-08-13 00:41:58 +09:00
Tatsuhiro Tsujikawa
2277cc771a Merge branch 'openssl_no_ec' of https://github.com/yuki-kodama/nghttp2 into yuki-kodama-openssl_no_ec 2015-08-13 00:32:15 +09:00
Tatsuhiro Tsujikawa
f8c30d0229 nghttpx: Fix heap-use-after-free 2015-08-12 21:14:18 +09:00
yuuki-kodama
53b5ffa103 Guard ecdh use with !OPENSSL_NO_EC @asio_server_tls_context.cc 2015-08-12 15:32:54 +09:00
Tatsuhiro Tsujikawa
b384b76f66 nghttpx: Fix hmac_keylen should be 16 for aes-128-cbc 2015-08-12 00:38:07 +09:00
Tatsuhiro Tsujikawa
b406d2da9e h2load: Stop timeout_watcher in Worker dtor 2015-08-11 23:51:08 +09:00
Tatsuhiro Tsujikawa
dd97b53554 h2load: Fix division by zero if -r > -n 2015-08-11 23:49:34 +09:00
Tatsuhiro Tsujikawa
0f7e84bb62 h2load: Always initialize timeout_watcher 2015-08-11 23:44:22 +09:00
Tatsuhiro Tsujikawa
81add96b1e src: Fix bug in get_uint64 2015-08-11 23:42:32 +09:00
Tatsuhiro Tsujikawa
020e66b9da nghttpx: Start read watcher after handshake 2015-08-11 23:14:48 +09:00
Tatsuhiro Tsujikawa
d2a63a88a0 nghttpx: Fix stall if read buffer has app data when handshake finished 2015-08-11 22:37:15 +09:00
Tatsuhiro Tsujikawa
e5a9f6c163 Merge branch 'skip2-reword-hpac-tutorial' 2015-08-11 00:24:50 +09:00
Tom Harwood
560955f50d doc: Reword the HPAC tutorial.
The overall meaning is the same. I added a paragraph to introduce nghttp2_hd_inflate_hd(), and added an explanation of using NGHTTP2_NV_FLAG_NO_INDEX for security sensitive headers.
2015-08-09 17:05:52 +01:00
Tatsuhiro Tsujikawa
8410f684fb nghttpx: Drop connection if client hello is too large 2015-08-10 00:29:43 +09:00
Tatsuhiro Tsujikawa
ff44e211ed nghttpx: Fix tls handshake bug
This fixes 2 things:
1. potential busy loop
2. disabling ticket is not working after resumption
2015-08-09 18:33:49 +09:00
Tatsuhiro Tsujikawa
73442ba5ba Bump up version number to 1.2.1-DEV 2015-08-09 01:27:50 +09:00
Tatsuhiro Tsujikawa
b78662e506 integration: Fix errors related to host-rewrite 2015-08-09 01:23:58 +09:00
Tatsuhiro Tsujikawa
8a7bc6f7bc Update bash_completion 2015-08-09 01:13:53 +09:00
Tatsuhiro Tsujikawa
66f2097627 Update man pages 2015-08-09 01:13:35 +09:00
Tatsuhiro Tsujikawa
a67d15be58 Bump up version number to 1.2.0, LT revision to 14:7:0 2015-08-09 01:09:37 +09:00
Tatsuhiro Tsujikawa
2e7cee0faa h2load: Code cleanup 2015-08-09 01:05:15 +09:00
Tatsuhiro Tsujikawa
50eac7bdf0 h2load: Fix -r does not work without -C option 2015-08-09 00:24:17 +09:00
Tatsuhiro Tsujikawa
846da5fb3f h2load: Update doc 2015-08-08 23:44:47 +09:00
Tatsuhiro Tsujikawa
3e53cd189c clang-format-3.5 2015-08-08 23:36:02 +09:00
Tatsuhiro Tsujikawa
9331dc755e Add python-setuptools to apt-get line 2015-08-07 22:27:26 +09:00
Tatsuhiro Tsujikawa
bf8220fd5e Merge branch 'skip2-reword-client-tutorial' 2015-08-04 23:36:37 +09:00
Tatsuhiro Tsujikawa
6a70f34c73 Merge branch 'reword-client-tutorial' of https://github.com/skip2/nghttp2 into skip2-reword-client-tutorial 2015-08-04 23:33:00 +09:00
Tom Harwood
c50ea91a3f doc: Reword some of the client tutorial.
The overall meaning of the tutorial is the same. I added text describing frame types where it helps explain the callbacks better, e.g. introducing the HEADERS frame before on_header_callback().

Also fixed a couple of typos:
- Fixed ``reacb`` typo to ``readcb``
- Added parens to some functions, e.g. ``on_frame_recv_callback`` => ``on_frame_recv_callback()``
2015-08-04 00:08:12 +01:00
Tatsuhiro Tsujikawa
388285675b python: Check protocol is None 2015-08-03 16:49:09 +09:00
Tatsuhiro Tsujikawa
0481d44c69 Fix typo 2015-08-01 20:20:32 +09:00
Tatsuhiro Tsujikawa
3d0905a90f Merge branch 'skip2-master' 2015-08-01 16:20:00 +09:00
Tatsuhiro Tsujikawa
091055edec Merge branch 'master' of https://github.com/skip2/nghttp2 into skip2-master 2015-08-01 16:18:55 +09:00
Tom Harwood
4f0ff5bfb1 doc: fix a couple of links 2015-08-01 02:39:38 +01:00
Tatsuhiro Tsujikawa
c941bff929 Fix compile error with gcc 2015-07-31 21:27:36 +09:00
Tatsuhiro Tsujikawa
0bbff5b738 nghttpx: Continue if push was failed 2015-07-31 21:25:43 +09:00
Tatsuhiro Tsujikawa
e66bd490a4 Fix crash if response or data is submitted to closing stream 2015-07-31 21:11:16 +09:00
Tom Harwood
e9e9626c2c doc: Reword some of the server tutorial.
The overall meaning of the tutorial is the same, except for a couple of changes:
- app_context struct was called "app_content", fixed the typo
- nghttp2_session_server_new2() is mentioned, but the example uses nghttp2_session_server_new() instead, changed the text to match
2015-07-30 23:50:34 +01:00
Tatsuhiro Tsujikawa
a152c6346d Fix build error with Android NDK 2015-07-30 22:57:25 +09:00
Tatsuhiro Tsujikawa
96a6dcb152 python: Remove draft from hpack checker 2015-07-30 22:12:08 +09:00
Tatsuhiro Tsujikawa
8c701bb139 Header table size UINT32_MAX must be accepted 2015-07-30 21:19:46 +09:00
Tatsuhiro Tsujikawa
ebf27e6523 Fix configure warning that 'missing' is missing or too old 2015-07-30 20:08:43 +09:00
Tatsuhiro Tsujikawa
c379b46a26 Remove monotonic_clock replacement macro for gcc-4.6 2015-07-29 21:19:33 +09:00
Tatsuhiro Tsujikawa
762bafa47b Add tlsticketupdate.go to EXTRA_DIST 2015-07-29 21:18:16 +09:00
Tatsuhiro Tsujikawa
0ed8ed3f8d tlsticketupdate.go: Add expiry time, some refactoring 2015-07-29 21:14:43 +09:00
Tatsuhiro Tsujikawa
6446660113 nghttpx: Make record size timeout more durable to high load situation 2015-07-29 20:57:11 +09:00
Tatsuhiro Tsujikawa
d0a37d59a5 nghttpx: Disable TLS session ticket if ticket key is not available 2015-07-29 20:38:49 +09:00
Tatsuhiro Tsujikawa
58dd924343 Update man pages 2015-07-29 00:01:12 +09:00
Tatsuhiro Tsujikawa
a73cfd5f7b nghttpx: Add reference to manual section for session resumption 2015-07-29 00:00:43 +09:00
Tatsuhiro Tsujikawa
a1288a5826 nghttpx: Rename --tls-ticket-cipher as --tls-ticket-key-cipher 2015-07-28 23:49:37 +09:00
Tatsuhiro Tsujikawa
80d96590c5 nghttpx: Update doc 2015-07-28 23:43:32 +09:00
Tatsuhiro Tsujikawa
e8c83798da Merge branch 'memcached' 2015-07-28 21:20:21 +09:00
Tatsuhiro Tsujikawa
6ad332b801 nghttpx: Call disconnect() when memcached connection cannot be made 2015-07-28 21:19:27 +09:00
Tatsuhiro Tsujikawa
f1b163a32c nghttpx: Log notice level when TLS ticket key was retrieved from memcached 2015-07-28 02:19:14 +09:00
Tatsuhiro Tsujikawa
7a3dff5a65 Add sample TLS ticket key generator program 2015-07-28 01:59:48 +09:00
Tatsuhiro Tsujikawa
4d7be08585 nghttpx: Do some macro dance for IOV_MAX 2015-07-28 01:26:34 +09:00
Tatsuhiro Tsujikawa
a6fdca730d nghttpx: Add options to set maximum retry and failure when getting ticket keys 2015-07-28 01:17:29 +09:00
Tatsuhiro Tsujikawa
4949dd4888 nghttpx: Add --tls-ticket-key-memcached-interval option 2015-07-28 01:02:33 +09:00
Tatsuhiro Tsujikawa
2f2a300e83 nghttpx: Add TLS ticket key sharing among nghttpx instances using memcached 2015-07-28 00:54:44 +09:00
Tatsuhiro Tsujikawa
a4a9cfd650 nghttpx: Change session cache key prefix 2015-07-27 21:18:12 +09:00
Tatsuhiro Tsujikawa
bb228c27de Merge branch 'master' into memcached
Conflicts:
	src/shrpx_ssl.cc
2015-07-27 21:16:02 +09:00
Tatsuhiro Tsujikawa
7152e0f6b8 nghttpx: Fix bug that decrypt only key is not considered 2015-07-27 21:13:02 +09:00
Tatsuhiro Tsujikawa
72cfdbc0fa nghttpx: Fix compile error on travis (again) 2015-07-27 02:28:36 +09:00
Tatsuhiro Tsujikawa
f472e6ff48 nghttpx: Fix compile error on travis 2015-07-27 02:22:27 +09:00
Tatsuhiro Tsujikawa
1708d2e69e nghttpx: Add doc 2015-07-27 02:14:52 +09:00
Tatsuhiro Tsujikawa
e3cdfd12ea nghttpx: Use std::array for TicketKey 2015-07-27 02:12:07 +09:00
Tatsuhiro Tsujikawa
cd25c6846e nghttpx: Create struct Address which holds struct sockaddr_union and length 2015-07-27 01:41:10 +09:00
Tatsuhiro Tsujikawa
efcd43a367 nghttpx: Don't enable read timer while connecting to HTTP/1 server 2015-07-27 01:18:52 +09:00
Tatsuhiro Tsujikawa
90b4b48c7e nghttpx: Add shared session cache using memcached 2015-07-26 23:33:06 +09:00
Tatsuhiro Tsujikawa
9eb234d321 Merge branch 'nshoemaker-mt' 2015-07-25 12:57:29 +09:00
Tatsuhiro Tsujikawa
fea70ec832 Merge branch 'mt' of https://github.com/nshoemaker/nghttp2 into nshoemaker-mt 2015-07-25 12:55:15 +09:00
Tatsuhiro Tsujikawa
3e333f49fe Update http-parser 2015-07-25 12:53:17 +09:00
Nora Shoemaker
12013508bf Running clang-format 2015-07-24 15:35:11 -07:00
Nora Shoemaker
871a93e4aa Merge branch 'mt_master' into mt 2015-07-24 15:31:55 -07:00
Nora Shoemaker
85e4151bca manual merge 2015-07-24 15:17:22 -07:00
Nora Shoemaker
278247faa9 Starting a second earlier 2015-07-24 14:34:53 -07:00
Nora Shoemaker
e2808dcd96 Merge pull request #4 from tatsuhiro-t/master
Merging tatsuhiro-t:master -> nshoemaker:master
2015-07-24 13:38:04 -07:00
Tatsuhiro Tsujikawa
adec2c06bf nghttpx: Set SSL/TLS session timeout to 12 hours 2015-07-24 23:59:19 +09:00
Tatsuhiro Tsujikawa
6c8243f6d2 nghttpd: Add verbose output when SSL/TLS session is reused 2015-07-24 23:40:44 +09:00
Tatsuhiro Tsujikawa
afbb99ecf7 nghttpx: Enable session resumption on HTTP/2 backend 2015-07-24 23:40:27 +09:00
Tatsuhiro Tsujikawa
abce7c7210 nghttpd: Fix the bug that 304 response has non-empty body 2015-07-24 23:25:10 +09:00
Nora Shoemaker
ec617ae6e5 Getting rid of unused fields in config 2015-07-23 11:21:12 -07:00
Nora Shoemaker
d6786f75cb Getting rid of unused fields in Worker 2015-07-23 11:01:09 -07:00
Nora Shoemaker
584f5f3734 Do not allow -r > -t 2015-07-23 10:37:51 -07:00
Nora Shoemaker
a04c67bcd6 Getting rid of print statements 2015-07-23 10:30:55 -07:00
Nora Shoemaker
8325c6ccdf setting request number correctly: 2015-07-23 10:20:18 -07:00
Nora Shoemaker
30235f8809 Assigning clients to workers proportional to rate 2015-07-23 09:37:44 -07:00
Tatsuhiro Tsujikawa
9b63fc011e nghttpx: Open log files by default configuration 2015-07-24 00:32:19 +09:00
Tatsuhiro Tsujikawa
cab6c7871c nghttpx: Don't rewrite host header field by default
In reverse proxy usage, backend server most likely wants to see the
original header field.  So this commit turns off host header rewrite
by default.  --no-host-rewrite option is deprecated, and if it is
used, warning message is displayed.  --host-rewrite option is added to
enable host rewrite.
2015-07-23 23:54:56 +09:00
Tatsuhiro Tsujikawa
04bd25d468 nghttpx: Simplify ticket handling between workers just using mutex 2015-07-23 23:13:29 +09:00
Tatsuhiro Tsujikawa
cd2c751f82 nghttpx: Generate new ticket key every 1hr and its life time is now 12hrs 2015-07-23 21:14:38 +09:00
Nora Shoemaker
65df3c63bf Adding new rate and connection allocation to threads 2015-07-22 16:41:58 -07:00
Tatsuhiro Tsujikawa
aa012f7a58 Use PROTOCOL_ERROR against DATA sent to idle stream 2015-07-23 02:02:27 +09:00
Tatsuhiro Tsujikawa
f6a8c8d078 Remove unused variable 2015-07-23 00:44:54 +09:00
Tatsuhiro Tsujikawa
7f71fed963 Allow multiple in-flight SETTINGS 2015-07-23 00:36:00 +09:00
Tatsuhiro Tsujikawa
44cbc785fc nghttpx: Don't reuse backend connection if it is not clean 2015-07-22 21:41:16 +09:00
Nora Shoemaker
916e27489f rate now working 2015-07-21 16:53:46 -07:00
Nora Shoemaker
650e463a49 First try with something working, still need to clean and test 2015-07-21 11:28:12 -07:00
Nora Shoemaker
52152ad96d Can make h2load, but running into recursive loop problem 2015-07-21 11:06:33 -07:00
Tatsuhiro Tsujikawa
f3288092e8 Strictly check occurrence of dynamic table size update
RFC 7541 requires that dynamic table size update must occur at the
beginning of the first header block, and is signaled as SETTINGS
acknowledgement.  This commit checks these conditions.  If dynamic
table size update appears other than the beginning of the first header
block, it is treated as error.  If SETTINGS ACK is received, and next
HEADERS header block does not have dynamic table size update, it is
treated as error.
2015-07-22 00:11:23 +09:00
Tatsuhiro Tsujikawa
18234b8741 Merge branch 'alagoutte-misc' 2015-07-21 21:18:40 +09:00
Alexis La Goutte
26b7bee16f Fix rm: cannot remove ‘*.rst’: No such file or directory when "make clean"
When you don't generated documentation via make html
2015-07-21 11:19:50 +02:00
Tatsuhiro Tsujikawa
921e393dcd src: Use <PATH> instead of <FILE> in usage text 2015-07-20 23:50:05 +09:00
Tatsuhiro Tsujikawa
0ec1b98f27 nghttpx: Reorder config fields 2015-07-20 23:15:01 +09:00
Tatsuhiro Tsujikawa
a8574fdef2 nghttpx: Use Use std::string instead of std::unique_ptr<char[]> for tls config 2015-07-20 23:15:01 +09:00
Tatsuhiro Tsujikawa
dd8ce1e9d2 nghttpx: Use std::unique_ptr<char[]> instead of raw char pointer 2015-07-20 21:37:23 +09:00
Tatsuhiro Tsujikawa
ca3444c34c Fix compile error/warnings with gcc-4.7 2015-07-19 20:50:14 +09:00
Tatsuhiro Tsujikawa
5c96ecd77d Dump APIDOC removal failure errors to /dev/null 2015-07-19 19:16:09 +09:00
Tatsuhiro Tsujikawa
fa7a74cfa8 h2load: Use std::string::size instead of strlen 2015-07-19 18:37:41 +09:00
Tatsuhiro Tsujikawa
b37716ab6a h2load: Workaround with clang-3.4 2015-07-19 18:35:14 +09:00
Tatsuhiro Tsujikawa
5dc060c1a2 src: Use C++11 value-initialization, instead of memset-ing 0 2015-07-19 17:55:37 +09:00
Tatsuhiro Tsujikawa
05d5c404e2 Merge branch 'tls-session-ticket-aes256' 2015-07-19 17:38:34 +09:00
Tatsuhiro Tsujikawa
cce64e6728 h2load: Call second_timeout_cb manually so that we don't waste first 1 second 2015-07-19 17:31:35 +09:00
Tatsuhiro Tsujikawa
006ac7b1b0 h2load: Fix HTML formatting 2015-07-19 17:27:38 +09:00
Tatsuhiro Tsujikawa
5465cdf4a4 src: Don't use struct tm.tm_yday from strptime 2015-07-19 17:14:25 +09:00
Tatsuhiro Tsujikawa
f2a1c8ee60 Partially revert a23ab00686
The workaround introduced in a23ab00686
may cause a problem in certain platform (e.g., MacPorts, see GH-303)
2015-07-19 16:11:42 +09:00
Tatsuhiro Tsujikawa
a78fcdb7bf Merge branch 'nshoemaker-h2load_r_C' 2015-07-19 16:07:09 +09:00
Tatsuhiro Tsujikawa
ad87266a58 Merge branch 'h2load_r_C' of https://github.com/nshoemaker/nghttp2 into nshoemaker-h2load_r_C 2015-07-19 16:04:43 +09:00
Nora Shoemaker
d326e28c92 running clang-format 2015-07-17 14:10:40 -07:00
Nora Shoemaker
c1c177addc Changing warning to mention #reqs rather than test time 2015-07-17 14:10:21 -07:00
Tatsuhiro Tsujikawa
e8167ceea7 nghttpx: Add AES-256-CBC encryption for TLS session ticket 2015-07-18 02:02:33 +09:00
Tatsuhiro Tsujikawa
ac301537ef Bump up version number to 1.1.3-DEV 2015-07-18 00:31:43 +09:00
Tatsuhiro Tsujikawa
03034c0081 Update man pages 2015-07-18 00:23:53 +09:00
Tatsuhiro Tsujikawa
fa872a6b48 Bump up version number to 1.1.2 2015-07-18 00:21:29 +09:00
Tatsuhiro Tsujikawa
a23ab00686 Allow custom install location for python bindings 2015-07-18 00:19:47 +09:00
Nora Shoemaker
eeba12144c Refactored seconds setting and worker space reservation 2015-07-16 11:02:01 -07:00
Nora Shoemaker
ce00c50720 Changing comparison from double to ssize_t 2015-07-16 10:51:41 -07:00
Nora Shoemaker
7d2ea42c38 Fixing spelling mistake in num-conns description 2015-07-16 10:43:50 -07:00
Nora Shoemaker
e0d7ce439d Fixing style for Config field initializer list 2015-07-16 10:35:03 -07:00
Nora Shoemaker
ccfe7f8548 Reordering Config field initializer list 2015-07-16 10:33:44 -07:00
Tatsuhiro Tsujikawa
c470ac7b00 asio: Fix missing nghttp2_timegm 2015-07-16 14:01:18 +09:00
Nora Shoemaker
6cf772da6a Merge pull request #2 from tatsuhiro-t/master
pulling changes from master
2015-07-15 11:59:50 -07:00
Nora Shoemaker
5892385e5c [EDGE-879] run clang-format and make sure style is good 2015-07-15 09:51:33 -07:00
Tatsuhiro Tsujikawa
1ce3a000a1 Bump up version number to 1.1.2-DEV 2015-07-16 00:36:10 +09:00
Tatsuhiro Tsujikawa
8585599b4b nghttpx: Add doc 2015-07-16 00:03:34 +09:00
Tatsuhiro Tsujikawa
2bac00ea5f nghttpx: Add additional assert just in case 2015-07-16 00:01:26 +09:00
Tatsuhiro Tsujikawa
3396c71c3c Update man pages 2015-07-15 23:48:41 +09:00
Tatsuhiro Tsujikawa
f821f6bd80 Bump up version number to 1.1.1 2015-07-15 23:46:22 +09:00
Tatsuhiro Tsujikawa
7a3012cc1b src: Rename timegm as nghttp2_timegm 2015-07-15 23:44:24 +09:00
Tatsuhiro Tsujikawa
ba31b990a2 nghttpx: Remove dead handling of Downstream::STREAM_CLOSED 2015-07-15 23:33:44 +09:00
Tatsuhiro Tsujikawa
fc062976a1 nghttpx: Delete DownstreamConnection from Downstream explicitly 2015-07-15 23:31:32 +09:00
Tatsuhiro Tsujikawa
20e63151a5 nghttpx: Fix bug that idle timer is used after reuse 2015-07-15 23:18:32 +09:00
Tatsuhiro Tsujikawa
e63e775fea nghttpx: Simplify BlockedLink management 2015-07-15 20:44:44 +09:00
Tatsuhiro Tsujikawa
031fb31248 nghttpx: Fix memory leak, and blocked stream dispatch 2015-07-15 19:47:15 +09:00
Tatsuhiro Tsujikawa
6d10799301 nghttpx: Don't pool failed HTTP/1 backend connection 2015-07-15 19:46:48 +09:00
Nora Shoemaker
d6551de8d4 [EDGE-877] [h2load] apply changes to new version of h2load 2015-07-14 23:41:29 +00:00
Nora Shoemaker
6b53f7ee19 [EDGE-879] run clang-format and make sure style is good 2015-07-14 11:16:37 -07:00
Tatsuhiro Tsujikawa
f54745fe4c Bump up version number to 1.1.1-DEV 2015-07-15 01:29:57 +09:00
Tatsuhiro Tsujikawa
da51389927 Update man pages 2015-07-15 01:25:27 +09:00
Tatsuhiro Tsujikawa
a06c16c99a Bump up version number to 1.1.0 2015-07-15 01:23:18 +09:00
Tatsuhiro Tsujikawa
3db03a3f51 Exclude python bindings for make distcheck
setuptools does now allow us to install custom location without hack.
Also it does not provide uninstall feature, and `make uninstall`
leaves several files we cannot easily remove (e.g., easy-install.pth).
Therefore, it is better just exclude python bindings from `make
distcheck`.
2015-07-15 01:16:56 +09:00
Tatsuhiro Tsujikawa
5e966d000a python: Fix out-of-tree builds failure 2015-07-15 01:14:52 +09:00
Tatsuhiro Tsujikawa
1c7431293d Update bash_completion 2015-07-15 00:01:22 +09:00
Tatsuhiro Tsujikawa
9c8bc1218d Update man pages 2015-07-15 00:01:04 +09:00
Tatsuhiro Tsujikawa
860da8bf87 Bump up version number to 1.0.6, LT revision to 14:6:0 2015-07-14 23:54:29 +09:00
Tatsuhiro Tsujikawa
326ac31a23 nghttpx: Update doc 2015-07-14 23:45:50 +09:00
Tatsuhiro Tsujikawa
a2c78cfc69 nghttpx: Update doc 2015-07-14 23:44:58 +09:00
Tatsuhiro Tsujikawa
4fed7a1476 nghttpx: Refactor log format parsing 2015-07-14 23:36:44 +09:00
Tatsuhiro Tsujikawa
8c1e863523 nghttpx: Refactor option name lookup 2015-07-14 23:21:38 +09:00
Tatsuhiro Tsujikawa
27da08ee68 nghttpx: Add inline LogFragment ctor 2015-07-14 22:43:02 +09:00
Tatsuhiro Tsujikawa
0a6877d091 nghttpx: Supply template version strcopy 2015-07-14 22:40:33 +09:00
Tatsuhiro Tsujikawa
7f7b6d641d nghttpx: Allow log variable to be enclosed by curly braces 2015-07-14 22:25:52 +09:00
Tatsuhiro Tsujikawa
7c301defbd clang-format src/nghttp.cc 2015-07-14 21:37:34 +09:00
Nora Shoemaker
2482dd7f77 Adding -r and -C options to h2load 2015-07-13 11:28:15 -07:00
Tatsuhiro Tsujikawa
fb7775e382 nghttpx: Detect loop in --include paths 2015-07-13 21:44:06 +09:00
Tatsuhiro Tsujikawa
f96edbf987 nghttpx: Pin frontend to specific HTTP/2 session object per group 2015-07-13 21:31:37 +09:00
Tatsuhiro Tsujikawa
3db0badc35 Update man pages 2015-07-12 23:26:45 +09:00
Tatsuhiro Tsujikawa
3097547491 nghttpx: Add --include option to read additional configuration from given file 2015-07-12 23:18:36 +09:00
Tatsuhiro Tsujikawa
6307f96fb3 nghttpx: Enable host-path backend routing in HTTP/2 backend
To achieve host-path backend routing, we changed behaviour of
--backend-http2-connections-per-worker.  It now sets the number of
HTTP/2 physical connections per pattern group if pattern is used in -b
option.

Fixes GH-292
2015-07-12 23:02:30 +09:00
Tatsuhiro Tsujikawa
8a2543d7b7 asio: Fix custom OpenSSL build 2015-07-11 19:37:04 +09:00
Tatsuhiro Tsujikawa
fa7069a273 nghttpx: Don't rewrite path if http2 proxy or client proxy is enabled
There are many requests which changes its meaning when we rewrite
path.  This is due to bad percent-encoding in URI; reserved characters
are just used without percent encoding.  It seems this is common in ad
services, but I suspect more to come.  For reverse proxying situation,
sane service most likely encodes URI properly, so probably this is not
an issue.
2015-07-11 17:50:58 +09:00
Tatsuhiro Tsujikawa
1a63cd94aa nghttpx: Pass by reference, since it just get copied there 2015-07-11 17:30:38 +09:00
Tatsuhiro Tsujikawa
7c216c6df8 nghttpx: Document that patterns with host take precedence 2015-07-11 16:46:13 +09:00
Tatsuhiro Tsujikawa
e7724914a9 nghttpx: Less copy when matching path 2015-07-11 16:46:13 +09:00
Tatsuhiro Tsujikawa
19e47a1922 nghttpx: Normalize path when setting it to Downstream 2015-07-11 16:12:35 +09:00
Tatsuhiro Tsujikawa
d62e4dbc5e Update man pages 2015-07-11 12:45:23 +09:00
Tatsuhiro Tsujikawa
c2e4ed9624 nghttpx: Deal with the path without trailing slash on pattern match
If pattern ends with '/', and pattern and path matches without that
slash, we consider they match to deal with request to the directory
without trailing slash.  That is if pattern is "/foo/" and path is
"/foo", we consider they match.
2015-07-11 12:43:48 +09:00
Tatsuhiro Tsujikawa
d457f39b1e nghttpx: Fix unix domain backend 2015-07-11 02:41:33 +09:00
Tatsuhiro Tsujikawa
6d556755ee Attemp to fix travis build error 2015-07-11 02:08:16 +09:00
Tatsuhiro Tsujikawa
3119fc259c Select backend based on request host and path by extending -b option
-b option syntax is now <HOST>,<PORT>[;<PATTERN>[:...]].  The optional
<PATTERN>s specify the request host and path it is used for.  The
<PATTERN> can contain path, host + path or host.  The matching rule is
closely designed to ServeMux in Go programming language.
2015-07-11 00:15:52 +09:00
Tatsuhiro Tsujikawa
1940413eb3 Document that python-setuptools is required for python bindings 2015-07-09 21:12:25 +09:00
Tatsuhiro Tsujikawa
237f742100 h2load: Add --ciphers option 2015-07-08 23:14:41 +09:00
Tatsuhiro Tsujikawa
764cd17316 Add test when nghttp2_http_on_data_chunk failed without auto flow control 2015-07-08 22:56:40 +09:00
Tatsuhiro Tsujikawa
c70cfe64c4 Fix DATA is not consumed if nghttp2_http_on_data_chunk failed
This commit fixes the bug that DATA is not consumed if
nghttp2_http_on_data_chunk is failed.  It also simplify the handling
of missing stream in NGHTTP2_IB_READ_DATA state.
2015-07-08 22:56:39 +09:00
Tatsuhiro Tsujikawa
693fba3b64 Add more docs about NGHTTP2_ERR_DATA_EXIST and its condition
This commit documents NGHTTP2_ERR_DATA_EXIST also occurs if HEADERS
has been already attached to stream too.  This commit also fixes
possible assertion error, and now nghttp2_submit_headers() and
nghttp2_submit_response() may return NGHTTP2_ERR_DATA_EXIST.  But we
recommend to use nghttp2_submit_request() and
nghttp2_submit_response(), and using them will avoid this error.
2015-07-08 00:35:07 +09:00
Tatsuhiro Tsujikawa
8fcf5f60e4 nghttp: Add --max-concurrent-streams option 2015-07-08 00:22:21 +09:00
Tatsuhiro Tsujikawa
c00f8e3847 Merge branch 'acesso-patch-2' 2015-07-07 21:22:17 +09:00
Tatsuhiro Tsujikawa
7af638f921 Merge branch 'patch-2' of https://github.com/acesso/nghttp2 into acesso-patch-2 2015-07-07 21:19:23 +09:00
Tatsuhiro Tsujikawa
580c1f3af3 Remove AC_FUNC_MALLOC, which may break C++ build 2015-07-07 21:14:11 +09:00
Tatsuhiro Tsujikawa
d10228cdf7 Merge branch 'mindw-lib_msvc_fix' 2015-07-07 01:19:35 +09:00
Gabi Davar
1dd3564d15 one more. 2015-07-05 18:01:13 +03:00
Gabi Davar
e3fd81995b remove redundant function decorators. 2015-07-05 07:09:27 +03:00
Gabi Davar
d4e1b63c19 msvc build fixes and enchantments.
* fix build broken by recent changes
* place all build artifacts to OBJDIR
* explicitly add manifest (VC9/10)
* modernize python bindings creation
* some minor refactoring
2015-07-04 23:12:55 +03:00
Tatsuhiro Tsujikawa
3973d9ce12 Fix typo 2015-07-04 16:02:28 +09:00
Tatsuhiro Tsujikawa
43d6f6b16a Compile with IRIX gcc-4.7
Patch from Klaus Ziegler
2015-07-01 21:30:27 +09:00
Tatsuhiro Tsujikawa
2f7839fa42 Fix compiler warning 2015-06-30 21:33:54 +09:00
acesso
49c3d75f9a Right place for comment
comment of pushed moved from request to entry array
added stream_id as string to connection element as string
2015-06-29 15:31:00 -03:00
Tatsuhiro Tsujikawa
dc7232fa53 Fix travis compile error 2015-06-30 00:01:26 +09:00
Tatsuhiro Tsujikawa
51ef646678 src: Always use our own faster simpler timegm, use it to calculate gmtoff 2015-06-29 23:14:54 +09:00
Tatsuhiro Tsujikawa
515c313073 nghttpx: Add $ssl_session_reused log variable
The syntax for this variable is the same as nginx: if SSL/TLS session
was reused, "r" is produced.  Otherwise ".".
2015-06-28 22:15:04 +09:00
Tatsuhiro Tsujikawa
197493afd4 nghttpx: Add log variables related to SSL/TLS connection
This commit add following 3 log variables to SSL/TLS connection:
$ssl_cipher, $ssl_protocol, $ssl_session_id.  If no information is
available for them, '-' is produced for each.
2015-06-28 16:44:34 +09:00
acesso
2ea1deafd0 Add comment on HAR on pushed objects
It seems that HAR 1.2 does not have a proper representaion for pushed objects. I could´t just add a custom parameter so I think a comment at response will not hurt anybody.
2015-06-27 09:47:53 -03:00
Tatsuhiro Tsujikawa
b06e339dbb Prepare for IRIX support, port relevant change from spdylay 2015-06-27 17:51:07 +09:00
Tatsuhiro Tsujikawa
68c0f8a310 Fix compile error with gcc-4.7
Use std::map::insert instead of std::map::emplace, since gcc-4.7 does
not support the latter.
2015-06-27 11:19:54 +09:00
Tatsuhiro Tsujikawa
5182dc6cc9 Bump up version number to 1.0.6-DEV 2015-06-27 11:01:44 +09:00
Tatsuhiro Tsujikawa
68f6df61e5 Update man pages 2015-06-27 10:58:25 +09:00
Tatsuhiro Tsujikawa
078337de3c Bump up version number to 1.0.5, LT revision to 14:5:0 2015-06-27 10:55:54 +09:00
Tatsuhiro Tsujikawa
9e82687cbe Fix compile error with --enable-werror 2015-06-26 23:21:01 +09:00
Tatsuhiro Tsujikawa
660f90e13f Add switch STREAM_DEP_DEBUG to enable runtime validation of depedency tree 2015-06-26 23:02:18 +09:00
Tatsuhiro Tsujikawa
2eec42df39 Merge branch 'master' of https://github.com/tatsuhiro-t/nghttp2 2015-06-26 00:03:04 +09:00
Tatsuhiro Tsujikawa
34b92a30de Merge pull request #268 from Andersbakken/typo
Fix typo
2015-06-26 00:02:46 +09:00
Tatsuhiro Tsujikawa
bab99af565 Fix unusual control flow in stream_update_dep_set_rest 2015-06-25 22:31:15 +09:00
Anders Bakken
2e8e38ec35 Fix typo 2015-06-24 13:56:50 -07:00
Tatsuhiro Tsujikawa
d6ca95a0c9 Fix sibling's item is not queued when ancestor's item is detached 2015-06-24 22:18:07 +09:00
Tatsuhiro Tsujikawa
285c74c394 nghttpx: Fix crash with --http2-bridge and both frontend and backend TLS 2015-06-24 21:31:17 +09:00
Tatsuhiro Tsujikawa
7780c07838 Bump up version number to 1.0.5-DEV 2015-06-23 23:25:22 +09:00
Tatsuhiro Tsujikawa
5a8d5e5dd9 Update man pages 2015-06-23 23:22:35 +09:00
Tatsuhiro Tsujikawa
9bcb0ffdef Bump up version number to 1.0.4, LT revision to 14:4:0 2015-06-23 23:20:13 +09:00
Tatsuhiro Tsujikawa
1945d0f02a Fix assertion failure in nghttp2_stream.c
This is regression introduced in
46b70c1db8.
2015-06-23 23:04:53 +09:00
Tatsuhiro Tsujikawa
4870edb33d Bump up version number to 1.0.4-DEV 2015-06-23 01:02:48 +09:00
Tatsuhiro Tsujikawa
3abb162969 Update man pages 2015-06-23 00:54:09 +09:00
Tatsuhiro Tsujikawa
4242478f39 Update nghttpx man page template 2015-06-23 00:53:51 +09:00
Tatsuhiro Tsujikawa
4fa2ffe292 Dump up version number to 1.0.3, LT revision to 14:3:0 2015-06-23 00:48:23 +09:00
Tatsuhiro Tsujikawa
301df2a856 src: Disable SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 2015-06-22 23:26:45 +09:00
Tatsuhiro Tsujikawa
f3b7f4140b nghttpx: Clarify origin host for --backend-http1-connection-per-host 2015-06-22 21:09:39 +09:00
Tatsuhiro Tsujikawa
878b873c69 src: Use using instead of typedef 2015-06-21 19:37:50 +09:00
Tatsuhiro Tsujikawa
2ca8cf36b7 util: Use constexpr for ALPN id 2015-06-21 19:34:43 +09:00
Tatsuhiro Tsujikawa
2224b98c9c Remove duplicated dependency validation in nghttp2_session_reprioritize_stream 2015-06-21 16:31:30 +09:00
Tatsuhiro Tsujikawa
a7031da364 Fix bug that idle self-depending PRIORITY is not handled gracefully
Previously, we did not handle PRIORITY frame which depends on itself
and for idle stream.  As a result, nghttp2_session_mem_recv (or
nghttp2_session_recv) returne NGHTTP2_ERR_NOMEM.  The error code was
still misleading.  It was not out of memory, and we failed to insert
hash map because of duplicated key, which was treated as out of
memory.  This commit fixes this issue, by explicitly checking
dependency for incoming PRIORITY for all cases.
2015-06-21 16:02:32 +09:00
Tatsuhiro Tsujikawa
cebfdacc5a src: Use user-defined literals for time (hours and minutes) 2015-06-21 14:51:32 +09:00
Tatsuhiro Tsujikawa
39f89f4a60 src: Use user-defined literals for k, m, and g. 2015-06-21 14:32:47 +09:00
Tatsuhiro Tsujikawa
46b70c1db8 Optimize dependency based priority code to Firefox style tree
While this commit optimizes dependency routine to Firefox style tree,
the other use cases (e.g., linear chain) are also improved
dramatically as well.
2015-06-20 22:11:24 +09:00
Tatsuhiro Tsujikawa
5537503172 Merge branch 'jfcalcerrada-patch-1' 2015-06-20 19:42:09 +09:00
José F. Calcerrada
81cc550eb9 Update README.rst
Typo
2015-06-20 11:02:33 +01:00
Tatsuhiro Tsujikawa
0a6de0d378 nghttp: Perform special handling of IPv6 literal with zone ID as per RFC 6874
This commit adds special handling of IPv6 literal with zone ID as per
RFC 6874.  Still IPv6 link local address does not work, since URI
parser from http-parser does not allow this syntax.
2015-06-18 20:00:02 +09:00
Tatsuhiro Tsujikawa
25d1de0278 nghttp: Print error if all connect() syscall faild 2015-06-18 18:03:25 +09:00
Tatsuhiro Tsujikawa
39eb8b8a6b nghttp: Print error when parsing URI failed 2015-06-18 18:00:24 +09:00
Tatsuhiro Tsujikawa
c050fca177 Merge branch 'vapier-master' 2015-06-18 17:55:50 +09:00
Mike Frysinger
19309823aa enable third-party for asio_lib too
Since this library uses the third-party subdir, make sure we auto-enable
it when that lib is turned on.
2015-06-17 13:29:37 -04:00
Tatsuhiro Tsujikawa
90bcdb0dda Merge branch 'libressl' 2015-06-17 18:27:54 +09:00
Tatsuhiro Tsujikawa
17ec30e45c Mention LibreSSL in README.rst 2015-06-17 18:27:27 +09:00
Tatsuhiro Tsujikawa
07f763be49 fetch-ocsp-response: Support LibreSSL, and include port in ocsp_host 2015-06-17 18:24:57 +09:00
Tatsuhiro Tsujikawa
69119f47c4 src: Support compile with LibreSSL 2015-06-17 18:24:51 +09:00
Tatsuhiro Tsujikawa
b0b792e735 integration: Add tests for x-forwarded-proto header field 2015-06-16 21:31:47 +09:00
Tatsuhiro Tsujikawa
8aab74ad36 nghttpx: Refactor a bit 2015-06-16 21:31:33 +09:00
Tatsuhiro Tsujikawa
f418d1239f nghttpx: Fix bug that XFP header always http on HTTP/2 backend
This commit fixes the bug that x-forwarded-proto header field sent on
HTTP/2 backend always "http", regardless of frontend scheme.
2015-06-16 21:29:47 +09:00
Tatsuhiro Tsujikawa
5b51320dc5 nghttpx: Validate :path on SPDY frontend
Unless method is CONNECT, we require that :path starts with "/",
except for OPTIONS method, which can take "*" as :path (server-wide
OPTIONS request).
2015-06-16 00:09:22 +09:00
Tatsuhiro Tsujikawa
d2e81da9e2 Bump up version number to 1.0.3-DEV 2015-06-12 22:58:14 +09:00
Tatsuhiro Tsujikawa
a61054e1f7 Update bash_completion 2015-06-12 22:38:32 +09:00
Tatsuhiro Tsujikawa
749f5d6a32 Update man pages 2015-06-12 22:38:19 +09:00
Tatsuhiro Tsujikawa
f09bd821ac Bump up version number to 1.0.2, LT revision to 14:2:0 2015-06-12 22:35:29 +09:00
Tatsuhiro Tsujikawa
6d5c00b8eb nghttpx: Use vector for WorkerEvent queue 2015-06-12 21:28:24 +09:00
Tatsuhiro Tsujikawa
532bffdb01 nghttpx: Minimize critical section for shared ocsp response 2015-06-12 21:27:12 +09:00
Tatsuhiro Tsujikawa
c6c7145167 Fix compile warning with android NDK 2015-06-12 19:19:53 +09:00
Tatsuhiro Tsujikawa
b5717cd288 Fix bug that data are not consumed for connection in race condition
When we know that stream is closed at time we read DATA frame header,
we use NGHTTP2_IB_IGN_DATA, and consume data for connection if
nghttp2_option_set_no_auto_window_update() is used.  However, if
stream is closed while we are in NGHTTP2_IB_READ_DATA, those bytes are
not consumed for connection, nor notified to application via callback,
so it eventually fills up connection window and connection will
freeze.  This commit fixes this issue by consuming these data for
connection when stream is closed or does not exist.
2015-06-11 23:34:30 +09:00
Tatsuhiro Tsujikawa
d4d7597efb nghttpx: Delete SSL_CTX on quit 2015-06-10 21:31:58 +09:00
Tatsuhiro Tsujikawa
2952706b53 Fix scan-build error 2015-06-10 00:29:03 +09:00
Tatsuhiro Tsujikawa
9b0ccdef34 h2load: Code cleanup 2015-06-10 00:28:27 +09:00
Tatsuhiro Tsujikawa
41dd5f6897 nghttpx: Tokenize request method
We share the same method value with http-parser.  This commit also
returns 501 for unknown request method on HTTP/2 and SPDY frontend.
2015-06-09 23:33:14 +09:00
Tatsuhiro Tsujikawa
f9c60d5e9d nghttpx: Return 501 if invalid method is received on h1 frontend 2015-06-09 22:08:49 +09:00
Tatsuhiro Tsujikawa
c2ca04c1db python: Call on_close callback when connection is lost for server session 2015-06-07 16:17:48 +09:00
Tatsuhiro Tsujikawa
5fbb99e3d0 Check python without python bindings to get PYTHON variable
We use PYTHON variable to execute Python script, mainly to generate
documents.  Therefore it is better to always check python interpreter
even if we don't request python bindings
2015-06-07 13:14:31 +09:00
Tatsuhiro Tsujikawa
ba34313f9f mkapiref.py: Ensure better 2 and 3 support 2015-06-07 13:13:51 +09:00
Tatsuhiro Tsujikawa
aa6699435a make_bash_completion.py: Support Python 3.4 2015-06-07 13:01:02 +09:00
Tatsuhiro Tsujikawa
e857e99df8 help2rst.py: Support Python 3.4 2015-06-07 12:55:22 +09:00
Tatsuhiro Tsujikawa
6d537c419e nghttpx: Document failure case on bind() 2015-06-07 00:05:33 +09:00
Tatsuhiro Tsujikawa
4894e24dc8 nghttpx: Add error logging for listener socket creation failure 2015-06-07 00:02:30 +09:00
Tatsuhiro Tsujikawa
bbbddedb8f Fix compiler warning 2015-06-06 23:37:46 +09:00
Tatsuhiro Tsujikawa
163dfb3150 Fix make distcheck failure 2015-06-06 23:37:31 +09:00
Tatsuhiro Tsujikawa
4f3d20e024 Include script/README.rst in dist 2015-06-06 23:32:32 +09:00
Tatsuhiro Tsujikawa
b7ba1baf48 Translate fetch-ocsp-response into Python 2015-06-06 23:18:32 +09:00
Tatsuhiro Tsujikawa
00efa86fb6 nghttpx: Add --add-request-header option 2015-06-05 23:04:20 +09:00
Tatsuhiro Tsujikawa
43b3640836 Slight code cleanup 2015-06-05 22:06:49 +09:00
Tatsuhiro Tsujikawa
708eb2a217 Increase maximum number of streams in one dep tree including idle nodes 2015-06-05 22:06:14 +09:00
Tatsuhiro Tsujikawa
590a5c3ff3 Fix typo 2015-06-05 00:18:29 +09:00
Tatsuhiro Tsujikawa
28b528dc9e Merge branch 'vapier-master' 2015-06-04 23:45:49 +09:00
Mike Frysinger
a50f6e5d50 configure: fix bashism
The == operator is not in POSIX; use = like normal.

Reported-by: Mikael Magnusson <mikachu@gmail.com>
2015-06-04 00:10:00 -04:00
Tatsuhiro Tsujikawa
1534edd3f3 Update building android doc to include zlib build instruction 2015-06-01 23:14:38 +09:00
Tatsuhiro Tsujikawa
892c159d8f Remove unused clock_gettime and dlsym detection 2015-06-01 23:05:42 +09:00
Tatsuhiro Tsujikawa
0cb4750e3c libevent-client: Fix bug that path is broken if URI does not contain path part 2015-06-01 00:22:35 +09:00
Tatsuhiro Tsujikawa
ee4d53a9e4 More constexpr 2015-05-31 18:44:37 +09:00
Tatsuhiro Tsujikawa
ad150c3ab1 Merge branch 'fwiesel-client_certificate' 2015-05-31 18:28:16 +09:00
Fabian Wiesel
7eafebfeb9 Expose client certificate, if available
Client certificates can use used for authentication/authorization in the server,
so expose them similar to the remote address.
2015-05-31 10:55:10 +02:00
Tatsuhiro Tsujikawa
3d59c6c0b7 nghttpx: Use defined string iteral when defining long_options 2015-05-29 22:48:46 +09:00
Tatsuhiro Tsujikawa
34efc6b7a4 More constexpr 2015-05-29 22:36:05 +09:00
Tatsuhiro Tsujikawa
7582640fd5 nghttpx: Remove unused 2015-05-29 22:20:46 +09:00
Tatsuhiro Tsujikawa
ad265aa9d0 Build third-party if either examples or apps is enabled 2015-05-28 22:55:47 +09:00
Tatsuhiro Tsujikawa
1f7e6ea3fe Define NGHTTP2_EXTERN to __declspec(dllimport) when using nghttp2
The private global variable nghttp2_enable_strict_preface is also
marked as NGHTTP2_EXTERN, but it is test purpose only (test with
.dll), and not part of public API.  It could be removed in the future
release.
2015-05-28 22:36:43 +09:00
Tatsuhiro Tsujikawa
a0a5f4f93e tests: Break if all compressed header input processed in nghttp2_buf 2015-05-27 00:33:24 +09:00
Tatsuhiro Tsujikawa
59e6272ba4 integration: Add WebSocket upgrade test 2015-05-26 23:28:45 +09:00
Tatsuhiro Tsujikawa
323fc8c552 nghttpx: Make WebSocket upgrade work
This commit makes sure that WebSocket upgrade works for HTTP/1.1
frontend and backend pair.  Actually, this implementation probably
supports other upgrade as well, other than HTTP/2 Upgrade, which is
handled specially in other place.
2015-05-26 22:26:17 +09:00
Tatsuhiro Tsujikawa
cbb10aa80f Merge branch 'fwiesel-python3.4-on-macos' 2015-05-26 00:48:42 +09:00
Fabian Wiesel
abe4c7c92a Catch and log failure to set TCP_NODELAY
Setting TCP_NODELAY may fail. Instead of failing the routine, log it and continue.
It seems, that setting TCP_NODELAY in python on Mac OS X is not necessarily supported.
2015-05-25 17:39:54 +02:00
Tatsuhiro Tsujikawa
326b4c467b nghttpx: Fix bug that END_STREAM is not set in backend for POST with Upgrade 2015-05-26 00:00:11 +09:00
Tatsuhiro Tsujikawa
7e51a87111 nghttpx: Don't upgrade to HTTP/2 if we have non-final HTTP/1 response pending 2015-05-25 23:59:44 +09:00
Tatsuhiro Tsujikawa
5fdb36239a nghttpx: Don't send Expect header field twice 2015-05-25 23:59:18 +09:00
Tatsuhiro Tsujikawa
9f99cad9ab Bump up version number to 1.0.2-DEV 2015-05-24 19:50:35 +09:00
Tatsuhiro Tsujikawa
7c7d4700f1 Update README.rst about go spdy package 2015-05-24 19:26:53 +09:00
Tatsuhiro Tsujikawa
8e5c8430f1 Update man pages 2015-05-24 19:21:24 +09:00
Tatsuhiro Tsujikawa
92ecd3c0fb Bump up version number to 1.0.1, LT revision to 14:1:0 2015-05-24 19:11:18 +09:00
Tatsuhiro Tsujikawa
90eac0709d src: Make sure that empty param is error when parsing Link header field 2015-05-24 15:40:16 +09:00
Tatsuhiro Tsujikawa
791660ef8d Fix up OpenSSL initialization
Use the example presented at
http://en.wikibooks.org/wiki/OpenSSL/Initialization
2015-05-23 00:23:38 +09:00
Tatsuhiro Tsujikawa
1c06cfd29f integration: Use our own copy of golang spdy package
Official golang spdy package is done.  We made a copy of it until we
drop spdy support.
2015-05-23 00:01:45 +09:00
Tatsuhiro Tsujikawa
f0379aa428 Fix invalid memory free 2015-05-22 23:36:34 +09:00
Tatsuhiro Tsujikawa
9a0b9428da nghttpx: Fill request scheme in upstream
We may log before filling scheme in Downstream, so we leave
construct_absolute_request_uri as is.
2015-05-22 02:22:59 +09:00
Tatsuhiro Tsujikawa
b20abfc11a nghttpx: Allow HTTP Upgrade from POST request if response header was not sent 2015-05-22 01:59:40 +09:00
Tatsuhiro Tsujikawa
d983dd81ec Update http-parser to 39ff0975c220ef76a2d98c8ac61b0d36f4dce80f 2015-05-22 01:55:47 +09:00
Tatsuhiro Tsujikawa
bcf9e66dbc Update README.rst 2015-05-22 01:40:23 +09:00
Tatsuhiro Tsujikawa
890a10b216 nghttpx: Fix bug that PUSH_PROMISE is sent after associated response HEADERS 2015-05-22 00:53:02 +09:00
Tatsuhiro Tsujikawa
28adb2dad3 h2load: Fix bug that NPN fails if ALPN is enabled 2015-05-22 00:48:32 +09:00
Tatsuhiro Tsujikawa
c795018f29 Dockerfile.android: Update NDK ver, and ubuntu; build and link zlib 2015-05-21 00:45:01 +09:00
Tatsuhiro Tsujikawa
c1a663b577 Don't link zlib bundled with android NDK 2015-05-21 00:15:04 +09:00
Tatsuhiro Tsujikawa
2b450f26ba Comment out uninstall-local for python
This uninstall-local rule is too strong; it could delete unexpected
files, although they are likely nghttp2 related.
2015-05-20 22:50:58 +09:00
Tatsuhiro Tsujikawa
1ddff5bbf9 Include stdint.h instead of inttypes.h when compiled with MSVC < 2013 2015-05-20 22:33:57 +09:00
Tatsuhiro Tsujikawa
3a4c8bc8f1 Document about small write 2015-05-19 22:56:23 +09:00
Tatsuhiro Tsujikawa
fe752174a9 nghttpd: Close connection after settings timeout and GOAWAY was sent 2015-05-18 21:38:12 +09:00
Tatsuhiro Tsujikawa
494ed221b6 Merge branch 'alagoutte-scan-build' 2015-05-16 02:17:28 +09:00
Tatsuhiro Tsujikawa
14f971d71f Merge branch 'scan-build' of https://github.com/alagoutte/nghttp2 into alagoutte-scan-build 2015-05-16 02:15:38 +09:00
Alexis La Goutte
ddee5d3896 fix Value stored to 'rv' is never read found by Clang Analyzer 2015-05-15 18:11:59 +02:00
Tatsuhiro Tsujikawa
447e346b1e Bump up version number to 1.0.1-DEV 2015-05-16 00:25:34 +09:00
Tatsuhiro Tsujikawa
553d741f03 Fix migration version number 2015-05-16 00:15:00 +09:00
Tatsuhiro Tsujikawa
6bd728b3c2 Update man pages 2015-05-16 00:10:41 +09:00
Tatsuhiro Tsujikawa
a99085891a Bump up version number to 1.0.0, LT revision to 14:0:0 2015-05-16 00:03:08 +09:00
Tatsuhiro Tsujikawa
68d3724fad Update README.rst 2015-05-15 23:55:30 +09:00
Tatsuhiro Tsujikawa
fe39ec8697 doc: Update Resources 2015-05-15 23:36:51 +09:00
Tatsuhiro Tsujikawa
c896118747 Fix required spdylay version 2015-05-15 23:32:15 +09:00
Tatsuhiro Tsujikawa
b89140c311 Merge branch 'v1.0.0' 2015-05-15 23:30:59 +09:00
Tatsuhiro Tsujikawa
a869c39a2c Bump up version number to 1.0.0-DEV 2015-05-15 23:30:24 +09:00
Tatsuhiro Tsujikawa
0b27f005e0 Merge branch 'master' into v1.0.0
Conflicts:
	src/HttpServer.cc
2015-05-15 23:24:19 +09:00
Tatsuhiro Tsujikawa
92a20c76e6 Update bash_completion 2015-05-15 23:01:33 +09:00
Tatsuhiro Tsujikawa
42ccea806c Update man pages 2015-05-15 23:01:19 +09:00
Tatsuhiro Tsujikawa
805f36d134 Bump up version number to 0.7.15, LT revision to 13:4:8 2015-05-15 22:59:00 +09:00
Tatsuhiro Tsujikawa
e2c0a3e43b Retry finding jemalloc lib by je_malloc_stats_print
Fixes GH-233
2015-05-15 22:40:49 +09:00
Tatsuhiro Tsujikawa
3572e7c634 inflatehd: Fix crash if 'wire' value is not string
Fixes GH-235
2015-05-15 22:29:57 +09:00
Tatsuhiro Tsujikawa
0479f833fc Revert "nghttpx: Remove last write/read fields for TLS"
This reverts commit 585af93828.
2015-05-15 22:20:15 +09:00
Tatsuhiro Tsujikawa
252aeb43e1 Add test for GH-232 2015-05-15 01:00:09 +09:00
Tatsuhiro Tsujikawa
24fe24b37d Merge branch 'etcimon-patch-1' 2015-05-15 00:57:07 +09:00
Etienne Cimon
32603d7eff Access violation in buffers
When adding a large amount of data that spans to multiple chunks, the pointer is incremented by the wrong value.
2015-05-14 10:45:17 -04:00
Tatsuhiro Tsujikawa
53bfc70c9e Include inttypes.h (or cintypes for C++) instead of stdint.h
From autoconf manual, section 5.6.1 Portability of Headers, says:

"""
The C99 standard says that inttypes.h includes stdint.h, so there's no
need to include stdint.h separately in a standard environment. Some
implementations have inttypes.h but not stdint.h (e.g., Solaris 7),
but we don't know of any implementation that has stdint.h but not
inttypes.h.
"""
2015-05-14 00:17:45 +09:00
Tatsuhiro Tsujikawa
c4068cd404 Fix travis build error
Remove AC_PROG_RANLIB because it is rendered obsolete by LT_INIT.
Remove AC_CHECK_HEADER_STDBOOl, because travis does not have one.
2015-05-13 23:48:31 +09:00
Tatsuhiro Tsujikawa
0aa17f64c1 doc: Remove 'NGHTTP2_EXTERN' from api doc 2015-05-13 23:39:48 +09:00
Tatsuhiro Tsujikawa
38cfc5c47c Check more headers and funcs 2015-05-13 23:29:20 +09:00
Tatsuhiro Tsujikawa
91c8f085ef Update man pages 2015-05-13 00:44:37 +09:00
Tatsuhiro Tsujikawa
5da49989f8 nghttpd: Add --echo-upload option to send back request body 2015-05-13 00:38:28 +09:00
Tatsuhiro Tsujikawa
260131966d help2rst.py: Add comment to tell that this is a generated file 2015-05-12 23:30:17 +09:00
Tatsuhiro Tsujikawa
6862f66c23 Merge branch 'syohex-misspelling' 2015-05-12 23:25:33 +09:00
Tatsuhiro Tsujikawa
2f2a7ace81 Fix corresponding upstream source reported in previous commits accordingly 2015-05-12 23:24:18 +09:00
Syohei YOSHIDA
132719f752 Correct misspellings in document 2015-05-12 10:49:42 +09:00
Tatsuhiro Tsujikawa
64b1aae567 integration: Fix TestH2H1Upgrade test failure 2015-05-08 19:35:09 +09:00
Tatsuhiro Tsujikawa
a8625e15f0 clang-format 2015-05-08 19:24:17 +09:00
Tatsuhiro Tsujikawa
e63d6e490a Merge branch 'master' into v1.0.0
Conflicts:
	lib/nghttp2_option.h
	lib/nghttp2_session.h
	src/HttpServer.cc
2015-05-08 19:21:51 +09:00
Tatsuhiro Tsujikawa
7f60de0c51 Bump up version number to 0.7.15-DEV 2015-05-08 18:36:58 +09:00
Tatsuhiro Tsujikawa
3a46a2c0a4 Update man pages 2015-05-08 17:55:15 +09:00
Tatsuhiro Tsujikawa
fbff101165 Update bash_completion 2015-05-08 17:54:51 +09:00
Tatsuhiro Tsujikawa
526d2c727d Bump up version number to 0.7.14, LT revision to 13:3:8 2015-05-08 17:51:54 +09:00
Tatsuhiro Tsujikawa
6c232da679 Merge branch 'alagoutte-misc' 2015-05-07 23:40:22 +09:00
Alexis La Goutte
1241c951d6 rv is only used in an assert.
The assert only evaluates to code if NDEBUG is undefined. Protect rv and its use accordingly

Issue reported by Joerg Mayer
https://code.wireshark.org/review/8260
2015-05-07 15:20:24 +02:00
Tatsuhiro Tsujikawa
73e79130d1 Update doc 2015-05-07 21:14:21 +09:00
Tatsuhiro Tsujikawa
1a1902350b Update sphinx_rtd_theme 2015-05-07 21:09:57 +09:00
Tatsuhiro Tsujikawa
eec65826cf Update man pages 2015-05-07 20:55:10 +09:00
Tatsuhiro Tsujikawa
fc17c0a618 Fix global-buffer-overflow 2015-05-07 19:37:43 +09:00
Tatsuhiro Tsujikawa
2620992003 Document about time for connect and time for 1st byte in h2load man page 2015-05-07 18:58:32 +09:00
Tatsuhiro Tsujikawa
5a2069b55c Merge branch 'wzyboy-patch-upstart' 2015-05-06 15:56:57 +09:00
Tatsuhiro Tsujikawa
14adcb2d81 Substitute bindir in nghttpx-upstart.conf 2015-05-06 15:56:18 +09:00
Tatsuhiro Tsujikawa
13660edef2 Merge branch 'patch-upstart' of https://github.com/wzyboy/nghttp2 into wzyboy-patch-upstart 2015-05-06 15:54:42 +09:00
Tatsuhiro Tsujikawa
98034286ac Substitute bindir in nghttpx.service 2015-05-06 15:53:12 +09:00
Tatsuhiro Tsujikawa
2a37a28d72 Revert "Substitute bindir for nghttpx.service"
This reverts commit 7bb154f768.
2015-05-06 15:37:56 +09:00
Tatsuhiro Tsujikawa
7bb154f768 Substitute bindir for nghttpx.service
Use static pattern rules to use same recipe for nghttpx-init and
nghttpx.service.

Also rewrite how to produce nghttpx
2015-05-06 12:02:12 +09:00
Zhuoyun Wei
eb96aa261f Add Upstart configuration file 2015-05-06 10:38:24 +08:00
Tatsuhiro Tsujikawa
232d359cbb Add nghttpx.service to distribution 2015-05-06 11:02:51 +09:00
Tatsuhiro Tsujikawa
2d5d9d5d04 nghttpd: Add -m, --max-concurrent-streams option 2015-05-06 10:42:43 +09:00
Tatsuhiro Tsujikawa
7ecca39025 nghttpx: Fix heap-use-after-free bug in http/1 frontend
This is a regression introduced in
4be4d875f3
2015-05-05 23:45:39 +09:00
Tatsuhiro Tsujikawa
bc0190c19f Merge branch 'wzyboy-patch-systemd-service' 2015-05-05 22:37:40 +09:00
Tatsuhiro Tsujikawa
9a162b81f0 Merge branch 'patch-systemd-service' of https://github.com/wzyboy/nghttp2 into wzyboy-patch-systemd-service 2015-05-05 22:37:21 +09:00
Tatsuhiro Tsujikawa
a67a8fabff Merge branch 'wzyboy-patch-logrotate' 2015-05-05 22:36:06 +09:00
Zhuoyun Wei
989d381aab Add systemd service file 2015-05-04 23:56:09 +08:00
Zhuoyun Wei
1d65d82cb5 Improve logrotate configuration file
- Avoid changing file permissions
- Make sure all log files are reopened
- Remove non-sense prerotate script
- Send SIGUSR1 to all nghttpx processes
2015-05-04 23:17:27 +08:00
Tatsuhiro Tsujikawa
4be4d875f3 nghttpx: Log absolute URI for HTTP/2 or client proxy request 2015-05-04 23:24:33 +09:00
Tatsuhiro Tsujikawa
1ab707713f nghttpx: Accept reference instead of pointer by upstream_accesslog 2015-05-04 22:45:34 +09:00
Tatsuhiro Tsujikawa
cc46d363c5 h2load: Refactor statistics hanlding to scale more upcoming new metrics 2015-05-04 22:36:21 +09:00
Tatsuhiro Tsujikawa
fa082cbdd0 Merge branch 'alex-nalivko-include_pull_request' 2015-05-03 16:52:27 +09:00
Tatsuhiro Tsujikawa
016d40ea0f Merge branch 'include_pull_request' of https://github.com/alex-nalivko/nghttp2 into alex-nalivko-include_pull_request 2015-05-03 16:50:52 +09:00
Tatsuhiro Tsujikawa
fe6d065bb4 Merge branch 'ericcarlschwartz-finer_stats' 2015-05-03 16:47:52 +09:00
Tatsuhiro Tsujikawa
b4e8bea4b5 clang-format 2015-05-03 16:47:32 +09:00
Tatsuhiro Tsujikawa
555d5abac9 Merge branch 'finer_stats' of https://github.com/ericcarlschwartz/nghttp2 into ericcarlschwartz-finer_stats 2015-05-03 16:37:02 +09:00
Alex Nalivko
3137dc4a70 h2load_spdy_session errno include 2015-05-02 19:33:04 +00:00
es
4bba4bf66c update h2load to give connect time and ttfb stats
finer statistics for h2load: update per comments from tatsuhiro-t

finer stats for h2load: fixed formatting
2015-05-01 10:30:09 -07:00
Tatsuhiro Tsujikawa
7b3a33a313 README.rst: Fix formatting and remove trailing spaces 2015-05-01 13:29:43 +09:00
Tatsuhiro Tsujikawa
ee52290de7 Merge branch 'brk0v-typo' 2015-05-01 00:41:48 +09:00
Viacheslav Biriukov
8f0899a190 mages to images typo 2015-04-30 18:22:51 +03:00
Tatsuhiro Tsujikawa
f6cfd082c7 Merge branch 'alagoutte-misc' 2015-04-30 18:43:41 +09:00
Tatsuhiro Tsujikawa
9d81be4b35 Merge branch 'misc' of https://github.com/alagoutte/nghttp2 into alagoutte-misc 2015-04-30 18:42:17 +09:00
Alexis La Goutte
a62778d6b0 fix comma at end of enumerator list [-Wpedantic] 2015-04-30 07:49:55 +02:00
Tatsuhiro Tsujikawa
ea612a2dce Merge branch 'nghttpx-headers-size-option' 2015-04-29 22:55:30 +09:00
Tatsuhiro Tsujikawa
026521b097 integration: Add tests for --header-field-buffer and --max-header-fields 2015-04-29 22:54:25 +09:00
Tatsuhiro Tsujikawa
9dc5259593 nghttpx: Take into account request URI in header size in https frontend 2015-04-29 22:23:25 +09:00
Tatsuhiro Tsujikawa
ea8a566d98 nghttpx: Send 431 if header field size exceeded the configuration limit 2015-04-29 21:39:46 +09:00
Tatsuhiro Tsujikawa
8c6f9e899f nghttpx: Enforce header field buffer limit for SPDY frontend 2015-04-29 21:27:36 +09:00
Tatsuhiro Tsujikawa
552f675466 nghttpx: Add --header-field-buffer and --max-header-fields options 2015-04-29 21:10:59 +09:00
Tatsuhiro Tsujikawa
f9a50333d2 Fix doc for nghttp2_select_next_protocol
We have to return this error code to notify OpenSSL that we have not
filled any values in |*out| and |*outlen|.
2015-04-28 23:12:27 +09:00
Tatsuhiro Tsujikawa
de4735092a Fix doc formatting 2015-04-28 23:06:48 +09:00
Tatsuhiro Tsujikawa
1c4df1832b Update doc, mainly for RFC numbers 2015-04-28 23:05:00 +09:00
Tatsuhiro Tsujikawa
1ad1fe6005 Merge branch 'master' into v1.0.0 2015-04-28 22:48:34 +09:00
Tatsuhiro Tsujikawa
f05a4830c5 nghttp: Fix assertion error if very large value is given to -t 2015-04-28 21:51:28 +09:00
Tatsuhiro Tsujikawa
9e1b068a4b Fix bug that promised stream was not reset on decompression error 2015-04-28 21:38:52 +09:00
Tatsuhiro Tsujikawa
54bff91762 Bump up version number to 0.7.14-DEV 2015-04-28 00:01:09 +09:00
Tatsuhiro Tsujikawa
63630690a8 Fix make -j3 distcheck error 2015-04-27 23:52:36 +09:00
Tatsuhiro Tsujikawa
dbc613e0d0 Update man pages 2015-04-27 23:09:00 +09:00
Tatsuhiro Tsujikawa
ee354ee6c8 Bump up version number to 0.7.13, LT revision to 13:2:8 2015-04-27 23:06:14 +09:00
Tatsuhiro Tsujikawa
df707df21b Update man pages 2015-04-27 22:36:34 +09:00
Tatsuhiro Tsujikawa
2436acbd23 Update doc about h2load flow control 2015-04-27 22:36:03 +09:00
Tatsuhiro Tsujikawa
b41835f19b h2load: Effectively disable flow control by setting large window size
Previously h2load used default flow control window as described in
HTTP/2 and SPDY specification.  The window size is 64KiB, which is a
bit small, and cannot utilize full server performance when response
size is not too small.  Basically, we do this kind of benchmarking
test to measure server's throughput, and optimal performance.  Smaller
window certainly degrades performance even in local testing because
server is so fast that it has to wait for WINDOW_UPDATE from h2load.
To make default behaviour suitable for peak performance test, we
decided to disable flow control in h2load by setting large enough
window size.

Most users used h2load without -w or -W options, so they were
implicitly throttled by flow control and the result was affected by
that negatively.  Now flow control is disabled by default, the result
may improve depending on the implementations.
2015-04-27 21:23:01 +09:00
Tatsuhiro Tsujikawa
42b2430fe1 Remove unnecessary assignment to item->cycle 2015-04-26 22:32:54 +09:00
Tatsuhiro Tsujikawa
c8f67788e0 Remove unused local variable 2015-04-26 19:47:14 +09:00
Tatsuhiro Tsujikawa
bbdff112a3 Make huffman decoding slightly faster using evil looking macro 2015-04-26 19:39:33 +09:00
Tatsuhiro Tsujikawa
02468b1ca1 Allocate field name and value in the same buffer if indname to dynamic table 2015-04-26 18:43:24 +09:00
Tatsuhiro Tsujikawa
c41f413978 Fix compile error with --enable-werror 2015-04-25 02:23:01 +09:00
Tatsuhiro Tsujikawa
e38dd37667 Update doc 2015-04-25 01:00:02 +09:00
Tatsuhiro Tsujikawa
f2cf2b625c Replace priority queue with linear queue where possible
After reviewing codebase, only queue for DATA frames requires
priorities.  Other frames can be replaced multiple linear queues.
Replacing priority queue with linear queue allows us to simplify
codebase a bit; for example, now nghttp2_session.next_seq is gone.
2015-04-25 00:56:46 +09:00
Tatsuhiro Tsujikawa
eb05777d88 clang-format 2015-04-24 00:17:13 +09:00
Tatsuhiro Tsujikawa
db4a68454a Merge branch 'master' into v1.0.0
Conflicts:
	lib/includes/nghttp2/nghttp2.h
2015-04-24 00:13:15 +09:00
Tatsuhiro Tsujikawa
6b0b8ea7d5 Update doc 2015-04-24 00:05:10 +09:00
Tatsuhiro Tsujikawa
c925c32233 Fix bug that promised stream is not reset on temporal failure from on_header_callback 2015-04-23 23:57:39 +09:00
Tatsuhiro Tsujikawa
514558afc0 Allow NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE from nghttp2_on_begin_headers_callback
Since application most likely allocates the stream object in
nghttp2_on_begin_headers_callback, it is desirable to handle its
failure as stream error.  But previously it only signals success or
fatal error.  Submitting RST_STREAM does not prevent
nghttp2_on_header_callback from being invoked.  This commit improves
this situation by allowing NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE from
nghttp2_on_begin_headers_callback.  If that value is returned, library
submits RST_STREAM with error code INTERNAL_ERROR, and
nghttp2_on_header_callback and nghttp2_on_frame_recv_callback for that
frame are not invoked.  Note that for PUSH_PROMISE frame, the stream
to be reset is promised stream.
2015-04-23 23:43:30 +09:00
Tatsuhiro Tsujikawa
b9f602b9a2 Update doc 2015-04-23 21:14:09 +09:00
Tatsuhiro Tsujikawa
1a99bcc860 Merge branch 'travis-container' 2015-04-23 00:00:06 +09:00
Tatsuhiro Tsujikawa
6b8aa36c98 travis: Use gcc-4.9 instead of gcc-4.8 2015-04-22 23:59:23 +09:00
Tatsuhiro Tsujikawa
86ddda5c0e tiny-nghttpd: Fix compile error with travis gcc-4.8 2015-04-22 23:59:23 +09:00
Tatsuhiro Tsujikawa
58b7f4a096 Fix inline error with travis gcc-4.8 2015-04-22 23:59:23 +09:00
Tatsuhiro Tsujikawa
4069aab4f7 travis: Attempt to enable gcc 2015-04-22 23:59:23 +09:00
Tatsuhiro Tsujikawa
5595ba643e travis: Use container-based infrastructure 2015-04-22 23:59:23 +09:00
Tatsuhiro Tsujikawa
77c556901c nghttpx: Increase maximum header field set size 2015-04-22 22:27:48 +09:00
Tatsuhiro Tsujikawa
4928959213 asio: Document asynchronous parameter for listen_and_serve 2015-04-22 22:25:16 +09:00
Tatsuhiro Tsujikawa
a200bb1084 Merge branch 'sunxiaoguang-asio_graceful_shutdown' 2015-04-22 21:43:52 +09:00
Xiaoguang Sun
92a1ca5917 Graceful shutdown and joinable server 2015-04-22 17:51:28 +08:00
Tatsuhiro Tsujikawa
97648d257f mkhufftbl.py: Refactor 2015-04-21 23:48:45 +09:00
Tatsuhiro Tsujikawa
5937b4b6f7 Merge branch 'master' into v1.0.0 2015-04-19 23:13:38 +09:00
Tatsuhiro Tsujikawa
787d40129b Bump up version number to 0.7.13-DEV 2015-04-19 18:32:58 +09:00
Tatsuhiro Tsujikawa
91ad7e150e Never indexing still can use header field name in dynamic table 2015-04-19 18:21:26 +09:00
Tatsuhiro Tsujikawa
28bde2cef0 Update bash_completion 2015-04-19 18:11:11 +09:00
Tatsuhiro Tsujikawa
a9b54a1bfa Update man pages 2015-04-19 18:10:54 +09:00
Tatsuhiro Tsujikawa
80f0e99f00 Bump up version number to 0.7.12, LT revision to 13:1:8 2015-04-19 18:07:57 +09:00
Tatsuhiro Tsujikawa
102ea7c0bb nghttpd: Cache fd
Implement fd caching for static files.  The response body for such as
404 was dynamically generated previously, but now it is written in
temporally file and its fd is cached.  Currently, cache is reference
counted and expired when count becomes 0.  This makes caching is not
effective other than "busy" period, but we don't need this feature if
we are not busy.
2015-04-19 17:38:06 +09:00
Tatsuhiro Tsujikawa
85671a69bf Update doc 2015-04-18 16:49:34 +09:00
Tatsuhiro Tsujikawa
a3fa257473 Fix compile error with Android NDK r10d + --enable-werror 2015-04-17 23:46:19 +09:00
Tatsuhiro Tsujikawa
c4e994c97d nghttp: Add --no-push option to disable server push 2015-04-17 23:35:16 +09:00
Tatsuhiro Tsujikawa
0b41e20d54 nghttp: Show stream ID in statistics output 2015-04-17 23:35:16 +09:00
Tatsuhiro Tsujikawa
cfabce6e70 Update man pages 2015-04-17 23:14:23 +09:00
Tatsuhiro Tsujikawa
b948c5457d Specify program directive 2015-04-17 23:13:42 +09:00
Tatsuhiro Tsujikawa
3bdf78e8af Document nghttp's dependency based priority 2015-04-17 23:06:07 +09:00
Tatsuhiro Tsujikawa
436595df98 nghttp: Remove --dep-idle option
In this commit, we made --dep-idle behaviour by default.  This is
because the previous default behaviour is not reflect current usage of
dependency priority and never will be because of fragility of tree due
to stream closure.
2015-04-17 22:24:06 +09:00
Tatsuhiro Tsujikawa
d3561a63b1 nghttp: Depend on "leader" anchor if js is linked inside head element 2015-04-17 21:25:31 +09:00
Tatsuhiro Tsujikawa
1a12a9b397 Penalize cycle according to effective weight 2015-04-17 21:17:22 +09:00
Tatsuhiro Tsujikawa
57644e0256 Effectively revert 03c4092862
This is not mandated by spec.  Also it may work badly with Firefox
style dependency tree usage.
2015-04-17 21:04:17 +09:00
Tatsuhiro Tsujikawa
7323d4c639 Fix bug that nghttp2_session_set_next_stream_id accepts invalid stream_id 2015-04-17 00:12:47 +09:00
Tatsuhiro Tsujikawa
e23225689f nghttp: Use same priority anchor nodes as Firefox does 2015-04-16 23:56:37 +09:00
Tatsuhiro Tsujikawa
e6ad2eb14f We can assert this 2015-04-16 22:58:25 +09:00
Tatsuhiro Tsujikawa
d4a22edeb3 Don't do fancy stuff yet 2015-04-16 22:58:25 +09:00
Tatsuhiro Tsujikawa
8f4e2d941f Revert accidental change in nghttp.cc 2015-04-16 22:58:25 +09:00
Tatsuhiro Tsujikawa
1a8da6caec Update doc 2015-04-16 21:40:39 +09:00
Tatsuhiro Tsujikawa
dc335b9025 Improve weight handling a bit 2015-04-16 21:38:13 +09:00
Tatsuhiro Tsujikawa
93afbc7d2f Rewrite static header table handling
We rewrite static header table handling in nghttp2_hd.c.  We expand
nghttp2_token to include all static header table entries, and fully
use them in header compression and decompression.  The lookup function
is now located in nghttp2_hd.c.  We add new nghttp2_hd_inflate_hd2()
function to export token value for header name, then we pass it to
nghttp2_http_on_header function, so that we don't have to look up
token there.  We carefully set enum value of token to static table
index, so looking up static table is now O(1), assuming we have token.
2015-04-15 23:58:56 +09:00
Tatsuhiro Tsujikawa
82e2c5bd22 Never index authorization and small cookie header field
nghttp2 library now use Literal Header Field never Indexed for
"authorization" header field and small "cookie" header field,
regardless of nghttp2_nv.flags.
2015-04-15 23:58:56 +09:00
Tatsuhiro Tsujikawa
53bcafb39f Merge branch 'cubicdaiya-alloc-error-handling' 2015-04-15 22:45:10 +09:00
Tatsuhiko Kubo
59f8397659 Use nullptr instead of NULL in C++. 2015-04-15 21:18:39 +09:00
Tatsuhiko Kubo
061732adf0 improved malloc error handlings. 2015-04-15 09:20:45 +09:00
Tatsuhiro Tsujikawa
5c2ca28706 asio: client: Call error_cb on error occurred in do_read and do_write
Fixes GH-207
2015-04-13 21:33:43 +09:00
Tatsuhiro Tsujikawa
a8ea86cfe5 src: constexpr 2015-04-12 17:51:23 +09:00
Tatsuhiro Tsujikawa
7451a73def nghttpx: Don't push resource if link header has non empty loadpolicy 2015-04-12 17:42:25 +09:00
Tatsuhiro Tsujikawa
889e705f35 nghttpx: Add logging for somewhat important events (logs, tickets, and ocsp) 2015-04-11 00:08:28 +09:00
Tatsuhiro Tsujikawa
14d4979c54 Don't install libnghttp2_asio headers if they are disabled 2015-04-10 23:11:40 +09:00
Tatsuhiro Tsujikawa
095bc178f3 nghttpx: Robust HTTP/1 backend CL and TE handling
We should ignore Content-Length and Transfer-Encoding for upgraded
response, and reset content-length if this is a non-final response.
2015-04-10 22:30:20 +09:00
Tatsuhiro Tsujikawa
308738025c nghttpx: Don't set response content-length if HTTP/2 response upgraded 2015-04-10 22:24:17 +09:00
Tatsuhiro Tsujikawa
97366bf55c nghttpx: Set content-length after complete request/response headers 2015-04-10 22:10:51 +09:00
Tatsuhiro Tsujikawa
87cadca3d8 integration: Add HTTP Upgrade test 2015-04-10 21:28:12 +09:00
Tatsuhiro Tsujikawa
9803f92e9c nghttpx: Set Downstream to stream user data on HTTP Upgrade to h2 2015-04-10 02:40:09 +09:00
Tatsuhiro Tsujikawa
cbfa021095 Bump up version number to 0.7.12-DEV 2015-04-10 00:38:17 +09:00
Tatsuhiro Tsujikawa
03746884a4 Update man pages 2015-04-10 00:35:00 +09:00
Tatsuhiro Tsujikawa
6ed710adbd Bump up version number to 0.7.11 2015-04-10 00:31:46 +09:00
Tatsuhiro Tsujikawa
44b4cda200 src: Check return value from nghttp2_session_get_stream_user_data 2015-04-10 00:21:31 +09:00
Tatsuhiro Tsujikawa
69a4f3bf42 nghttp: Consider :authority custom header field for SNI 2015-04-10 00:15:01 +09:00
Tatsuhiro Tsujikawa
5334cb5acc Enable PIE in Dockerfile.android too 2015-04-09 23:34:42 +09:00
Tatsuhiro Tsujikawa
6ca24264e4 Enable PIE for Android build 2015-04-09 23:30:12 +09:00
Tatsuhiro Tsujikawa
37a631278f Merge branch 'alagoutte-misc' 2015-04-09 23:27:15 +09:00
Alexis La Goutte
5c42687759 fix comma at end of enumerator list [-Wpedantic] 2015-04-09 15:44:36 +02:00
Tatsuhiro Tsujikawa
b636e9744f Merge branch 'nghttpx-rewrite-ocsp' 2015-04-09 01:06:13 +09:00
Tatsuhiro Tsujikawa
b873930802 nghttpx: Now ocsp works without threads 2015-04-09 01:03:28 +09:00
Tatsuhiro Tsujikawa
bc53c81616 nghttpx: Replace posix_spawn functions with fork + dup2 + execve
Although posx_spawn is very convenient and useful, we have platform
which don't have these functions (e.g., Android NDK r10d).
2015-04-09 01:03:28 +09:00
Tatsuhiro Tsujikawa
09c485e712 nghttpx: Eliminate 1 second refresh timer 2015-04-09 01:03:28 +09:00
Tatsuhiro Tsujikawa
d247470da2 nghttpx: Rewrite ocsp without thread
Since libev handles SIGCHLD, using waitpid in separate thread to wait
for the completion of fetch-ocsp-response script process is undefined.
This commit rewrite ocsp handling code so that it utilizes libev
ev_child watcher and perform ocsp update without thread.
2015-04-09 01:03:28 +09:00
Tatsuhiro Tsujikawa
90bfea77e0 doc: Remove nghttp2_submit_altsvc.rst 2015-04-08 18:12:54 +09:00
Tatsuhiro Tsujikawa
cf0576253f Merge branch 'master' into v1.0.0 2015-04-08 18:10:04 +09:00
Tatsuhiro Tsujikawa
4aca2f0b59 Bump up version number to 0.7.11-DEV 2015-04-08 18:07:38 +09:00
Tatsuhiro Tsujikawa
9d711f65f7 Fix make distcheck 2015-04-08 17:55:23 +09:00
Tatsuhiro Tsujikawa
0eab08a7cf Update bash_completion files 2015-04-08 17:38:55 +09:00
Tatsuhiro Tsujikawa
b9c4757d21 Update man pages 2015-04-08 17:36:12 +09:00
Tatsuhiro Tsujikawa
1fcd881395 nghttpx: Document that stderr is redirected to error log file 2015-04-08 17:33:18 +09:00
Tatsuhiro Tsujikawa
cd0564ddfa Bump up version number to 0.7.10, LT revision to 13:0:8 2015-04-08 17:21:40 +09:00
Tatsuhiro Tsujikawa
dd435b51ab nghttpx: Redirect stderr to errorlog file 2015-04-08 16:59:58 +09:00
Tatsuhiro Tsujikawa
ff60cc6b71 integration: Don't send Link header field for resource under /css/ 2015-04-08 16:09:02 +09:00
Tatsuhiro Tsujikawa
80743ddc7b nghttpx: Set promised Downstream as nghttp2 stream user data 2015-04-08 16:07:53 +09:00
Tatsuhiro Tsujikawa
36a8f24559 nghttpx: Finish incomplete incoming request with END_STREAM flag
Previously we send RST_STREAM when we send DATA with END_STREAM flag
set.  With this commit, we also do this when we send HEADERS with
END_STREAM flag set.
2015-04-08 16:07:13 +09:00
Tatsuhiro Tsujikawa
b25e19e876 nghttpx: HTTP backend: Check parser error first so that we can get error msg 2015-04-08 14:39:27 +09:00
Tatsuhiro Tsujikawa
e9660c3558 nghttpx: Fix heap-use-after-free
The bug was introduced by 8c3b379b66.
2015-04-08 13:43:57 +09:00
Tatsuhiro Tsujikawa
8c3b379b66 Pool Memchunk per worker 2015-04-08 00:10:48 +09:00
Tatsuhiro Tsujikawa
b2bb6f1db1 Fix android NDK build error 2015-04-07 21:25:05 +09:00
Tatsuhiro Tsujikawa
59e3783f3f Update manual entry 2015-04-07 00:19:57 +09:00
Tatsuhiro Tsujikawa
d56ecd7414 Add nghttp2_session_consume_{connection,stream} to consume bytes independently
The existing nghttp2_session_consume() affects both connection and
stream level flow control windows.  The new functions only affects
either connection or stream.  There is some interesting use cases.
For example, we may want to pause a stream by not sending
WINDOW_UPDATE, meanwhile we want to continue to process other streams.
In this case, we use nghttp2_session_consume_connection() to tell
library that only connection level window is recovered.  The relevant
discussion: https://code.google.com/p/chromium/issues/detail?id=473259
2015-04-07 00:14:18 +09:00
Tatsuhiro Tsujikawa
ef4e39be55 Update doc 2015-04-06 23:57:48 +09:00
Tatsuhiro Tsujikawa
d42f31ca78 nghttpx: Fix bug that data buffered in SSL object are not read
This is same issue described in https://github.com/h2o/h2o/issues/268.
That is if SSL object has decrypted data buffered inside it, and
application does not read it for some reason (e.g., rate limit), we
have to check the existence of data using SSL_pending.  This is
because buffered data inside SSL is not notified by io watcher.  It is
obvious, but we totally missed it.

nghttpx code normally reads everything until SSL_read returns error
(want-read).  But if rate limit is involved, we stop reading early.
Also in HTTP/1 code, while processing one request, we just read until
buffer is filled up.  In these cases, we may suffer from this problem.

This commit fixes this problem, by performing SSL_pending() and if it
has buffered data and read io watcher is enabled, we feed event using
ev_feed_event().
2015-04-06 22:31:36 +09:00
Tatsuhiro Tsujikawa
084e4487ed Add migration section 2015-04-05 23:53:19 +09:00
Tatsuhiro Tsujikawa
24897aa50d Update README.rst 2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa
3e50ef439d Announce h2, final HTTP/2 ALPN identifier 2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa
87602e5d72 Use NGHTTP2_PROTOCOL_ERROR for NGHTTP2_ERR_HTTP_{HEADER,MESSAGING} 2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa
d0c27d5229 Send 24 bytes client magic byte string by library
Previously nghttp2_session_send() and nghttp2_session_mem_send() did
not send 24 bytes client magic byte string (MAGIC).  We made
nghttp2_session_recv() and nghttp2_session_mem_recv() process MAGIC by
default, so it is natural to make library send MAGIC as well.  This
commit makes nghttp2_session_send() and nghttp2_session_mem_send()
send MAGIC.  This commit also replace "connection preface" with
"client magic", since we call MAGIC as "connection preface" but it is
just a part of connection preface.  NGHTTP2_CLIENT_CONNECTION_PREFACE
macro was replaced with NGHTTP2_CLIENT_MAGIC.  The already deprecated
NGHTTP2_CLIENT_CONNECTION_HEADER macro was removed permanently.
nghttp2_option_set_no_recv_client_preface() was renamed as
nghttp2_option_set_no_recv_client_magic().  NGHTTP2_ERR_BAD_PREFACE
was renamed as NGHTTP2_ERR_BAD_CLIENT_MAGIC.
2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa
ebf214c8fc nghttp2_on_invalid_frame_recv_callback should have lib_error_code as param
nghttp2_error_code is HTTP/2 standard error code and is too coarse to
know what's going on.
2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa
250ea53e4b Deal with 24 bytes client connection preface by default
Since HTTP/2 spec requires for client to send connection preface, it
is reasonable to make this option enabled by default.  It is still a
use case to disable this, so replace this option with
nghttp2_option_set_no_recv_client_preface().
2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa
01af6ea70c Remove ALTSVC related code
HTTP/2 and HPACK are going to be published as RFC, but ALTSVC is still
in draft state.  To make our API stable, it would be better to remove
ALTSVC API for 1.0.0 release.
2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa
7522d50d1a nghttpd, tiny-nghttpd: No need to check existence of stream
The stream existence is guaranteed by library as of
cc03a12b75.
2015-04-05 23:13:29 +09:00
Tatsuhiro Tsujikawa
cc03a12b75 Don't call nghttp2_send_data_callback if stream has already closed
This is more inline with other callback function invocations where if
stream was closed, they are not invoked.
2015-04-05 12:40:21 +09:00
Tatsuhiro Tsujikawa
9eff511c5e Add nghttp2_send_data_callback to send DATA payload without copying
To avoid buffer copy in nghttp2_data_source_read_callback, this commit
introduces NGHTTP2_DATA_FLAG_NO_COPY and nghttp2_send_data_callback.
By using NGHTTP2_DATA_FLAG_NO_COPY in
nghttp2_data_source_read_callback, application can avoid to copy
application data to given buffer.  Instead, application has to
implement nghttp2_send_data_callback to send complete DATA frame by
itself.  We see noticeable performance increase in nghttpd and
tiny-nghttpd using this new feature.  On the other hand, nghttpx does
not show such difference, probably because buffer copy is not
bottleneck.  Using nghttp2_send_data_callback adds complexity, so it
is recommended to measure the performance to see whether this extra
complexity worth it.
2015-04-04 21:23:50 +09:00
Tatsuhiro Tsujikawa
a96ac6f0a0 Merge branch 'remoe-patch-2' 2015-04-04 01:05:02 +09:00
Tatsuhiro Tsujikawa
213a63d97d Merge branch 'patch-2' of https://github.com/remoe/nghttp2 into remoe-patch-2 2015-04-04 01:04:28 +09:00
Tatsuhiro Tsujikawa
8d4548b9c1 Merge branch 'remoe-patch-1' 2015-04-04 01:03:33 +09:00
Tatsuhiro Tsujikawa
44f2e6ae1d Merge branch 'patch-1' of https://github.com/remoe/nghttp2 into remoe-patch-1 2015-04-04 01:02:52 +09:00
Tatsuhiro Tsujikawa
0cd7d268f3 python: Update url 2015-04-03 21:10:11 +09:00
Remo E
f3a9041851 MSVC: remove of winsock dependency 2015-04-03 12:00:06 +02:00
Remo E
776a8c64f6 "static inline" fix for build with VS2013
"static inline" doesn't build on VS2013:

https://msdn.microsoft.com/en-us/library/z8y1yy88.aspx
2015-04-03 11:55:57 +02:00
Tatsuhiro Tsujikawa
524a1f9498 Update sphinx_rtd_theme 2015-04-01 23:11:07 +09:00
Tatsuhiro Tsujikawa
28cfae162a Update doc 2015-04-01 23:10:01 +09:00
Tatsuhiro Tsujikawa
b0123448a4 python: Add async body generation support 2015-04-01 22:54:31 +09:00
Tatsuhiro Tsujikawa
2d15dca096 Merge branch 'alagoutte-scan-build' 2015-04-01 22:53:56 +09:00
Alexis La Goutte
5f05135d1b Fix some "Value stored to 'stream' is never read" found by Clang Analyzer 2015-04-01 13:03:22 +02:00
Alexis La Goutte
3b6b4ff066 Fix Value stored to 'rv' is never read found by Clang Analyzer 2015-04-01 13:03:22 +02:00
Tatsuhiro Tsujikawa
0c8ec7bfa6 Make sure that nghttp2 license is MIT license 2015-04-01 19:41:32 +09:00
Tatsuhiro Tsujikawa
2c05b8d6f0 Update doc 2015-04-01 01:26:21 +09:00
Tatsuhiro Tsujikawa
45c4187d8f doc: Update .gitignore 2015-04-01 01:19:08 +09:00
Tatsuhiro Tsujikawa
87029e05af doc: Split API reference into smaller fine grained files
Previously API reference is gigantic one rst file and it is a bit hard
to use, especially when browsing similar functions.  This commit
splits API reference into smaller fine grained files.  The macros,
enums, types are now in its own file.  Each API function has its own
file now.  API reference doc is now index to above documentation
files.  The apiref-header.rst is renamed as programmers-guide.rst and
becomes standalone document.
2015-04-01 01:13:10 +09:00
Tatsuhiro Tsujikawa
363914c3f7 Mention OCSP stapling in doc 2015-03-31 23:31:24 +09:00
Tatsuhiro Tsujikawa
1316065c14 python: Fix pseudo-header field ordering bug 2015-03-31 21:53:13 +09:00
Tatsuhiro Tsujikawa
2b6a181bef Dockerfile.android: Update openssl to 1.0.2a 2015-03-31 21:36:53 +09:00
Tatsuhiro Tsujikawa
bf68df9ef4 Merge branch 'wzyboy-patch-dockerfile' 2015-03-31 21:35:32 +09:00
Tatsuhiro Tsujikawa
e7f6089b0e Merge branch 'patch-dockerfile' of https://github.com/wzyboy/nghttp2 into wzyboy-patch-dockerfile 2015-03-31 21:35:10 +09:00
Tatsuhiro Tsujikawa
a1500b0ee3 rst document specific corrections 2015-03-31 21:32:25 +09:00
Tatsuhiro Tsujikawa
14001052f8 Merge branch 'fangdingjun-master' 2015-03-31 21:27:18 +09:00
Tatsuhiro Tsujikawa
95ab54c79d Merge branch 'master' of https://github.com/fangdingjun/nghttp2 into fangdingjun-master 2015-03-31 21:26:46 +09:00
Zhuoyun Wei
5e84f767f0 Improve Dockerfile
- Tell Vim this is a Dockerfile to enable syntax highlight;
- Explicity use Ubuntu "Trusty";
- Remove downloaded file to save space;
- Chain up some RUN commands to generate fewer layers.
2015-03-31 14:21:56 +08:00
Dingjun
c47855085b Update README.rst
fix the typo and add the missing command in sample command
2015-03-31 10:02:22 +08:00
Tatsuhiro Tsujikawa
1442b1bd0a nghttpx: Remove --tls-ctx-per-worker option
--tls-ctx-per-worker option does not work well of OCSP stapling.  Also
it makes session ID useless.
2015-03-31 00:42:21 +09:00
Tatsuhiro Tsujikawa
763293a050 Update man pages 2015-03-31 00:23:12 +09:00
Tatsuhiro Tsujikawa
cc94632b29 src: Use separator "--" to mark start of the footer without ambiguity 2015-03-31 00:21:52 +09:00
Tatsuhiro Tsujikawa
5df770b9c1 h2load: Fix compile error with Android NDK 2015-03-30 23:59:03 +09:00
Tatsuhiro Tsujikawa
4bc9afe20a nghttpx: Add OCSP stapling feature 2015-03-30 23:58:28 +09:00
Dingjun
522faeb24f Update README.rst 2015-03-30 18:39:07 +08:00
fangdingjun
362ff09183 add build notes for windows user under Mingw and Cygwin 2015-03-30 18:29:10 +08:00
Tatsuhiro Tsujikawa
ccea4d42b5 Refactor .gitignore files 2015-03-29 18:40:37 +09:00
Tatsuhiro Tsujikawa
ebbe065716 Update .gitignore 2015-03-29 18:23:55 +09:00
Tatsuhiro Tsujikawa
3a97f21383 Reorder fields 2015-03-29 18:10:38 +09:00
Tatsuhiro Tsujikawa
12ced1cddc nghttpx: Add flag to track connection state in HTTP/1 backend 2015-03-29 01:47:22 +09:00
Tatsuhiro Tsujikawa
3576f20e5a nghttpx: Revert part of 6f58434d89
The reverted part of the change may use not connected socket in HTTP/1
backend.
2015-03-29 01:32:27 +09:00
Tatsuhiro Tsujikawa
7ae6e6b4c5 Exclude num_idle_streams when counting active stream 2015-03-29 00:59:15 +09:00
Tatsuhiro Tsujikawa
a2486daee1 nghttpd: Rename Http2Handler::on_connect as connection_made 2015-03-28 20:21:12 +09:00
Tatsuhiro Tsujikawa
8bf440b89c nghttpx: Rename Http2Session::on_connect as connection_made 2015-03-28 20:19:17 +09:00
Tatsuhiro Tsujikawa
e9cdb9c896 h2load: Remove unused fields in Client class 2015-03-28 20:17:30 +09:00
Tatsuhiro Tsujikawa
c4804ee50b h2load: Remove Client::noop 2015-03-28 20:14:12 +09:00
Tatsuhiro Tsujikawa
95cb284e27 h2load: Rename Client::on_connect as connection_made 2015-03-28 20:13:37 +09:00
Tatsuhiro Tsujikawa
c4ccc376df nghttp: Refactor function names
on_SOMETHING should be used only for I/O callback functions
2015-03-28 20:07:12 +09:00
Tatsuhiro Tsujikawa
6133110386 Remove dependency on libws2_32 on Windows build 2015-03-28 19:58:44 +09:00
Tatsuhiro Tsujikawa
6f58434d89 nghttpx, h2load: Perform write whenever read succeeds 2015-03-28 19:13:14 +09:00
Tatsuhiro Tsujikawa
3fd5d0af79 Don't consider num_active_streams in nghttp2_session_want_write() 2015-03-28 19:00:24 +09:00
Tatsuhiro Tsujikawa
1a6855ea7d Merge branch 'remoe-fix/win_build' 2015-03-28 18:41:03 +09:00
remoe
0312521ac9 - source file list updated
- zlib removed
- build of .def files removed
2015-03-27 21:54:44 +01:00
Tatsuhiro Tsujikawa
67b0e0c2d6 Fix "redefine WIN32" bug 2015-03-28 02:16:37 +09:00
Tatsuhiro Tsujikawa
966e3a1308 Define NGHTTP2_EXTERN macro to export function for Windows build 2015-03-28 01:58:59 +09:00
Tatsuhiro Tsujikawa
fd8f8e2708 Bump up version number to 0.7.10-DEV 2015-03-27 01:06:42 +09:00
271 changed files with 24998 additions and 7733 deletions

58
.gitignore vendored
View File

@@ -1,14 +1,19 @@
# emacs backup file
*~
*.o
*.lo
# autotools
*.la
depcomp
*.lo
*.m4
*.o
*.pyc
.deps/
.libs/
INSTALL
Makefile
Makefile.in
libtool
missing
autom4te.cache/
compile
config.guess
config.h
config.h.in
@@ -16,36 +21,21 @@ config.log
config.status
config.sub
configure
depcomp
install-sh
.deps/
.libs
lib/includes/nghttp2/nghttp2ver.h
lib/libnghttp2.pc
src/libnghttp2_asio.pc
libtool
ltmain.sh
missing
stamp-h1
.deps/
INSTALL
.DS_STORE
compile
test-driver
.dirstamp
doc/index.rst
doc/nghttp2.h.rst
doc/nghttp2ver.h.rst
doc/package_README.rst
doc/tutorial-client.rst
doc/tutorial-server.rst
doc/nghttpx-howto.rst
doc/h2load-howto.rst
doc/tutorial-hpack.rst
doc/python-apiref.rst
doc/building-android-binary.rst
doc/asio_http2.h.rst
doc/asio_http2_server.h.rst
doc/asio_http2_client.h.rst
doc/libnghttp2_asio.rst
doc/contribute.rst
python/setup.py
python/dist
python/MANIFEST
# test logs generated by `make check`
*.log
*.trs
lib/MSVC_obj/
_VC_ROOT/
.depend.MSVC
*.pyd
*.egg-info/
python/nghttp2.c

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "third-party/mruby"]
path = third-party/mruby
url = https://github.com/mruby/mruby

View File

@@ -1,37 +1,38 @@
language: cpp
compiler:
- clang
#Disable gcc build for the moment...
# - gcc
- gcc
sudo: false
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.9
- libstdc++-4.9-dev
- autoconf
- automake
- autotools-dev
- libtool
- pkg-config
- zlib1g-dev
- libcunit1-dev
- libssl-dev
- libxml2-dev
- libev-dev
- libevent-dev
- libjansson-dev
- libjemalloc-dev
before_install:
- $CC --version
- sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test
- sudo apt-get update -qq
#Install and use gcc-4.8 (don't build with gcc-4.6)
#libstdc++-4.8 is needed by Clang to build too
- sudo apt-get -qq install g++-4.8 libstdc++-4.8-dev
- >
sudo apt-get install --no-install-recommends -qq
autoconf
automake
autotools-dev
libtool
pkg-config
zlib1g-dev
libcunit1-dev
libssl-dev
libxml2-dev
libev-dev
libevent-dev
libjansson-dev
libjemalloc-dev
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
- $CC --version
before_script:
- autoreconf -i
- automake
- autoconf
- ./configure --enable-werror
- git submodule update --init
- ./configure --enable-werror --with-mruby
script:
- make
- make check

18
CONTRIBUTION Normal file
View File

@@ -0,0 +1,18 @@
[The text below 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.
When changing existing source code, you do not alter the copyright of
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).
By submitting a patch to the nghttp2 project, you are assumed to have
the right to the code and to be allowed by your employer or whatever
to hand over that patch/code to us. We will credit you for your
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!

19
COPYING
View File

@@ -20,22 +20,3 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
[The text below 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.
When changing existing source code, you do not alter the copyright of
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).
By submitting a patch to the nghttp2 project, you are assumed to have
the right to the code and to be allowed by your employer or whatever
to hand over that patch/code to us. We will credit you for your
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!

View File

@@ -1,3 +1,4 @@
# vim: ft=dockerfile:
# Dockerfile to build nghttp2 android binary
#
# $ sudo docker build -t nghttp2-android - < Dockerfile.android
@@ -9,7 +10,7 @@
#
# $ sudo docker run -v /path/to/dest:/out nghttp2-android cp /root/build/nghttp2/src/nghttpx /out
FROM ubuntu
FROM ubuntu:vivid
MAINTAINER Tatsuhiro Tsujikawa
@@ -29,11 +30,12 @@ RUN apt-get install -y make binutils autoconf automake autotools-dev libtool \
genisoimage libc6-i386 lib32stdc++6
WORKDIR /root/build
RUN curl -L -O http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86_64.bin
RUN chmod a+x android-ndk-r10c-linux-x86_64.bin
RUN ./android-ndk-r10c-linux-x86_64.bin
RUN curl -L -O http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin && \
chmod a+x android-ndk-r10d-linux-x86_64.bin && \
./android-ndk-r10d-linux-x86_64.bin && \
rm android-ndk-r10d-linux-x86_64.bin
WORKDIR /root/build/android-ndk-r10c
WORKDIR /root/build/android-ndk-r10d
RUN /bin/bash build/tools/make-standalone-toolchain.sh \
--install-dir=$ANDROID_HOME/toolchain \
--toolchain=arm-linux-androideabi-4.9 --llvm-version=3.5 \
@@ -57,20 +59,24 @@ RUN autoreconf -i && \
make install
WORKDIR /root/build
RUN curl -L -O https://www.openssl.org/source/openssl-1.0.1j.tar.gz
RUN tar xf openssl-1.0.1j.tar.gz
WORKDIR /root/build/openssl-1.0.1j
RUN curl -L -O https://www.openssl.org/source/openssl-1.0.2a.tar.gz && \
tar xf openssl-1.0.2a.tar.gz && \
rm openssl-1.0.2a.tar.gz
WORKDIR /root/build/openssl-1.0.2a
RUN export CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi- && \
./Configure --prefix=$PREFIX android && \
make && make install_sw
WORKDIR /root/build
RUN curl -L -O http://dist.schmorp.de/libev/libev-4.19.tar.gz
RUN curl -L -O https://gist.github.com/tatsuhiro-t/48c45f08950f587180ed/raw/80a8f003b5d1091eae497c5995bbaa68096e739b/libev-4.19-android.patch
RUN tar xf libev-4.19.tar.gz
RUN curl -L -O http://dist.schmorp.de/libev/libev-4.19.tar.gz && \
curl -L -O https://gist.github.com/tatsuhiro-t/48c45f08950f587180ed/raw/80a8f003b5d1091eae497c5995bbaa68096e739b/libev-4.19-android.patch && \
tar xf libev-4.19.tar.gz && \
rm libev-4.19.tar.gz
WORKDIR /root/build/libev-4.19
RUN patch -p1 < ../libev-4.19-android.patch
RUN ./configure \
RUN patch -p1 < ../libev-4.19-android.patch && \
./configure \
--host=arm-linux-androideabi \
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
--prefix=$PREFIX \
@@ -80,6 +86,25 @@ RUN ./configure \
LDFLAGS=-L$PREFIX/lib && \
make install
WORKDIR /root/build
RUN curl -L -O http://zlib.net/zlib-1.2.8.tar.gz && \
tar xf zlib-1.2.8.tar.gz && \
rm zlib-1.2.8.tar.gz
WORKDIR /root/build/zlib-1.2.8
RUN HOST=arm-linux-androideabi \
CC=$HOST-gcc \
AR=$HOST-ar \
LD=$HOST-ld \
RANLIB=$HOST-ranlib \
STRIP=$HOST-strip \
./configure \
--prefix=$PREFIX \
--libdir=$PREFIX/lib \
--includedir=$PREFIX/include \
--static && \
make install
WORKDIR /root/build
RUN git clone https://github.com/tatsuhiro-t/nghttp2
WORKDIR /root/build/nghttp2
@@ -95,9 +120,9 @@ RUN autoreconf -i && \
--disable-threads \
LIBSPDYLAY_CFLAGS=-I$PREFIX/usr/local/include \
LIBSPDYLAY_LIBS="-L$PREFIX/usr/local/lib -lspdylay" \
CPPFLAGS="-I$PREFIX/include" \
CPPFLAGS="-fPIE -I$PREFIX/include" \
CXXFLAGS="-fno-strict-aliasing" \
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
LDFLAGS="-L$PREFIX/lib" && \
LDFLAGS="-fPIE -pie -L$PREFIX/lib" && \
make && \
arm-linux-androideabi-strip src/nghttpx src/nghttpd src/nghttp

View File

@@ -21,7 +21,12 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SUBDIRS = lib third-party src examples python tests integration-tests \
doc contrib
doc contrib script
# Now with python setuptools, make uninstall will leave many files we
# cannot easily remove (e.g., easy-install.pth). Disable it for
# distcheck rule.
AM_DISTCHECK_CONFIGURE_FLAGS = --disable-python-bindings
ACLOCAL_AMFLAGS = -I m4

View File

@@ -13,26 +13,18 @@ An HPACK encoder and decoder are available as a public API.
An experimental high level C++ library is also available.
We have Python bindings of this libary, but we do not have full
We have Python bindings of this library, but we do not have full
code coverage yet.
Development Status
------------------
We started to implement h2-14
(http://tools.ietf.org/html/draft-ietf-httpbis-http2-14), and header
compression
(http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09).
We have implemented `RFC 7540 <https://tools.ietf.org/html/rfc7540>`_
HTTP/2 and `RFC 7541 <https://tools.ietf.org/html/rfc7541>`_ HPACK -
Header Compression for HTTP/2
The nghttp2 code base was forked from the spdylay project.
=========================== =======
HTTP/2 Features Support
=========================== =======
Core frames handling Yes
Dependency Tree Yes
Large header (CONTINUATION) Yes
=========================== =======
The nghttp2 code base was forked from the spdylay
(https://github.com/tatsuhiro-t/spdylay) project.
Public Test Server
------------------
@@ -46,9 +38,9 @@ implementation.
and ``http/1.1`` via ALPN/NPN and requires TLSv1.2 for HTTP/2
connection.
* http://nghttp2.org/ (Upgrade / Direct)
* http://nghttp2.org/ (HTTP Upgrade and HTTP/2 Direct)
``h2c-14`` and ``http/1.1``.
``h2c`` and ``http/1.1``.
Requirements
------------
@@ -75,11 +67,13 @@ required:
* zlib >= 1.2.3
ALPN support requires OpenSSL >= 1.0.2 (released 22 January 2015).
LibreSSL >= 2.2.0 can be used instead of OpenSSL, but OpenSSL has more
features than LibreSSL at the time of this writing.
To enable the SPDY protocol in the application program ``nghttpx`` and
``h2load``, the following package is required:
* spdylay >= 1.3.0
* spdylay >= 1.3.2
To enable ``-a`` option (getting linked assets from the downloaded
resource) in ``nghttp``, the following package is required:
@@ -108,16 +102,31 @@ The Python bindings require the following packages:
* cython >= 0.19
* python >= 2.7
* python-setuptools
If you are using Ubuntu 14.04 LTS (trusty), run the following to install the needed packages::
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
libjemalloc-dev cython python3.4-dev python-setuptools
spdylay is not packaged in Ubuntu, so you need to build it yourself:
http://tatsuhiro-t.github.io/spdylay/
To enable mruby support for nghttpx, `mruby
<https://github.com/mruby/mruby>`_ is required. We need to build
mruby with C++ ABI explicitly turned on, and probably need other
mrgems, mruby is manged by git submodule under third-party/mruby
directory. Currently, mruby support for nghttpx is disabled by
default. To enable mruby support, use ``--with-mruby`` configure
option. Note that at the time of this writing, libmruby-dev and mruby
packages in Debian/Ubuntu are not usable for nghttp2, since they do
not enable C++ ABI. To build mruby, the following packages are
required:
* ruby
* bison
Building from git
-----------------
@@ -132,6 +141,12 @@ used::
To compile the source code, gcc >= 4.8.3 or clang >= 3.4 is required.
.. note::
To enable mruby support in nghttpx, run ``git submodule update
--init`` before running configure script, and use ``--with-mruby``
configure option.
.. note::
Mac OS X users may need the ``--disable-threads`` configure option to
@@ -139,6 +154,33 @@ To compile the source code, gcc >= 4.8.3 or clang >= 3.4 is required.
them from crashing. A patch is welcome to make multi threading work
on Mac OS X platform.
Notes for building on Windows (Mingw/Cygwin)
--------------------------------------------
Under Mingw environment, you can only compile the library, it's
``libnghttp2-X.dll`` and ``libnghttp2.a``.
If you want to compile the applications(``h2load``, ``nghttp``,
``nghttpx``, ``nghttpd``), you need to use the Cygwin environment.
Under Cygwin environment, to compile the applications you need to
compile and install the libev first.
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::
$ export CFLAGS="-U__STRICT_ANSI__ -I$libev_PREFIX/include -L$libev_PREFIX/lib"
$ export CXXFLAGS=$CFLAGS
$ ./configure
$ make
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.
Building the documentation
--------------------------
@@ -160,7 +202,7 @@ https://nghttp2.org/documentation/
Unit tests
----------
Unit tests are done by simply running `make check`.
Unit tests are done by simply running ``make check``.
Integration tests
-----------------
@@ -171,7 +213,8 @@ its testing framework. We depend on the following libraries:
* https://github.com/bradfitz/http2
* https://github.com/tatsuhiro-t/go-nghttp2
* https://golang.org/x/net/spdy
* https://github.com/tatsuhiro-t/spdy
* golang.org/x/net/websocket
To download the above packages, after settings ``GOPATH``, run the
following command under ``integration-tests`` directory::
@@ -185,6 +228,109 @@ To run the tests, run the following command under
Inside the tests, we use port 3009 to run the test subject server.
.. note::
github.com/tatsuhiro-t/spdy is a copy used to be available at
golang.org/x/net/spdy, but it is now gone.
Migration from v0.7.15 or earlier
---------------------------------
nghttp2 v1.0.0 introduced several backward incompatible changes. In
this section, we describe these changes and how to migrate to v1.0.0.
ALPN protocol ID is now ``h2`` and ``h2c``
++++++++++++++++++++++++++++++++++++++++++
Previously we announced ``h2-14`` and ``h2c-14``. v1.0.0 implements
final protocol version, and we changed ALPN ID to ``h2`` and ``h2c``.
The macros ``NGHTTP2_PROTO_VERSION_ID``,
``NGHTTP2_PROTO_VERSION_ID_LEN``,
``NGHTTP2_CLEARTEXT_PROTO_VERSION_ID``, and
``NGHTTP2_CLEARTEXT_PROTO_VERSION_ID_LEN`` have been updated to
reflect this change.
Basically, existing applications do not have to do anything, just
recompiling is enough for this change.
Use word "client magic" where we use "client connection preface"
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
We use "client connection preface" to mean first 24 bytes of client
connection preface. This is technically not correct, since client
connection preface is composed of 24 bytes client magic byte string
followed by SETTINGS frame. For clarification, we call "client magic"
for this 24 bytes byte string and updated API.
* ``NGHTTP2_CLIENT_CONNECTION_PREFACE`` was replaced with
``NGHTTP2_CLIENT_MAGIC``.
* ``NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN`` was replaced with
``NGHTTP2_CLIENT_MAGIC_LEN``.
* ``NGHTTP2_BAD_PREFACE`` was renamed as ``NGHTTP2_BAD_CLIENT_MAGIC``
The alreay deprecated ``NGHTTP2_CLIENT_CONNECTION_HEADER`` and
``NGHTTP2_CLIENT_CONNECTION_HEADER_LEN`` were removed.
If application uses these macros, just replace old ones with new ones.
Since v1.0.0, client magic is sent by library (see next subsection),
so client application may just remove these macro use.
Client magic is sent by library
+++++++++++++++++++++++++++++++
Previously nghttp2 library did not send client magic, which is first
24 bytes byte string of client connection preface, and client
applications have to send it by themselves. Since v1.0.0, client
magic is sent by library via first call of ``nghttp2_session_send()``
or ``nghttp2_session_mem_send()``.
The client applications which send client magic must remove the
relevant code.
Remove HTTP Alternative Services (Alt-Svc) related code
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alt-Svc specification is not finalized yet. To make our API stable,
we have decided to remove all Alt-Svc related API from nghttp2.
* ``NGHTTP2_EXT_ALTSVC`` was removed.
* ``nghttp2_ext_altsvc`` was removed.
We have already removed the functionality of Alt-Svc in v0.7 series
and they have been essentially noop. The application using these
macro and struct, remove those lines.
Use nghttp2_error in nghttp2_on_invalid_frame_recv_callback
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Previously ``nghttp2_on_invalid_frame_recv_cb_called`` took the
``error_code``, defined in ``nghttp2_error_code``, as parameter. But
they are not detailed enough to debug. Therefore, we decided to use
more detailed ``nghttp2_error`` values instead.
The application using this callback should update the callback
signature. If it treats ``error_code`` as HTTP/2 error code, update
the code so that it is treated as ``nghttp2_error``.
Receive client magic by default
+++++++++++++++++++++++++++++++
Previously nghttp2 did not process client magic (24 bytes byte
string). To make it deal with it, we had to use
``nghttp2_option_set_recv_client_preface()``. Since v1.0.0, nghttp2
processes client magic by default and
``nghttp2_option_set_recv_client_preface()`` was removed.
Some application may want to disable this behaviour, so we added
``nghttp2_option_set_no_recv_client_magic()`` to achieve this.
The application using ``nghttp2_option_set_recv_client_preface()``
with nonzero value, just remove it.
The application using ``nghttp2_option_set_recv_client_preface()``
with zero value or not using it must use
``nghttp2_option_set_no_recv_client_magic()`` with nonzero value.
Client, Server and Proxy programs
---------------------------------
@@ -200,140 +346,180 @@ It has verbose output mode for framing information. Here is sample
output from ``nghttp`` client::
$ nghttp -nv https://nghttp2.org
[ 0.033][NPN] server offers:
* h2-14
* spdy/3.1
* http/1.1
The negotiated protocol: h2-14
[ 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)=[])
[ 0.190] Connected
The negotiated protocol: h2
[ 0.212] recv SETTINGS frame <length=12, flags=0x00, stream_id=0>
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.212] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.212] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[ 0.212] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
(dep_stream_id=0, weight=201, exclusive=0)
[ 0.212] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
(dep_stream_id=0, weight=101, exclusive=0)
[ 0.212] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
(dep_stream_id=0, weight=1, exclusive=0)
[ 0.212] send PRIORITY frame <length=5, flags=0x00, stream_id=9>
(dep_stream_id=7, weight=1, exclusive=0)
[ 0.212] send PRIORITY frame <length=5, flags=0x00, stream_id=11>
(dep_stream_id=3, weight=1, exclusive=0)
[ 0.212] send HEADERS frame <length=39, flags=0x25, stream_id=13>
; END_STREAM | END_HEADERS | PRIORITY
(padlen=0, dep_stream_id=11, weight=16, exclusive=0)
; Open new stream
:method: GET
:path: /
:scheme: https
:authority: nghttp2.org
accept: */*
accept-encoding: gzip, deflate
user-agent: nghttp2/1.0.1-DEV
[ 0.221] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[ 0.221] recv (stream_id=13) :method: GET
[ 0.221] recv (stream_id=13) :scheme: https
[ 0.221] recv (stream_id=13) :path: /stylesheets/screen.css
[ 0.221] recv (stream_id=13) :authority: nghttp2.org
[ 0.221] recv (stream_id=13) accept-encoding: gzip, deflate
[ 0.222] recv (stream_id=13) user-agent: nghttp2/1.0.1-DEV
[ 0.222] recv PUSH_PROMISE frame <length=50, flags=0x04, stream_id=13>
; END_HEADERS
(padlen=0, promised_stream_id=2)
[ 0.222] recv (stream_id=13) :status: 200
[ 0.222] recv (stream_id=13) date: Thu, 21 May 2015 16:38:14 GMT
[ 0.222] recv (stream_id=13) content-type: text/html
[ 0.222] recv (stream_id=13) last-modified: Fri, 15 May 2015 15:38:06 GMT
[ 0.222] recv (stream_id=13) etag: W/"555612de-19f6"
[ 0.222] recv (stream_id=13) link: </stylesheets/screen.css>; rel=preload; as=stylesheet
[ 0.222] recv (stream_id=13) content-encoding: gzip
[ 0.222] recv (stream_id=13) server: nghttpx nghttp2/1.0.1-DEV
[ 0.222] recv (stream_id=13) via: 1.1 nghttpx
[ 0.222] recv (stream_id=13) strict-transport-security: max-age=31536000
[ 0.222] recv HEADERS frame <length=166, flags=0x04, stream_id=13>
; END_HEADERS
(padlen=0)
; First response header
[ 0.222] recv DATA frame <length=2601, flags=0x01, stream_id=13>
; END_STREAM
[ 0.222] recv (stream_id=2) :status: 200
[ 0.222] recv (stream_id=2) date: Thu, 21 May 2015 16:38:14 GMT
[ 0.222] recv (stream_id=2) content-type: text/css
[ 0.222] recv (stream_id=2) last-modified: Fri, 15 May 2015 15:38:06 GMT
[ 0.222] recv (stream_id=2) etag: W/"555612de-9845"
[ 0.222] recv (stream_id=2) content-encoding: gzip
[ 0.222] recv (stream_id=2) server: nghttpx nghttp2/1.0.1-DEV
[ 0.222] recv (stream_id=2) via: 1.1 nghttpx
[ 0.222] recv (stream_id=2) strict-transport-security: max-age=31536000
[ 0.222] recv HEADERS frame <length=32, flags=0x04, stream_id=2>
; END_HEADERS
(padlen=0)
; First push response header
[ 0.228] recv DATA frame <length=8715, flags=0x01, stream_id=2>
; END_STREAM
[ 0.228] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
(last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])
The HTTP Upgrade is performed like this::
The HTTP Upgrade is performed like so::
$ nghttp -nvu http://nghttp2.org
[ 0.013] HTTP Upgrade request
[ 0.011] Connected
[ 0.011] HTTP Upgrade request
GET / HTTP/1.1
Host: nghttp2.org
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c-14
HTTP2-Settings: AwAAAGQEAAD__wUAAAAB
Upgrade: h2c
HTTP2-Settings: AAMAAABkAAQAAP__
Accept: */*
User-Agent: nghttp2/0.4.0-DEV
User-Agent: nghttp2/1.0.1-DEV
[ 0.024] HTTP Upgrade response
[ 0.018] HTTP Upgrade response
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c-14
Upgrade: h2c
[ 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] 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)=[])
[ 0.018] HTTP Upgrade success
[ 0.018] recv SETTINGS frame <length=12, flags=0x00, stream_id=0>
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.018] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.018] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[ 0.018] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
(dep_stream_id=0, weight=201, exclusive=0)
[ 0.018] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
(dep_stream_id=0, weight=101, exclusive=0)
[ 0.018] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
(dep_stream_id=0, weight=1, exclusive=0)
[ 0.018] send PRIORITY frame <length=5, flags=0x00, stream_id=9>
(dep_stream_id=7, weight=1, exclusive=0)
[ 0.018] send PRIORITY frame <length=5, flags=0x00, stream_id=11>
(dep_stream_id=3, weight=1, exclusive=0)
[ 0.018] send PRIORITY frame <length=5, flags=0x00, stream_id=1>
(dep_stream_id=11, weight=16, exclusive=0)
[ 0.019] recv (stream_id=1) :method: GET
[ 0.019] recv (stream_id=1) :scheme: http
[ 0.019] recv (stream_id=1) :path: /stylesheets/screen.css
[ 0.019] recv (stream_id=1) host: nghttp2.org
[ 0.019] recv (stream_id=1) user-agent: nghttp2/1.0.1-DEV
[ 0.019] recv PUSH_PROMISE frame <length=49, flags=0x04, stream_id=1>
; END_HEADERS
(padlen=0, promised_stream_id=2)
[ 0.019] recv (stream_id=1) :status: 200
[ 0.019] recv (stream_id=1) date: Thu, 21 May 2015 16:39:16 GMT
[ 0.019] recv (stream_id=1) content-type: text/html
[ 0.019] recv (stream_id=1) content-length: 6646
[ 0.019] recv (stream_id=1) last-modified: Fri, 15 May 2015 15:38:06 GMT
[ 0.019] recv (stream_id=1) etag: "555612de-19f6"
[ 0.019] recv (stream_id=1) link: </stylesheets/screen.css>; rel=preload; as=stylesheet
[ 0.019] recv (stream_id=1) accept-ranges: bytes
[ 0.019] recv (stream_id=1) server: nghttpx nghttp2/1.0.1-DEV
[ 0.019] recv (stream_id=1) via: 1.1 nghttpx
[ 0.019] recv HEADERS frame <length=157, flags=0x04, stream_id=1>
; END_HEADERS
(padlen=0)
; First response header
[ 0.019] recv DATA frame <length=6646, flags=0x01, stream_id=1>
; END_STREAM
[ 0.019] recv (stream_id=2) :status: 200
[ 0.019] recv (stream_id=2) date: Thu, 21 May 2015 16:39:16 GMT
[ 0.019] recv (stream_id=2) content-type: text/css
[ 0.019] recv (stream_id=2) content-length: 38981
[ 0.019] recv (stream_id=2) last-modified: Fri, 15 May 2015 15:38:06 GMT
[ 0.019] recv (stream_id=2) etag: "555612de-9845"
[ 0.019] recv (stream_id=2) accept-ranges: bytes
[ 0.019] recv (stream_id=2) server: nghttpx nghttp2/1.0.1-DEV
[ 0.019] recv (stream_id=2) via: 1.1 nghttpx
[ 0.019] recv HEADERS frame <length=36, flags=0x04, stream_id=2>
; END_HEADERS
(padlen=0)
; First push response header
[ 0.026] recv DATA frame <length=16384, flags=0x00, stream_id=2>
[ 0.027] recv DATA frame <length=7952, flags=0x00, stream_id=2>
[ 0.027] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
(window_size_increment=33343)
[ 0.032] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=2>
(window_size_increment=33707)
[ 0.032] recv DATA frame <length=14645, flags=0x01, stream_id=2>
; END_STREAM
[ 0.032] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[ 0.032] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
(last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])
Using the ``-s`` option, ``nghttp`` prints out some timing information for
requests, sorted by completion time::
@@ -342,24 +528,26 @@ requests, sorted by completion time::
***** Statistics *****
Request timing:
complete: relative time from protocol handshake to stream close
request: relative time from protocol handshake to request
transmission. If '*' is shown, this was pushed by server.
process: time for request and response
code: HTTP status code
size: number of bytes received as response body without
inflation.
URI: request URI
responseEnd: the time when last byte of response was received
relative to connectEnd
requestStart: the time just before first byte of request was sent
relative to connectEnd. If '*' is shown, this was
pushed by server.
process: responseEnd - requestStart
code: HTTP status code
size: number of bytes received as response body without
inflation.
URI: request URI
see http://www.w3.org/TR/resource-timing/#processing-model
sorted by 'complete'
complete request process code size request path
+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
id responseEnd requestStart process code size request path
13 +37.19ms +280us 36.91ms 200 2K /
2 +72.65ms * +36.38ms 36.26ms 200 8K /stylesheets/screen.css
17 +77.43ms +38.67ms 38.75ms 200 3K /javascripts/octopress.js
15 +78.12ms +38.66ms 39.46ms 200 3K /javascripts/modernizr-2.0.js
Using the ``-r`` option, ``nghttp`` writes more detailed timing data to
the given file in HAR format.
@@ -381,59 +569,73 @@ Just like ``nghttp``, it has a verbose output mode for framing
information. Here is sample output from ``nghttpd``::
$ 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>
IPv4: listen 0.0.0.0:8080
IPv6: listen :::8080
[id=1] [ 1.521] send SETTINGS frame <length=6, flags=0x00, stream_id=0>
(niv=1)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=1] [ 1.521] recv SETTINGS frame <length=12, 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)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[id=1] [ 1.521] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
; ACK
(niv=0)
[id=1] [ 1.521] recv PRIORITY frame <length=5, flags=0x00, stream_id=3>
(dep_stream_id=0, weight=201, exclusive=0)
[id=1] [ 1.521] recv PRIORITY frame <length=5, flags=0x00, stream_id=5>
(dep_stream_id=0, weight=101, exclusive=0)
[id=1] [ 1.521] recv PRIORITY frame <length=5, flags=0x00, stream_id=7>
(dep_stream_id=0, weight=1, exclusive=0)
[id=1] [ 1.521] recv PRIORITY frame <length=5, flags=0x00, stream_id=9>
(dep_stream_id=7, weight=1, exclusive=0)
[id=1] [ 1.521] recv PRIORITY frame <length=5, flags=0x00, stream_id=11>
(dep_stream_id=3, weight=1, exclusive=0)
[id=1] [ 1.521] recv (stream_id=13) :method: GET
[id=1] [ 1.521] recv (stream_id=13) :path: /
[id=1] [ 1.521] recv (stream_id=13) :scheme: http
[id=1] [ 1.521] recv (stream_id=13) :authority: localhost:8080
[id=1] [ 1.521] recv (stream_id=13) accept: */*
[id=1] [ 1.521] recv (stream_id=13) accept-encoding: gzip, deflate
[id=1] [ 1.521] recv (stream_id=13) user-agent: nghttp2/1.0.0-DEV
[id=1] [ 1.521] recv HEADERS frame <length=41, flags=0x25, stream_id=13>
; END_STREAM | END_HEADERS | PRIORITY
(padlen=0, dep_stream_id=11, weight=16, exclusive=0)
; Open new stream
[id=1] [ 15.921] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
[id=1] [ 1.521] send 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>
[id=1] [ 1.521] send HEADERS frame <length=86, flags=0x04, stream_id=13>
; END_HEADERS
(padlen=0)
; First response header
:status: 200
server: nghttpd nghttp2/1.0.0-DEV
content-length: 10
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>
date: Fri, 15 May 2015 14:49:04 GMT
last-modified: Tue, 30 Sep 2014 12:40:52 GMT
[id=1] [ 1.522] send DATA frame <length=10, flags=0x01, stream_id=13>
; 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
[id=1] [ 1.522] stream_id=13 closed
[id=1] [ 1.522] recv GOAWAY frame <length=8, flags=0x00, stream_id=0>
(last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[])
[id=1] [ 1.522] closed
nghttpx - proxy
+++++++++++++++
``nghttpx`` is a multi-threaded reverse proxy for ``h2-14``, SPDY and
HTTP/1.1, and powers http://nghttp2.org and supports HTTP/2 server push.
It has several operational modes:
``nghttpx`` is a multi-threaded reverse proxy for HTTP/2, SPDY and
HTTP/1.1, and powers http://nghttp2.org and supports HTTP/2 server
push.
``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:
================== ============================ ============== =============
Mode option Frontend Backend Note
@@ -446,8 +648,8 @@ default mode HTTP/2, SPDY, HTTP/1.1 (TLS) HTTP/1.1 Reverse proxy
================== ============================ ============== =============
The interesting mode at the moment is the default mode. It works like
a reverse proxy and listens for ``h2-14``, SPDY and HTTP/1.1 and can
be deployed as a SSL/TLS terminator for existing web server.
a reverse proxy and listens for HTTP/2, SPDY and HTTP/1.1 and can be
deployed as a SSL/TLS terminator for existing web server.
The default mode, ``--http2-proxy`` and ``--http2-bridge`` modes use
SSL/TLS in the frontend connection by default. To disable SSL/TLS,
@@ -456,7 +658,7 @@ disabled in the frontend and incoming HTTP/1.1 connections can be
upgraded to HTTP/2 through HTTP Upgrade.
The ``--http2-bridge``, ``--client`` and ``--client-proxy`` modes use
SSL/TLS in the backend connection by deafult. To disable SSL/TLS, use
SSL/TLS in the backend connection by default. To disable SSL/TLS, use
the ``--backend-no-tls`` option.
``nghttpx`` supports a configuration file. See the ``--conf`` option and
@@ -548,6 +750,7 @@ follows::
spawning thread #0: 100 concurrent clients, 100000 total requests
Protocol: TLSv1.2
Cipher: ECDHE-RSA-AES128-GCM-SHA256
Server Temp Key: ECDH P-256 256 bits
progress: 10% done
progress: 20% done
progress: 30% done
@@ -559,12 +762,14 @@ follows::
progress: 90% done
progress: 100% done
finished in 7.10s, 14092 req/s, 55.67MB/s
finished in 771.26ms, 129658 req/s, 4.71MB/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
traffic: 3812300 bytes total, 1009900 bytes headers, 1000000 bytes data
min max mean sd +/- sd
time for request: 283.86ms 1.46s 659.70ms 150.87ms 84.68%
time for request: 25.12ms 124.55ms 51.07ms 15.36ms 84.87%
time for connect: 208.94ms 254.67ms 241.38ms 7.95ms 63.00%
time to 1st byte: 209.11ms 254.80ms 241.51ms 7.94ms 63.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
@@ -751,7 +956,7 @@ max_deflate_size
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
``max_deflate_size`` buffer. Since the header table size is still
``max_size``, the encoder has to keep track of entries ouside the
``max_size``, the encoder has to keep track of entries outside the
``max_deflate_size`` but inside the ``max_size`` and make sure
that they are no longer referenced.
@@ -1034,6 +1239,8 @@ an HTTP/2 server looks like this:
.. code-block:: cpp
#include <iostream>
#include <nghttp2/asio_http2_server.h>
using namespace nghttp2::asio_http2;
@@ -1074,32 +1281,32 @@ Here is sample code to use the client API:
session sess(io_service, "localhost", "3000");
sess.on_connect([&sess](tcp::resolver::iterator endpoint_it) {
boost::system::error_code ec;
boost::system::error_code ec;
auto req = sess.submit(ec, "GET", "http://localhost:3000/");
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;
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;
});
});
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();
});
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;
std::cerr << "error: " << ec.message() << std::endl;
});
io_service.run();
@@ -1239,7 +1446,7 @@ original creator(s) or those who have been assigned copyright by the
original author(s).
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.
the case may be) agree to assign the copyright of your submission to us.
.. the above really needs to be reworded to pass legal muster.
We will credit you for your
changes as far as possible, to give credit but also to keep a trace

View File

@@ -42,6 +42,6 @@ PATH=$TOOLCHAIN/bin:$PATH
--enable-werror \
CC=clang \
CXX=clang++ \
CPPFLAGS="-I$PREFIX/include" \
CPPFLAGS="-fPIE -I$PREFIX/include" \
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
LDFLAGS="-L$PREFIX/lib"
LDFLAGS="-fPIE -pie -L$PREFIX/lib"

View File

@@ -25,14 +25,30 @@ dnl Do not change user variables!
dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
AC_PREREQ(2.61)
AC_INIT([nghttp2], [0.7.9], [t-tujikawa@users.sourceforge.net])
AC_INIT([nghttp2], [1.3.1], [t-tujikawa@users.sourceforge.net])
AC_CONFIG_AUX_DIR([.])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
AC_USE_SYSTEM_EXTENSIONS
LT_PREREQ([2.2.6])
LT_INIT()
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE([subdir-objects])
# AM_EXTRA_RECURSIVE_TARGETS requires automake 1.13 or higher
m4_ifdef([AM_EXTRA_RECURSIVE_TARGETS], [AM_EXTRA_RECURSIVE_TARGETS([it itprep])])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl See versioning rule:
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
AC_SUBST(LT_CURRENT, 12)
AC_SUBST(LT_REVISION, 2)
AC_SUBST(LT_AGE, 7)
AC_SUBST(LT_CURRENT, 15)
AC_SUBST(LT_REVISION, 1)
AC_SUBST(LT_AGE, 1)
major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"`
minor=`echo $PACKAGE_VERSION |cut -d. -f2 | sed -e "s/[^0-9]//g"`
@@ -42,21 +58,6 @@ PACKAGE_VERSION_NUM=`printf "0x%02x%02x%02x" "$major" "$minor" "$patch"`
AC_SUBST(PACKAGE_VERSION_NUM)
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
AC_CANONICAL_TARGET
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([subdir-objects])
# comment out for now since this requires automake 1.13 or higher and
# travis has older one.
# AM_EXTRA_RECURSIVE_TARGETS([it])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_CONFIG_HEADERS([config.h])
dnl Checks for command-line options
AC_ARG_ENABLE([werror],
[AS_HELP_STRING([--enable-werror],
@@ -118,6 +119,11 @@ AC_ARG_WITH([spdylay],
[Use spdylay [default=check]])],
[request_spdylay=$withval], [request_spdylay=check])
AC_ARG_WITH([mruby],
[AS_HELP_STRING([--with-mruby],
[Use mruby [default=no]])],
[request_mruby=$withval], [request_mruby=no])
AC_ARG_WITH([cython],
[AS_HELP_STRING([--with-cython=PATH],
[Use cython in given PATH])],
@@ -129,14 +135,17 @@ AC_ARG_VAR([CYTHON], [the Cython executable])
dnl Checks for programs
AC_PROG_CC
AC_PROG_CXX
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
AM_PROG_CC_C_O
AC_PROG_MKDIR_P
PKG_PROG_PKG_CONFIG([0.20])
AM_PATH_PYTHON([2.7],, [:])
if [test "x$request_python_bindings" != "xno"]; then
AM_PATH_PYTHON([2.7],, [:])
AX_PYTHON_DEVEL([>= '2.7'])
fi
@@ -165,24 +174,6 @@ AX_CXX_COMPILE_STDCXX_11([noext], [optional])
AC_LANG_PUSH(C++)
# Check that std::chrono::steady_clock is available. In particular,
# gcc 4.6 does not have one, but has monotonic_clock which is the old
# name existed in the pre-standard draft. If steady_clock is not
# available, don't define HAVE_STEADY_CLOCK and replace steady_clock
# with monotonic_clock.
AC_MSG_CHECKING([whether std::chrono::steady_clock is available])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
[[
#include <chrono>
]],
[[
auto tp = std::chrono::steady_clock::now();
]])],
[AC_DEFINE([HAVE_STEADY_CLOCK], [1],
[Define to 1 if you have the `std::chrono::steady_clock`.])
AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])])
# Check that std::future is available.
AC_MSG_CHECKING([whether std::future is available])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
@@ -226,20 +217,6 @@ TESTLDADD=
# Additional libraries required for programs under src directory.
APPLDFLAGS=
LIBS_OLD=$LIBS
# Search for dlsym function, which is used in tests. Linux needs -ldl,
# but netbsd does not need it.
AC_SEARCH_LIBS([dlsym], [dl])
TESTLDADD="$LIBS $TESTLDADD"
LIBS=$LIBS_OLD
LIBS_OLD=$LIBS
AC_SEARCH_LIBS([clock_gettime], [rt],
[AC_DEFINE([HAVE_CLOCK_GETTIME], [1],
[Define to 1 if you have the `clock_gettime`.])])
APPLDFLAGS="$LIBS $APPLDFLAGS"
LIBS=$LIBS_OLD
case "$host" in
*android*)
android_build=yes
@@ -253,16 +230,10 @@ case "$host" in
esac
# zlib
if test "x$android_build" = "xyes"; then
# Use zlib provided by NDK
APPLDFLAGS="-lz $APPLDFLAGS"
have_zlib=yes
else
PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.3], [have_zlib=yes], [have_zlib=no])
PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.3], [have_zlib=yes], [have_zlib=no])
if test "x${have_zlib}" = "xno"; then
AC_MSG_NOTICE($ZLIB_PKG_ERRORS)
fi
if test "x${have_zlib}" = "xno"; then
AC_MSG_NOTICE($ZLIB_PKG_ERRORS)
fi
# cunit
@@ -328,7 +299,7 @@ fi
# jansson (for src/nghttp, src/deflatehd and src/inflatehd)
PKG_CHECK_MODULES([JANSSON], [jansson >= 2.5],
[have_jansson=yes], [have_jansson=no])
if test "x${have_jansson}" == "xyes"; then
if test "x${have_jansson}" = "xyes"; then
AC_DEFINE([HAVE_JANSSON], [1],
[Define to 1 if you have `libjansson` library.])
else
@@ -358,9 +329,23 @@ if test "x${request_jemalloc}" != "xno"; then
AC_SEARCH_LIBS([malloc_stats_print], [jemalloc], [have_jemalloc=yes], [],
[$PTHREAD_LDFLAGS])
LIBS=$LIBS_OLD
if test "x${have_jemalloc}" = "xyes"; then
jemalloc_libs=${ac_cv_search_malloc_stats_print}
else
# On Darwin, malloc_stats_print is je_malloc_stats_print
AC_SEARCH_LIBS([je_malloc_stats_print], [jemalloc], [have_jemalloc=yes], [],
[$PTHREAD_LDFLAGS])
LIBS=$LIBS_OLD
if test "x${have_jemalloc}" = "xyes"; then
jemalloc_libs=${ac_cv_search_je_malloc_stats_print}
fi
fi
if test "x${have_jemalloc}" = "xyes" &&
test "x${ac_cv_search_malloc_stats_print}" != "xnone required"; then
JEMALLOC_LIBS=${ac_cv_search_malloc_stats_print}
test "x${jemalloc_libs}" != "xnone required"; then
JEMALLOC_LIBS=${jemalloc_libs}
AC_SUBST([JEMALLOC_LIBS])
fi
fi
@@ -390,6 +375,20 @@ fi
AM_CONDITIONAL([HAVE_SPDYLAY], [ test "x${have_spdylay}" = "xyes" ])
# mruby (for src/nghttpx)
have_mruby=no
if test "x${request_mruby}" = "xyes"; then
# We are going to build mruby
have_mruby=yes
AC_DEFINE([HAVE_MRUBY], [1], [Define to 1 if you have `mruby` library.])
LIBMRUBY_LIBS="-lmruby -lm"
LIBMRUBY_CFLAGS=
AC_SUBST([LIBMRUBY_LIBS])
AC_SUBST([LIBMRUBY_CFLAGS])
fi
AM_CONDITIONAL([HAVE_MRUBY], [test "x${have_mruby}" = "xyes"])
# Check Boost Asio library
have_asio_lib=no
@@ -465,6 +464,18 @@ fi
AM_CONDITIONAL([ENABLE_EXAMPLES], [ test "x${enable_examples}" = "xyes" ])
# third-party only be built when needed
enable_third_party=no
if test "x${enable_examples}" = "xyes" ||
test "x${enable_app}" = "xyes" ||
test "x${enable_hpack_tools}" = "xyes" ||
test "x${enable_asio_lib}" = "xyes"; then
enable_third_party=yes
fi
AM_CONDITIONAL([ENABLE_THIRD_PARTY], [ test "x${enable_third_party}" = "xyes" ])
# Python bindings
enable_python_bindings=no
if test "x${request_python_bindings}" != "xno" &&
@@ -498,23 +509,23 @@ AM_CONDITIONAL([ENABLE_FAILMALLOC], [ test "x${enable_failmalloc}" = "xyes" ])
AC_HEADER_ASSERT
AC_CHECK_HEADERS([ \
arpa/inet.h \
fcntl.h \
inttypes.h \
limits.h \
netdb.h \
netinet/in.h \
pwd.h \
stddef.h \
stdint.h \
stdlib.h \
string.h \
sys/socket.h \
sys/time.h \
syslog.h \
time.h \
unistd.h \
])
case "${host}" in
*mingw*)
# For ntohl, ntohs in Windows
AC_CHECK_HEADERS([winsock2.h])
;;
esac
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
@@ -522,8 +533,16 @@ AC_TYPE_UINT8_T
AC_TYPE_UINT16_T
AC_TYPE_UINT32_T
AC_TYPE_UINT64_T
AC_TYPE_INT8_T
AC_TYPE_INT16_T
AC_TYPE_INT32_T
AC_TYPE_INT64_T
AC_TYPE_OFF_T
AC_TYPE_PID_T
AC_TYPE_UID_T
AC_CHECK_TYPES([ptrdiff_t])
AC_C_BIGENDIAN
AC_C_INLINE
AC_SYS_LARGEFILE
AC_CHECK_MEMBER([struct tm.tm_gmtoff], [have_struct_tm_tm_gmtoff=yes],
@@ -538,16 +557,40 @@ fi
# adjustment.
AC_CHECK_SIZEOF([int *])
AC_CHECK_SIZEOF([time_t])
# Checks for library functions.
if test "x$cross_compiling" != "xyes"; then
AC_FUNC_MALLOC
fi
# Don't check malloc, since it does not play nicely with C++ stdlib
# AC_FUNC_MALLOC
AC_FUNC_CHOWN
AC_FUNC_ERROR_AT_LINE
AC_FUNC_FORK
# Don't check realloc, since LeakSanitizer detects memory leak during check
# AC_FUNC_REALLOC
AC_FUNC_STRERROR_R
AC_FUNC_STRNLEN
AC_CHECK_FUNCS([ \
_Exit \
accept4 \
dup2 \
getcwd \
getpwnam \
localtime_r \
memchr \
memmove \
memset \
socket \
sqrt \
strchr \
strdup \
strerror \
strndup \
strstr \
strtol \
strtoul \
timegm \
])
@@ -564,13 +607,6 @@ AM_CONDITIONAL([ENABLE_TINY_NGHTTPD],
[ test "x${have_epoll}" = "xyes" &&
test "x${have_timerfd_create}" = "xyes"])
dnl Windows library for winsock2
case "${host}" in
*mingw*)
LIBS="$LIBS -lws2_32"
;;
esac
ac_save_CFLAGS=$CFLAGS
CFLAGS=
@@ -664,6 +700,7 @@ AC_CONFIG_FILES([
doc/asio_http2_client.h.rst
doc/contribute.rst
contrib/Makefile
script/Makefile
])
AC_OUTPUT
@@ -700,8 +737,10 @@ AC_MSG_NOTICE([summary of build options:
Libev: ${have_libev}
Libevent(SSL): ${have_libevent_openssl}
Spdylay: ${have_spdylay}
MRuby: ${have_mruby}
Jansson: ${have_jansson}
Jemalloc: ${have_jemalloc}
Zlib: ${have_zlib}
Boost CPPFLAGS: ${BOOST_CPPFLAGS}
Boost LDFLAGS: ${BOOST_LDFLAGS}
Boost::ASIO: ${BOOST_ASIO_LIB}
@@ -714,4 +753,5 @@ AC_MSG_NOTICE([summary of build options:
Examples: ${enable_examples}
Python bindings:${enable_python_bindings}
Threading: ${enable_threads}
Third-party: ${enable_third_party}
])

2
contrib/.gitignore vendored
View File

@@ -1 +1,3 @@
nghttpx-init
nghttpx.service
nghttpx-upstart.conf

View File

@@ -21,19 +21,24 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
EXTRA_DIST = nghttpx-init.in nghttpx-logrotate
configfiles = nghttpx-init nghttpx.service nghttpx-upstart.conf
EXTRA_DIST = $(configfiles:%=%.in) nghttpx-logrotate tlsticketupdate.go
edit = sed -e 's|@bindir[@]|$(bindir)|g'
nghttpx-init: Makefile
nghttpx-init: %: $(srcdir)/%.in
rm -f $@ $@.tmp
$(edit) $(srcdir)/$@.in > $@.tmp
$(edit) $< > $@.tmp
chmod +x $@.tmp
mv $@.tmp $@
nghttpx-init: $(srcdir)/nghttpx-init.in
nghttpx.service nghttpx-upstart.conf: %: $(srcdir)/%.in
$(edit) $< > $@
all-local: nghttpx-init
$(configfiles): Makefile
all-local: $(configfiles)
clean-local:
-rm -f nghttpx-init nghttpx-init.tmp
-rm -f nghttpx-init.tmp $(configfiles)

2
contrib/nghttpx-init.in Normal file → Executable file
View File

@@ -20,7 +20,7 @@ NAME=nghttpx
# Depending on the configuration, binary may be located under @sbindir@
DAEMON=@bindir@/$NAME
PIDFILE=/var/run/$NAME.pid
DAEMON_ARGS="--conf /etc/nghttpx/nghttpx.conf --pid-file=$PIDFILE"
DAEMON_ARGS="--conf /etc/nghttpx/nghttpx.conf --pid-file=$PIDFILE --daemon"
SCRIPTNAME=/etc/init.d/$NAME
# Exit if the package is not installed

View File

@@ -1,18 +1,11 @@
/var/log/nghttpx/*.log {
weekly
missingok
rotate 52
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
prerotate
if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
run-parts /etc/logrotate.d/httpd-prerotate; \
fi \
endscript
postrotate
[ -s /run/nghttpx.pid ] && kill -USR1 `cat /run/nghttpx.pid`
endscript
weekly
rotate 52
missingok
compress
delaycompress
notifempty
postrotate
killall -USR1 nghttpx 2> /dev/null || true
endscript
}

View File

@@ -0,0 +1,8 @@
# vim: ft=upstart:
description "HTTP/2 reverse proxy"
start on runlevel [2]
stop on runlevel [016]
exec @bindir@/nghttpx

View File

@@ -0,0 +1,10 @@
[Unit]
Description=HTTP/2 experimental proxy
After=network.target
[Service]
Type=simple
ExecStart=@bindir@/nghttpx --errorlog-syslog
[Install]
WantedBy=multi-user.target

113
contrib/tlsticketupdate.go Normal file
View File

@@ -0,0 +1,113 @@
//
// nghttp2 - HTTP/2 C Library
//
// Copyright (c) 2015 Tatsuhiro Tsujikawa
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
package main
import (
"bytes"
"crypto/rand"
"encoding/binary"
"flag"
"fmt"
"github.com/bradfitz/gomemcache/memcache"
"log"
"time"
)
func makeKey(len int) []byte {
b := make([]byte, len)
if _, err := rand.Read(b); err != nil {
log.Fatalf("rand.Read: %v", err)
}
return b
}
func main() {
var host = flag.String("host", "127.0.0.1", "memcached host")
var port = flag.Int("port", 11211, "memcached port")
var cipher = flag.String("cipher", "aes-128-cbc", "cipher for TLS ticket encryption")
var interval = flag.Int("interval", 3600, "interval to update TLS ticket keys")
flag.Parse()
var keylen int
switch *cipher {
case "aes-128-cbc":
keylen = 48
case "aes-256-cbc":
keylen = 80
default:
log.Fatalf("cipher: unknown cipher %v", cipher)
}
mc := memcache.New(fmt.Sprintf("%v:%v", *host, *port))
keys := [][]byte{
makeKey(keylen), // current encryption key
makeKey(keylen), // next encryption key; now decryption only
}
for {
buf := new(bytes.Buffer)
if err := binary.Write(buf, binary.BigEndian, uint32(1)); err != nil {
log.Fatalf("failed to write version: %v", err)
}
for _, key := range keys {
if err := binary.Write(buf, binary.BigEndian, uint16(keylen)); err != nil {
log.Fatalf("failed to write length: %v", err)
}
if _, err := buf.Write(key); err != nil {
log.Fatalf("buf.Write: %v", err)
}
}
mc.Set(&memcache.Item{
Key: "nghttpx:tls-ticket-key",
Value: buf.Bytes(),
Expiration: int32((*interval) + 300),
})
select {
case <-time.After(time.Duration(*interval) * time.Second):
}
// rotate keys. the last key is now encryption key.
// generate new key and append it to the last, so that
// we can at least decrypt TLS ticket encrypted by new
// key on the host which does not get new key yet.
// keep at most past 11 keys as decryption only key
n := len(keys) + 1
if n > 13 {
n = 13
}
newKeys := make([][]byte, n)
newKeys[0] = keys[len(keys)-1]
copy(newKeys[1:], keys[0:n-2])
newKeys[n-1] = makeKey(keylen)
keys = newKeys
}
}

23
doc/.gitignore vendored
View File

@@ -1,3 +1,24 @@
# generated files
apiref.rst
asio_http2.h.rst
asio_http2_client.h.rst
asio_http2_server.h.rst
building-android-binary.rst
conf.py
manual
contribute.rst
enums.rst
h2load-howto.rst
index.rst
libnghttp2_asio.rst
macros.rst
manual/
nghttp2.h.rst
nghttp2_*.rst
nghttp2ver.h.rst
nghttpx-howto.rst
package_README.rst
python-apiref.rst
tutorial-client.rst
tutorial-hpack.rst
tutorial-server.rst
types.rst

View File

@@ -23,10 +23,120 @@
man_MANS = nghttp.1 nghttpd.1 nghttpx.1 h2load.1
APIDOCS= \
macros.rst \
enums.rst \
types.rst \
nghttp2_check_header_name.rst \
nghttp2_check_header_value.rst \
nghttp2_hd_deflate_bound.rst \
nghttp2_hd_deflate_change_table_size.rst \
nghttp2_hd_deflate_del.rst \
nghttp2_hd_deflate_hd.rst \
nghttp2_hd_deflate_new.rst \
nghttp2_hd_deflate_new2.rst \
nghttp2_hd_inflate_change_table_size.rst \
nghttp2_hd_inflate_del.rst \
nghttp2_hd_inflate_end_headers.rst \
nghttp2_hd_inflate_hd.rst \
nghttp2_hd_inflate_new.rst \
nghttp2_hd_inflate_new2.rst \
nghttp2_is_fatal.rst \
nghttp2_nv_compare_name.rst \
nghttp2_option_del.rst \
nghttp2_option_new.rst \
nghttp2_option_set_max_reserved_remote_streams.rst \
nghttp2_option_set_no_auto_window_update.rst \
nghttp2_option_set_no_http_messaging.rst \
nghttp2_option_set_no_recv_client_magic.rst \
nghttp2_option_set_peer_max_concurrent_streams.rst \
nghttp2_pack_settings_payload.rst \
nghttp2_priority_spec_check_default.rst \
nghttp2_priority_spec_default_init.rst \
nghttp2_priority_spec_init.rst \
nghttp2_select_next_protocol.rst \
nghttp2_session_callbacks_del.rst \
nghttp2_session_callbacks_new.rst \
nghttp2_session_callbacks_set_before_frame_send_callback.rst \
nghttp2_session_callbacks_set_data_source_read_length_callback.rst \
nghttp2_session_callbacks_set_on_begin_frame_callback.rst \
nghttp2_session_callbacks_set_on_begin_headers_callback.rst \
nghttp2_session_callbacks_set_on_data_chunk_recv_callback.rst \
nghttp2_session_callbacks_set_on_frame_not_send_callback.rst \
nghttp2_session_callbacks_set_on_frame_recv_callback.rst \
nghttp2_session_callbacks_set_on_frame_send_callback.rst \
nghttp2_session_callbacks_set_on_header_callback.rst \
nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst \
nghttp2_session_callbacks_set_on_stream_close_callback.rst \
nghttp2_session_callbacks_set_recv_callback.rst \
nghttp2_session_callbacks_set_select_padding_callback.rst \
nghttp2_session_callbacks_set_send_callback.rst \
nghttp2_session_callbacks_set_send_data_callback.rst \
nghttp2_session_client_new.rst \
nghttp2_session_client_new2.rst \
nghttp2_session_client_new3.rst \
nghttp2_session_consume.rst \
nghttp2_session_consume_connection.rst \
nghttp2_session_consume_stream.rst \
nghttp2_session_del.rst \
nghttp2_session_find_stream.rst \
nghttp2_session_get_effective_local_window_size.rst \
nghttp2_session_get_effective_recv_data_length.rst \
nghttp2_session_get_last_proc_stream_id.rst \
nghttp2_session_get_next_stream_id.rst \
nghttp2_session_get_outbound_queue_size.rst \
nghttp2_session_get_remote_settings.rst \
nghttp2_session_get_remote_window_size.rst \
nghttp2_session_get_root_stream.rst \
nghttp2_session_get_stream_effective_local_window_size.rst \
nghttp2_session_get_stream_effective_recv_data_length.rst \
nghttp2_session_get_stream_local_close.rst \
nghttp2_session_get_stream_remote_close.rst \
nghttp2_session_get_stream_remote_window_size.rst \
nghttp2_session_get_stream_user_data.rst \
nghttp2_session_mem_recv.rst \
nghttp2_session_mem_send.rst \
nghttp2_session_recv.rst \
nghttp2_session_resume_data.rst \
nghttp2_session_send.rst \
nghttp2_session_server_new.rst \
nghttp2_session_server_new2.rst \
nghttp2_session_server_new3.rst \
nghttp2_session_set_next_stream_id.rst \
nghttp2_session_set_stream_user_data.rst \
nghttp2_session_terminate_session.rst \
nghttp2_session_terminate_session2.rst \
nghttp2_session_upgrade.rst \
nghttp2_session_want_read.rst \
nghttp2_session_want_write.rst \
nghttp2_stream_get_first_child.rst \
nghttp2_stream_get_next_sibling.rst \
nghttp2_stream_get_parent.rst \
nghttp2_stream_get_previous_sibling.rst \
nghttp2_stream_get_state.rst \
nghttp2_stream_get_sum_dependency_weight.rst \
nghttp2_stream_get_weight.rst \
nghttp2_strerror.rst \
nghttp2_submit_data.rst \
nghttp2_submit_goaway.rst \
nghttp2_submit_headers.rst \
nghttp2_submit_ping.rst \
nghttp2_submit_priority.rst \
nghttp2_submit_push_promise.rst \
nghttp2_submit_request.rst \
nghttp2_submit_response.rst \
nghttp2_submit_rst_stream.rst \
nghttp2_submit_settings.rst \
nghttp2_submit_shutdown_notice.rst \
nghttp2_submit_trailer.rst \
nghttp2_submit_window_update.rst \
nghttp2_version.rst
EXTRA_DIST = \
mkapiref.py \
README.rst \
apiref-header.rst \
programmers-guide.rst \
$(APIDOCS) \
nghttp.1.rst \
nghttpd.1.rst \
nghttpx.1.rst \
@@ -41,6 +151,9 @@ EXTRA_DIST = \
sources/python-apiref.rst \
sources/building-android-binary.rst \
sources/contribute.rst \
_exts/sphinxcontrib/LICENSE.rubydomain \
_exts/sphinxcontrib/__init__.py \
_exts/sphinxcontrib/rubydomain.py \
_themes/sphinx_rtd_theme/__init__.py \
_themes/sphinx_rtd_theme/breadcrumbs.html \
_themes/sphinx_rtd_theme/footer.html \
@@ -99,13 +212,17 @@ help:
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
apiref.rst: $(top_builddir)/lib/includes/nghttp2/nghttp2ver.h \
apiref.rst: \
$(top_builddir)/lib/includes/nghttp2/nghttp2ver.h \
$(top_builddir)/lib/includes/nghttp2/nghttp2.h
$(PYTHON) $(top_srcdir)/doc/mkapiref.py \
--header $(top_srcdir)/doc/apiref-header.rst $^ > $@
apiref.rst macros.rst enums.rst types.rst . $^
$(APIDOCS): apiref.rst
clean-local:
-rm apiref.rst
-rm -f apiref.rst
-rm -f $(APIDOCS)
-rm -rf $(BUILDDIR)/*
html-local: apiref.rst

View File

@@ -0,0 +1,28 @@
If not otherwise noted, the extensions in this package are licensed
under the following license.
Copyright (c) 2010 by the contributors (see AUTHORS file).
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
"""
sphinxcontrib
~~~~~~~~~~~~~
This package is a namespace package that contains all extensions
distributed in the ``sphinx-contrib`` distribution.
:copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
__import__('pkg_resources').declare_namespace(__name__)

View File

@@ -0,0 +1,695 @@
# -*- coding: utf-8 -*-
"""
sphinx.domains.ruby
~~~~~~~~~~~~~~~~~~~
The Ruby domain.
:copyright: Copyright 2010 by SHIBUKAWA Yoshiki
:license: BSD, see LICENSE for details.
"""
import re
from docutils import nodes
from docutils.parsers.rst import directives
from sphinx import addnodes
from sphinx.roles import XRefRole
from sphinx.locale import l_, _
from sphinx.domains import Domain, ObjType, Index
from sphinx.directives import ObjectDescription
from sphinx.util.nodes import make_refnode
from sphinx.util.compat import Directive
from sphinx.util.docfields import Field, GroupedField, TypedField
# REs for Ruby signatures
rb_sig_re = re.compile(
r'''^ ([\w.]*\.)? # class name(s)
(\$?\w+\??!?) \s* # thing name
(?: \((.*)\) # optional: arguments
(?:\s* -> \s* (.*))? # return annotation
)? $ # and nothing more
''', re.VERBOSE)
rb_paramlist_re = re.compile(r'([\[\],])') # split at '[', ']' and ','
separators = {
'method':'#', 'attr_reader':'#', 'attr_writer':'#', 'attr_accessor':'#',
'function':'.', 'classmethod':'.', 'class':'::', 'module':'::',
'global':'', 'const':'::'}
rb_separator = re.compile(r"(?:\w+)?(?:::)?(?:\.)?(?:#)?")
def _iteritems(d):
for k in d:
yield k, d[k]
def ruby_rsplit(fullname):
items = [item for item in rb_separator.findall(fullname)]
return ''.join(items[:-2]), items[-1]
class RubyObject(ObjectDescription):
"""
Description of a general Ruby object.
"""
option_spec = {
'noindex': directives.flag,
'module': directives.unchanged,
}
doc_field_types = [
TypedField('parameter', label=l_('Parameters'),
names=('param', 'parameter', 'arg', 'argument'),
typerolename='obj', typenames=('paramtype', 'type')),
TypedField('variable', label=l_('Variables'), rolename='obj',
names=('var', 'ivar', 'cvar'),
typerolename='obj', typenames=('vartype',)),
GroupedField('exceptions', label=l_('Raises'), rolename='exc',
names=('raises', 'raise', 'exception', 'except'),
can_collapse=True),
Field('returnvalue', label=l_('Returns'), has_arg=False,
names=('returns', 'return')),
Field('returntype', label=l_('Return type'), has_arg=False,
names=('rtype',)),
]
def get_signature_prefix(self, sig):
"""
May return a prefix to put before the object name in the signature.
"""
return ''
def needs_arglist(self):
"""
May return true if an empty argument list is to be generated even if
the document contains none.
"""
return False
def handle_signature(self, sig, signode):
"""
Transform a Ruby signature into RST nodes.
Returns (fully qualified name of the thing, classname if any).
If inside a class, the current class name is handled intelligently:
* it is stripped from the displayed name if present
* it is added to the full name (return value) if not present
"""
m = rb_sig_re.match(sig)
if m is None:
raise ValueError
name_prefix, name, arglist, retann = m.groups()
if not name_prefix:
name_prefix = ""
# determine module and class name (if applicable), as well as full name
modname = self.options.get(
'module', self.env.temp_data.get('rb:module'))
classname = self.env.temp_data.get('rb:class')
if self.objtype == 'global':
add_module = False
modname = None
classname = None
fullname = name
elif classname:
add_module = False
if name_prefix and name_prefix.startswith(classname):
fullname = name_prefix + name
# class name is given again in the signature
name_prefix = name_prefix[len(classname):].lstrip('.')
else:
separator = separators[self.objtype]
fullname = classname + separator + name_prefix + name
else:
add_module = True
if name_prefix:
classname = name_prefix.rstrip('.')
fullname = name_prefix + name
else:
classname = ''
fullname = name
signode['module'] = modname
signode['class'] = self.class_name = classname
signode['fullname'] = fullname
sig_prefix = self.get_signature_prefix(sig)
if sig_prefix:
signode += addnodes.desc_annotation(sig_prefix, sig_prefix)
if name_prefix:
signode += addnodes.desc_addname(name_prefix, name_prefix)
# exceptions are a special case, since they are documented in the
# 'exceptions' module.
elif add_module and self.env.config.add_module_names:
if self.objtype == 'global':
nodetext = ''
signode += addnodes.desc_addname(nodetext, nodetext)
else:
modname = self.options.get(
'module', self.env.temp_data.get('rb:module'))
if modname and modname != 'exceptions':
nodetext = modname + separators[self.objtype]
signode += addnodes.desc_addname(nodetext, nodetext)
signode += addnodes.desc_name(name, name)
if not arglist:
if self.needs_arglist():
# for callables, add an empty parameter list
signode += addnodes.desc_parameterlist()
if retann:
signode += addnodes.desc_returns(retann, retann)
return fullname, name_prefix
signode += addnodes.desc_parameterlist()
stack = [signode[-1]]
for token in rb_paramlist_re.split(arglist):
if token == '[':
opt = addnodes.desc_optional()
stack[-1] += opt
stack.append(opt)
elif token == ']':
try:
stack.pop()
except IndexError:
raise ValueError
elif not token or token == ',' or token.isspace():
pass
else:
token = token.strip()
stack[-1] += addnodes.desc_parameter(token, token)
if len(stack) != 1:
raise ValueError
if retann:
signode += addnodes.desc_returns(retann, retann)
return fullname, name_prefix
def get_index_text(self, modname, name):
"""
Return the text for the index entry of the object.
"""
raise NotImplementedError('must be implemented in subclasses')
def _is_class_member(self):
return self.objtype.endswith('method') or self.objtype.startswith('attr')
def add_target_and_index(self, name_cls, sig, signode):
if self.objtype == 'global':
modname = ''
else:
modname = self.options.get(
'module', self.env.temp_data.get('rb:module'))
separator = separators[self.objtype]
if self._is_class_member():
if signode['class']:
prefix = modname and modname + '::' or ''
else:
prefix = modname and modname + separator or ''
else:
prefix = modname and modname + separator or ''
fullname = prefix + name_cls[0]
# note target
if fullname not in self.state.document.ids:
signode['names'].append(fullname)
signode['ids'].append(fullname)
signode['first'] = (not self.names)
self.state.document.note_explicit_target(signode)
objects = self.env.domaindata['rb']['objects']
if fullname in objects:
self.env.warn(
self.env.docname,
'duplicate object description of %s, ' % fullname +
'other instance in ' +
self.env.doc2path(objects[fullname][0]),
self.lineno)
objects[fullname] = (self.env.docname, self.objtype)
indextext = self.get_index_text(modname, name_cls)
if indextext:
self.indexnode['entries'].append(('single', indextext,
fullname, fullname))
def before_content(self):
# needed for automatic qualification of members (reset in subclasses)
self.clsname_set = False
def after_content(self):
if self.clsname_set:
self.env.temp_data['rb:class'] = None
class RubyModulelevel(RubyObject):
"""
Description of an object on module level (functions, data).
"""
def needs_arglist(self):
return self.objtype == 'function'
def get_index_text(self, modname, name_cls):
if self.objtype == 'function':
if not modname:
return _('%s() (global function)') % name_cls[0]
return _('%s() (module function in %s)') % (name_cls[0], modname)
else:
return ''
class RubyGloballevel(RubyObject):
"""
Description of an object on module level (functions, data).
"""
def get_index_text(self, modname, name_cls):
if self.objtype == 'global':
return _('%s (global variable)') % name_cls[0]
else:
return ''
class RubyEverywhere(RubyObject):
"""
Description of a class member (methods, attributes).
"""
def needs_arglist(self):
return self.objtype == 'method'
def get_index_text(self, modname, name_cls):
name, cls = name_cls
add_modules = self.env.config.add_module_names
if self.objtype == 'method':
try:
clsname, methname = ruby_rsplit(name)
except ValueError:
if modname:
return _('%s() (in module %s)') % (name, modname)
else:
return '%s()' % name
if modname and add_modules:
return _('%s() (%s::%s method)') % (methname, modname,
clsname)
else:
return _('%s() (%s method)') % (methname, clsname)
else:
return ''
class RubyClasslike(RubyObject):
"""
Description of a class-like object (classes, exceptions).
"""
def get_signature_prefix(self, sig):
return self.objtype + ' '
def get_index_text(self, modname, name_cls):
if self.objtype == 'class':
if not modname:
return _('%s (class)') % name_cls[0]
return _('%s (class in %s)') % (name_cls[0], modname)
elif self.objtype == 'exception':
return name_cls[0]
else:
return ''
def before_content(self):
RubyObject.before_content(self)
if self.names:
self.env.temp_data['rb:class'] = self.names[0][0]
self.clsname_set = True
class RubyClassmember(RubyObject):
"""
Description of a class member (methods, attributes).
"""
def needs_arglist(self):
return self.objtype.endswith('method')
def get_signature_prefix(self, sig):
if self.objtype == 'classmethod':
return "classmethod %s." % self.class_name
elif self.objtype == 'attr_reader':
return "attribute [R] "
elif self.objtype == 'attr_writer':
return "attribute [W] "
elif self.objtype == 'attr_accessor':
return "attribute [R/W] "
return ''
def get_index_text(self, modname, name_cls):
name, cls = name_cls
add_modules = self.env.config.add_module_names
if self.objtype == 'classmethod':
try:
clsname, methname = ruby_rsplit(name)
except ValueError:
return '%s()' % name
if modname:
return _('%s() (%s.%s class method)') % (methname, modname,
clsname)
else:
return _('%s() (%s class method)') % (methname, clsname)
elif self.objtype.startswith('attr'):
try:
clsname, attrname = ruby_rsplit(name)
except ValueError:
return name
if modname and add_modules:
return _('%s (%s.%s attribute)') % (attrname, modname, clsname)
else:
return _('%s (%s attribute)') % (attrname, clsname)
else:
return ''
def before_content(self):
RubyObject.before_content(self)
lastname = self.names and self.names[-1][1]
if lastname and not self.env.temp_data.get('rb:class'):
self.env.temp_data['rb:class'] = lastname.strip('.')
self.clsname_set = True
class RubyModule(Directive):
"""
Directive to mark description of a new module.
"""
has_content = False
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = False
option_spec = {
'platform': lambda x: x,
'synopsis': lambda x: x,
'noindex': directives.flag,
'deprecated': directives.flag,
}
def run(self):
env = self.state.document.settings.env
modname = self.arguments[0].strip()
noindex = 'noindex' in self.options
env.temp_data['rb:module'] = modname
env.domaindata['rb']['modules'][modname] = \
(env.docname, self.options.get('synopsis', ''),
self.options.get('platform', ''), 'deprecated' in self.options)
targetnode = nodes.target('', '', ids=['module-' + modname], ismod=True)
self.state.document.note_explicit_target(targetnode)
ret = [targetnode]
# XXX this behavior of the module directive is a mess...
if 'platform' in self.options:
platform = self.options['platform']
node = nodes.paragraph()
node += nodes.emphasis('', _('Platforms: '))
node += nodes.Text(platform, platform)
ret.append(node)
# the synopsis isn't printed; in fact, it is only used in the
# modindex currently
if not noindex:
indextext = _('%s (module)') % modname
inode = addnodes.index(entries=[('single', indextext,
'module-' + modname, modname)])
ret.append(inode)
return ret
class RubyCurrentModule(Directive):
"""
This directive is just to tell Sphinx that we're documenting
stuff in module foo, but links to module foo won't lead here.
"""
has_content = False
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = False
option_spec = {}
def run(self):
env = self.state.document.settings.env
modname = self.arguments[0].strip()
if modname == 'None':
env.temp_data['rb:module'] = None
else:
env.temp_data['rb:module'] = modname
return []
class RubyXRefRole(XRefRole):
def process_link(self, env, refnode, has_explicit_title, title, target):
if not has_explicit_title:
title = title.lstrip('.') # only has a meaning for the target
title = title.lstrip('#')
if title.startswith("::"):
title = title[2:]
target = target.lstrip('~') # only has a meaning for the title
# if the first character is a tilde, don't display the module/class
# parts of the contents
if title[0:1] == '~':
m = re.search(r"(?:\.)?(?:#)?(?:::)?(.*)\Z", title)
if m:
title = m.group(1)
if not title.startswith("$"):
refnode['rb:module'] = env.temp_data.get('rb:module')
refnode['rb:class'] = env.temp_data.get('rb:class')
# if the first character is a dot, search more specific namespaces first
# else search builtins first
if target[0:1] == '.':
target = target[1:]
refnode['refspecific'] = True
return title, target
class RubyModuleIndex(Index):
"""
Index subclass to provide the Ruby module index.
"""
name = 'modindex'
localname = l_('Ruby Module Index')
shortname = l_('modules')
def generate(self, docnames=None):
content = {}
# list of prefixes to ignore
ignores = self.domain.env.config['modindex_common_prefix']
ignores = sorted(ignores, key=len, reverse=True)
# list of all modules, sorted by module name
modules = sorted(_iteritems(self.domain.data['modules']),
key=lambda x: x[0].lower())
# sort out collapsable modules
prev_modname = ''
num_toplevels = 0
for modname, (docname, synopsis, platforms, deprecated) in modules:
if docnames and docname not in docnames:
continue
for ignore in ignores:
if modname.startswith(ignore):
modname = modname[len(ignore):]
stripped = ignore
break
else:
stripped = ''
# we stripped the whole module name?
if not modname:
modname, stripped = stripped, ''
entries = content.setdefault(modname[0].lower(), [])
package = modname.split('::')[0]
if package != modname:
# it's a submodule
if prev_modname == package:
# first submodule - make parent a group head
entries[-1][1] = 1
elif not prev_modname.startswith(package):
# submodule without parent in list, add dummy entry
entries.append([stripped + package, 1, '', '', '', '', ''])
subtype = 2
else:
num_toplevels += 1
subtype = 0
qualifier = deprecated and _('Deprecated') or ''
entries.append([stripped + modname, subtype, docname,
'module-' + stripped + modname, platforms,
qualifier, synopsis])
prev_modname = modname
# apply heuristics when to collapse modindex at page load:
# only collapse if number of toplevel modules is larger than
# number of submodules
collapse = len(modules) - num_toplevels < num_toplevels
# sort by first letter
content = sorted(_iteritems(content))
return content, collapse
class RubyDomain(Domain):
"""Ruby language domain."""
name = 'rb'
label = 'Ruby'
object_types = {
'function': ObjType(l_('function'), 'func', 'obj'),
'global': ObjType(l_('global variable'), 'global', 'obj'),
'method': ObjType(l_('method'), 'meth', 'obj'),
'class': ObjType(l_('class'), 'class', 'obj'),
'exception': ObjType(l_('exception'), 'exc', 'obj'),
'classmethod': ObjType(l_('class method'), 'meth', 'obj'),
'attr_reader': ObjType(l_('attribute'), 'attr', 'obj'),
'attr_writer': ObjType(l_('attribute'), 'attr', 'obj'),
'attr_accessor': ObjType(l_('attribute'), 'attr', 'obj'),
'const': ObjType(l_('const'), 'const', 'obj'),
'module': ObjType(l_('module'), 'mod', 'obj'),
}
directives = {
'function': RubyModulelevel,
'global': RubyGloballevel,
'method': RubyEverywhere,
'const': RubyEverywhere,
'class': RubyClasslike,
'exception': RubyClasslike,
'classmethod': RubyClassmember,
'attr_reader': RubyClassmember,
'attr_writer': RubyClassmember,
'attr_accessor': RubyClassmember,
'module': RubyModule,
'currentmodule': RubyCurrentModule,
}
roles = {
'func': RubyXRefRole(fix_parens=False),
'global':RubyXRefRole(),
'class': RubyXRefRole(),
'exc': RubyXRefRole(),
'meth': RubyXRefRole(fix_parens=False),
'attr': RubyXRefRole(),
'const': RubyXRefRole(),
'mod': RubyXRefRole(),
'obj': RubyXRefRole(),
}
initial_data = {
'objects': {}, # fullname -> docname, objtype
'modules': {}, # modname -> docname, synopsis, platform, deprecated
}
indices = [
RubyModuleIndex,
]
def clear_doc(self, docname):
for fullname, (fn, _) in list(self.data['objects'].items()):
if fn == docname:
del self.data['objects'][fullname]
for modname, (fn, _, _, _) in list(self.data['modules'].items()):
if fn == docname:
del self.data['modules'][modname]
def find_obj(self, env, modname, classname, name, type, searchorder=0):
"""
Find a Ruby object for "name", perhaps using the given module and/or
classname.
"""
# skip parens
if name[-2:] == '()':
name = name[:-2]
if not name:
return None, None
objects = self.data['objects']
newname = None
if searchorder == 1:
if modname and classname and \
modname + '::' + classname + '#' + name in objects:
newname = modname + '::' + classname + '#' + name
elif modname and classname and \
modname + '::' + classname + '.' + name in objects:
newname = modname + '::' + classname + '.' + name
elif modname and modname + '::' + name in objects:
newname = modname + '::' + name
elif modname and modname + '#' + name in objects:
newname = modname + '#' + name
elif modname and modname + '.' + name in objects:
newname = modname + '.' + name
elif classname and classname + '.' + name in objects:
newname = classname + '.' + name
elif classname and classname + '#' + name in objects:
newname = classname + '#' + name
elif name in objects:
newname = name
else:
if name in objects:
newname = name
elif classname and classname + '.' + name in objects:
newname = classname + '.' + name
elif classname and classname + '#' + name in objects:
newname = classname + '#' + name
elif modname and modname + '::' + name in objects:
newname = modname + '::' + name
elif modname and modname + '#' + name in objects:
newname = modname + '#' + name
elif modname and modname + '.' + name in objects:
newname = modname + '.' + name
elif modname and classname and \
modname + '::' + classname + '#' + name in objects:
newname = modname + '::' + classname + '#' + name
elif modname and classname and \
modname + '::' + classname + '.' + name in objects:
newname = modname + '::' + classname + '.' + name
# special case: object methods
elif type in ('func', 'meth') and '.' not in name and \
'object.' + name in objects:
newname = 'object.' + name
if newname is None:
return None, None
return newname, objects[newname]
def resolve_xref(self, env, fromdocname, builder,
typ, target, node, contnode):
if (typ == 'mod' or
typ == 'obj' and target in self.data['modules']):
docname, synopsis, platform, deprecated = \
self.data['modules'].get(target, ('','','', ''))
if not docname:
return None
else:
title = '%s%s%s' % ((platform and '(%s) ' % platform),
synopsis,
(deprecated and ' (deprecated)' or ''))
return make_refnode(builder, fromdocname, docname,
'module-' + target, contnode, title)
else:
modname = node.get('rb:module')
clsname = node.get('rb:class')
searchorder = node.hasattr('refspecific') and 1 or 0
name, obj = self.find_obj(env, modname, clsname,
target, typ, searchorder)
if not obj:
return None
else:
return make_refnode(builder, fromdocname, obj[0], name,
contnode, name)
def get_objects(self):
for modname, info in _iteritems(self.data['modules']):
yield (modname, modname, 'module', info[0], 'module-' + modname, 0)
for refname, (docname, type) in _iteritems(self.data['objects']):
yield (refname, refname, type, docname, refname, 1)
def setup(app):
app.add_domain(RubyDomain)

View File

@@ -5,7 +5,7 @@ From https://github.com/ryan-roemer/sphinx-bootstrap-theme.
"""
import os
VERSION = (0, 1, 5)
VERSION = (0, 1, 8)
__version__ = ".".join(str(v) for v in VERSION)
__version_full__ = __version__

View File

@@ -6,12 +6,16 @@
{% endfor %}
<li>{{ title }}</li>
<li class="wy-breadcrumbs-aside">
{% if display_github %}
<a href="https://github.com/{{ github_user }}/{{ github_repo }}/blob/{{ github_version }}{{ conf_py_path }}{{ pagename }}{{ source_suffix }}" class="fa fa-github"> Edit on GitHub</a>
{% elif display_bitbucket %}
<a href="https://bitbucket.org/{{ bitbucket_user }}/{{ bitbucket_repo }}/src/{{ bitbucket_version}}{{ conf_py_path }}{{ pagename }}{{ source_suffix }}" class="fa fa-bitbucket"> Edit on Bitbucket</a>
{% elif show_source and has_source and sourcename %}
<a href="{{ pathto('_sources/' + sourcename, true)|e }}" rel="nofollow"> View page source</a>
{% if pagename != "search" %}
{% if display_github %}
<a href="https://{{ github_host|default("github.com") }}/{{ github_user }}/{{ github_repo }}/blob/{{ github_version }}{{ conf_py_path }}{{ pagename }}{{ source_suffix }}" class="fa fa-github"> Edit on GitHub</a>
{% elif display_bitbucket %}
<a href="https://bitbucket.org/{{ bitbucket_user }}/{{ bitbucket_repo }}/src/{{ bitbucket_version}}{{ conf_py_path }}{{ pagename }}{{ source_suffix }}" class="fa fa-bitbucket"> Edit on Bitbucket</a>
{% elif show_source and source_url_prefix %}
<a href="{{ source_url_prefix }}{{ pagename }}{{ source_suffix }}">View page source</a>
{% elif show_source and has_source and sourcename %}
<a href="{{ pathto('_sources/' + sourcename, true)|e }}" rel="nofollow"> View page source</a>
{% endif %}
{% endif %}
</li>
</ul>

View File

@@ -2,10 +2,10 @@
{% if next or prev %}
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
{% if next %}
<a href="{{ next.link|e }}" class="btn btn-neutral float-right" title="{{ next.title|striptags|e }}">Next <span class="fa fa-arrow-circle-right"></span></a>
<a href="{{ next.link|e }}" class="btn btn-neutral float-right" title="{{ next.title|striptags|e }}" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
{% endif %}
{% if prev %}
<a href="{{ prev.link|e }}" class="btn btn-neutral" title="{{ prev.title|striptags|e }}"><span class="fa fa-arrow-circle-left"></span> Previous</a>
<a href="{{ prev.link|e }}" class="btn btn-neutral" title="{{ prev.title|striptags|e }}" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
{% endif %}
</div>
{% endif %}
@@ -28,6 +28,9 @@
</p>
</div>
{%- if show_sphinx %}
{% trans %}Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>{% endtrans %}.
{%- endif %}
</footer>

View File

@@ -12,6 +12,7 @@
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
{{ metatags }}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% block htmltitle %}
<title>{{ title|striptags|e }}{{ titlesuffix }}</title>
@@ -23,7 +24,6 @@
{% endif %}
{# CSS #}
<link href='https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic|Roboto+Slab:400,700|Inconsolata:400,700&subset=latin,cyrillic' rel='stylesheet' type='text/css'>
{# OPENSEARCH #}
{% if not embedded %}
@@ -42,6 +42,10 @@
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
{% endfor %}
{% for cssfile in extra_css_files %}
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
{% endfor %}
{%- block linktags %}
{%- if hasdoc('about') %}
<link rel="author" title="{{ _('About these documents') }}"
@@ -71,7 +75,7 @@
{%- block extrahead %} {% endblock %}
{# Keep modernizr in head - http://modernizr.com/docs/#installing #}
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js"></script>
<script src="_static/js/modernizr.min.js"></script>
</head>
@@ -83,14 +87,27 @@
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-nav-search">
{% block sidebartitle %}
<a href="{{ pathto(master_doc) }}" class="fa fa-home"> {{ project }}</a>
{% endblock %}
{% if logo and theme_logo_only %}
<a href="{{ pathto(master_doc) }}">
{% else %}
<a href="{{ pathto(master_doc) }}" class="icon icon-home"> {{ project }}
{% endif %}
{% if logo %}
{# Not strictly valid HTML, but it's the only way to display/scale it properly, without weird scripting or heaps of work #}
<img src="{{ pathto('_static/' + logo, 1) }}" class="logo" />
{% endif %}
</a>
{% include "searchbox.html" %}
{% endblock %}
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
{% block menu %}
{% set toctree = toctree(maxdepth=2, collapse=False, includehidden=True) %}
{% set toctree = toctree(maxdepth=4, collapse=False, includehidden=True) %}
{% if toctree %}
{{ toctree }}
{% else %}

View File

@@ -0,0 +1,7 @@
{
"version": 3,
"mappings": "CAyDA,SAAY,EACV,qBAAsB,EAAE,UAAW,EAqDrC,QAAS,EARP,IAAK,EAAE,AAAC,EACR,+BAAS,EAEP,MAAO,EAAE,IAAK,EACd,MAAO,EAAE,CAAE,EACb,cAAO,EACL,IAAK,EAAE,GAAI,EC1Gb,SAkBC,EAjBC,UAAW,ECFJ,UAAW,EDGlB,UAAW,EAHqC,KAAM,EAItD,SAAU,EAJsD,KAAM,EAapE,EAAG,EAAE,qCAAwB,EAC7B,EAAG,EAAE,0PAAyE,ECZpF,SAAU,EACR,MAAO,EAAE,WAAY,EACrB,UAAW,EAAE,UAAW,EACxB,SAAU,EAAE,KAAM,EAClB,UAAW,EAAE,KAAM,EACnB,UAAW,EAAE,AAAC,EACd,cAAe,EAAE,MAAO,EAG1B,IAAK,EACH,MAAO,EAAE,WAAY,EACrB,cAAe,EAAE,MAAO,EAIxB,KAAG,EACD,MAAO,EAAE,WAAY,EACvB,sCAAiB,EAGf,IAAK,EAAE,MAAY,EAEvB,KAAM,EACJ,cAAe,EAAE,GAAI,EACrB,UAAW,EAAE,EAAG,EAChB,UAAW,EAAE,KAAM,EAEjB,YAAG,EACD,IAAK,EAAE,IAAI,EACb,oDAAiB,EAGf,aAAc,EAAE,OAAQ,EAG9B,cAAe,EACb,MAAO,EAAE,EAAO,EAElB,gBAAiB,EACf,MAAO,EAAE,EAAO,EAElB,oBAAqB,EACnB,MAAO,EAAE,EAAO,EAElB,sBAAuB,EACrB,MAAO,EAAE,EAAO,EAElB,kBAAmB,EACjB,MAAO,EAAE,EAAO,EAElB,oBAAqB,EACnB,MAAO,EAAE,EAAO,EAElB,oBAAqB,EACnB,MAAO,EAAE,EAAO,EAElB,sBAAuB,EACrB,MAAO,EAAE,EAAO,EAElB,qBAAsB,EACpB,MAAO,EAAE,EAAO,EAElB,uBAAwB,EACtB,MAAO,EAAE,EAAO,ECnElB,YAAa,EACX,OAAQ,EAAE,IAAK,EACf,KAAM,EAAE,AAAC,EACT,GAAI,EAAE,AAAC,EACP,IAAK,EC6E+B,IAAK,ED5EzC,IAAK,ECE+B,MAAyB,EDD7D,SAAU,EAAE,MAAkC,EAC9C,SAAU,EAAE,iBAAiC,EAC7C,UAAW,EEAyB,sDAAM,EFC1C,MAAO,EC+E6B,EAAG,ED9EvC,cAAC,EACC,IAAK,ECqE6B,MAAW,EDpE7C,cAAe,EAAE,GAAI,EACvB,6BAAgB,EACd,MAAO,EAAE,GAAI,EACf,iCAAoB,EAClB,MAAO,EAAE,GAAqB,EAC9B,eAAgB,EAAE,MAAkC,EACpD,MAAO,EAAE,IAAK,EACd,SAAU,EAAE,IAAK,EACjB,QAAS,EAAE,EAAG,EACd,KAAM,EAAE,MAAO,EACf,IAAK,ECiD6B,MAAM,EJgC1C,IAAK,EAAE,AAAC,EACR,iFAAS,EAEP,MAAO,EAAE,IAAK,EACd,MAAO,EAAE,CAAE,EACb,uCAAO,EACL,IAAK,EAAE,GAAI,EGrFX,qCAAG,EACD,IAAK,EClB2B,MAAyB,EDmB3D,0CAAQ,EACN,IAAK,EAAE,GAAI,EACb,4CAAU,EACR,IAAK,EAAE,GAAI,EACb,iDAAiB,EACf,eAAgB,ECQgB,MAAI,EDPpC,IAAK,EC0B2B,GAAM,EDzBxC,wDAAwB,EACtB,eAAgB,ECXgB,MAAO,EDYvC,IAAK,ECzB2B,GAAI,ED0BxC,yCAA8B,EAC5B,MAAO,EAAE,IAAK,EAChB,gCAAmB,EACjB,QAAS,EAAE,EAAG,EACd,MAAO,EAAE,GAAqB,EAC9B,IAAK,ECE6B,GAAwB,EDD1D,MAAO,EAAE,GAAI,EACb,mCAAE,EACA,MAAO,EAAE,IAAK,EACd,KAAM,EAAE,EAAG,EACX,KAAM,EAAE,AAAC,EACT,KAAM,EAAE,KAAM,EACd,MAAO,EAAE,AAAC,EACV,SAAU,EAAE,gBAA6C,EAC3D,mCAAE,EACA,MAAO,EAAE,WAAY,EACrB,KAAM,EAAE,AAAC,EACT,qCAAC,EACC,MAAO,EAAE,WAAY,EACrB,MAAO,EAAE,EAAqB,EAC9B,IAAK,ECjDyB,MAAyB,EDkD7D,sBAAW,EACT,IAAK,EAAE,GAAI,EACX,KAAM,EAAE,GAAI,EACZ,IAAK,EAAE,GAAI,EACX,GAAI,EAAE,GAAI,EACV,KAAM,EAAE,GAAI,EACZ,QAAS,ECkByB,IAAK,EDjBvC,iCAAU,EACR,IAAK,EAAE,GAAI,EACb,+BAAQ,EACN,IAAK,EAAE,GAAI,EACb,oDAA+B,EAC7B,SAAU,EAAE,IAAK,EACjB,6DAAQ,EACN,IAAK,EAAE,GAAI,EACb,+DAAU,EACR,IAAK,EAAE,GAAI,EACf,2CAAoB,EAClB,IAAK,EAAE,GAAI,EACX,KAAM,EAAE,GAAI,EACZ,UAAW,EAAE,GAAI,EACjB,MAAO,EAAE,IAAuB,EAChC,MAAO,EAAE,IAAK,EACd,SAAU,EAAE,KAAM,EGhDpB,mCAAsB,EHmDxB,YAAa,EACX,IAAK,EAAE,EAAG,EACV,MAAO,EAAE,GAAI,EACb,kBAAO,EACL,MAAO,EAAE,IAAK,EAClB,EAAG,EACD,IAAK,EAAE,GAAI,EACX,KAAM,EAAE,GAAI",
"sources": ["../../../bower_components/wyrm/sass/wyrm_core/_mixin.sass","../../../bower_components/bourbon/dist/css3/_font-face.scss","../../../sass/_theme_badge_fa.sass","../../../sass/_theme_badge.sass","../../../bower_components/wyrm/sass/wyrm_core/_wy_variables.sass","../../../sass/_theme_variables.sass","../../../bower_components/neat/app/assets/stylesheets/grid/_media.scss"],
"names": [],
"file": "badge_only.css"
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -1,47 +1,113 @@
$( document ).ready(function() {
function toggleCurrent (elem) {
var parent_li = elem.closest('li');
parent_li.siblings('li.current').removeClass('current');
parent_li.siblings().find('li.current').removeClass('current');
parent_li.find('> ul li.current').removeClass('current');
parent_li.toggleClass('current');
}
$(document).ready(function() {
// Shift nav in mobile when clicking the menu.
$(document).on('click', "[data-toggle='wy-nav-top']", function() {
$("[data-toggle='wy-nav-shift']").toggleClass("shift");
$("[data-toggle='rst-versions']").toggleClass("shift");
$("[data-toggle='wy-nav-shift']").toggleClass("shift");
$("[data-toggle='rst-versions']").toggleClass("shift");
});
// Close menu when you click a link.
// Nav menu link click operations
$(document).on('click', ".wy-menu-vertical .current ul li a", function() {
$("[data-toggle='wy-nav-shift']").removeClass("shift");
$("[data-toggle='rst-versions']").toggleClass("shift");
var target = $(this);
// Close menu when you click a link.
$("[data-toggle='wy-nav-shift']").removeClass("shift");
$("[data-toggle='rst-versions']").toggleClass("shift");
// Handle dynamic display of l3 and l4 nav lists
toggleCurrent(target);
if (typeof(window.SphinxRtdTheme) != 'undefined') {
window.SphinxRtdTheme.StickyNav.hashChange();
}
});
$(document).on('click', "[data-toggle='rst-current-version']", function() {
$("[data-toggle='rst-versions']").toggleClass("shift-up");
});
$("[data-toggle='rst-versions']").toggleClass("shift-up");
});
// Make tables responsive
$("table.docutils:not(.field-list)").wrap("<div class='wy-table-responsive'></div>");
// Add expand links to all parents of nested ul
$('.wy-menu-vertical ul').siblings('a').each(function () {
var link = $(this);
expand = $('<span class="toctree-expand"></span>');
expand.on('click', function (ev) {
toggleCurrent(link);
ev.stopPropagation();
return false;
});
link.prepend(expand);
});
});
// Sphinx theme state
window.SphinxRtdTheme = (function (jquery) {
var stickyNav = (function () {
var navBar,
win,
stickyNavCssClass = 'stickynav',
applyStickNav = function () {
if (navBar.height() <= win.height()) {
navBar.addClass(stickyNavCssClass);
} else {
navBar.removeClass(stickyNavCssClass);
}
},
winScroll = false,
linkScroll = false,
winPosition = 0,
enable = function () {
applyStickNav();
win.on('resize', applyStickNav);
init();
reset();
win.on('hashchange', reset);
// Set scrolling
win.on('scroll', function () {
if (!linkScroll) {
winScroll = true;
}
});
setInterval(function () {
if (winScroll) {
winScroll = false;
var newWinPosition = win.scrollTop(),
navPosition = navBar.scrollTop(),
newNavPosition = navPosition + (newWinPosition - winPosition);
navBar.scrollTop(newNavPosition);
winPosition = newWinPosition;
}
}, 25);
},
init = function () {
navBar = jquery('nav.wy-nav-side:first');
win = jquery(window);
win = jquery(window);
},
reset = function () {
// Get anchor from URL and open up nested nav
var anchor = encodeURI(window.location.hash);
if (anchor) {
try {
var link = $('.wy-menu-vertical')
.find('[href="' + anchor + '"]');
$('.wy-menu-vertical li.toctree-l1 li.current')
.removeClass('current');
link.closest('li.toctree-l2').addClass('current');
link.closest('li.toctree-l3').addClass('current');
link.closest('li.toctree-l4').addClass('current');
}
catch (err) {
console.log("Error expanding nav for anchor", err);
}
}
},
hashChange = function () {
linkScroll = true;
win.one('hashchange', function () {
linkScroll = false;
});
};
jquery(init);
return {
enable : enable
enable: enable,
hashChange: hashChange
};
}());
return {
StickyNav : stickyNav
StickyNav: stickyNav
};
}($));

View File

@@ -6,3 +6,4 @@ stylesheet = css/theme.css
typekit_id = hiw1hhg
analytics_id =
sticky_navigation = False
logo_only =

View File

@@ -8,7 +8,7 @@ _h2load()
_get_comp_words_by_ref cur prev
case $cur in
-*)
COMPREPLY=( $( compgen -W '--threads --connection-window-bits --input-file --help --requests --verbose --version --window-bits --clients --no-tls-proto --header --max-concurrent-streams ' -- "$cur" ) )
COMPREPLY=( $( compgen -W '--threads --connection-window-bits --input-file --help --requests --num-conns --data --verbose --timing-script-file --ciphers --connection-active-timeout --rate --connection-inactivity-timeout --base-uri --window-bits --clients --no-tls-proto --version --header --max-concurrent-streams ' -- "$cur" ) )
;;
*)
_filedir

View File

@@ -1,7 +1,10 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from __future__ import print_function
import subprocess
from StringIO import StringIO
import io
import re
import sys
import os.path
@@ -14,10 +17,10 @@ class Option:
def get_all_options(cmd):
opt_pattern = re.compile(r' (?:(-.), )?(--[^\s\[=]+)(\[)?')
proc = subprocess.Popen([cmd, "--help"], stdout=subprocess.PIPE)
stdoutdata, stderrdata = proc.communicate()
stdoutdata, _ = proc.communicate()
cur_option = None
opts = {}
for line in StringIO(stdoutdata):
for line in io.StringIO(stdoutdata.decode('utf-8')):
match = opt_pattern.match(line)
if not match:
continue
@@ -45,7 +48,7 @@ _{name}()
-*)
COMPREPLY=( $( compgen -W '\
''')
for opt in opts.itervalues():
for opt in opts.values():
out.write(opt.long_opt)
out.write(' ')
@@ -66,8 +69,8 @@ complete -F _{name} {name}
if __name__ == '__main__':
if len(sys.argv) < 2:
print "Generates bash_completion using `/path/to/cmd --help'"
print "Usage: make_bash_completion.py /path/to/cmd"
print("Generates bash_completion using `/path/to/cmd --help'")
print("Usage: make_bash_completion.py /path/to/cmd")
exit(1)
name = os.path.basename(sys.argv[1])
opts = get_all_options(sys.argv[1])

View File

@@ -8,7 +8,7 @@ _nghttp()
_get_comp_words_by_ref cur prev
case $cur in
-*)
COMPREPLY=( $( compgen -W '--verbose --no-dep --get-assets --har --header-table-size --multiply --padding --dep-idle --continuation --connection-window-bits --peer-max-concurrent-streams --timeout --data --no-content-length --version --color --cert --upgrade --remote-name --weight --help --key --null-out --window-bits --stat --header ' -- "$cur" ) )
COMPREPLY=( $( compgen -W '--no-push --verbose --no-dep --get-assets --har --header-table-size --multiply --padding --hexdump --max-concurrent-streams --continuation --connection-window-bits --peer-max-concurrent-streams --timeout --data --no-content-length --version --color --cert --upgrade --remote-name --trailer --weight --help --key --null-out --window-bits --stat --header ' -- "$cur" ) )
;;
*)
_filedir

View File

@@ -8,7 +8,7 @@ _nghttpd()
_get_comp_words_by_ref cur prev
case $cur in
-*)
COMPREPLY=( $( compgen -W '--error-gzip --push --header-table-size --htdocs --padding --verbose --version --help --daemon --verify-client --workers --no-tls --color --early-response --dh-param-file ' -- "$cur" ) )
COMPREPLY=( $( compgen -W '--error-gzip --push --header-table-size --trailer --htdocs --address --padding --verbose --version --help --hexdump --dh-param-file --daemon --verify-client --echo-upload --workers --no-tls --color --early-response --max-concurrent-streams ' -- "$cur" ) )
;;
*)
_filedir

View File

@@ -8,7 +8,7 @@ _nghttpx()
_get_comp_words_by_ref cur prev
case $cur in
-*)
COMPREPLY=( $( compgen -W '--frontend-http2-connection-window-bits --worker-read-rate --frontend-no-tls --frontend-http2-dump-request-header --daemon --write-rate --altsvc --frontend-http2-dump-response-header --backend-http1-connections-per-frontend --tls-ticket-key-file --ciphers --verify-client-cacert --backend-keep-alive-timeout --strip-incoming-x-forwarded-for --errorlog-file --private-key-passwd-file --version --backlog --backend-http-proxy-uri --add-response-header --backend-write-timeout --backend-request-buffer --add-x-forwarded-for --write-burst --backend-http2-connection-window-bits --insecure --rlimit-nofile --backend-http2-window-bits --tls-proto-list --no-location-rewrite --padding --accesslog-syslog --conf --http2-max-concurrent-streams --client-proxy --worker-frontend-connections --cacert --frontend-read-timeout --worker-write-burst --npn-list --syslog-facility --backend-http1-connections-per-host --no-server-push --client --http2-bridge --no-via --user --stream-write-timeout --backend-response-buffer --http2-no-cookie-crumbling --backend-read-timeout --stream-read-timeout --workers --worker-read-burst --tls-ctx-per-worker --dh-param-file --errorlog-syslog --frontend --accesslog-file --http2-proxy --read-burst --accesslog-format --frontend-http2-window-bits --backend-no-tls --client-private-key-file --pid-file --client-cert-file --no-host-rewrite --log-level --worker-write-rate --help --backend-tls-sni-field --subcert --frontend-frame-debug --frontend-write-timeout --verify-client --read-rate --frontend-http2-read-timeout --backend-ipv4 --listener-disable-timeout --backend-ipv6 --backend ' -- "$cur" ) )
COMPREPLY=( $( compgen -W '--worker-read-rate --frontend-no-tls --frontend-http2-dump-response-header --backend-http1-connections-per-frontend --tls-ticket-key-file --verify-client-cacert --include --backend-request-buffer --backend-http2-connection-window-bits --conf --worker-write-burst --npn-list --fetch-ocsp-response-file --stream-read-timeout --tls-ticket-key-memcached --accesslog-syslog --frontend-http2-read-timeout --listener-disable-timeout --frontend-http2-connection-window-bits --ciphers --strip-incoming-x-forwarded-for --private-key-passwd-file --backend-keep-alive-timeout --backend-http-proxy-uri --backend-http1-connections-per-host --rlimit-nofile --no-via --ocsp-update-interval --backend-write-timeout --client --tls-ticket-key-memcached-max-retry --http2-no-cookie-crumbling --worker-read-burst --client-proxy --http2-bridge --accesslog-format --errorlog-syslog --errorlog-file --http2-max-concurrent-streams --frontend-write-timeout --tls-ticket-key-cipher --response-phase-file --read-burst --backend-ipv4 --backend-ipv6 --backend --insecure --log-level --host-rewrite --tls-proto-list --backend-http2-connections-per-worker --tls-ticket-key-memcached-interval --dh-param-file --worker-frontend-connections --header-field-buffer --no-server-push --no-location-rewrite --tls-session-cache-memcached --no-ocsp --backend-response-buffer --workers --frontend-http2-window-bits --worker-write-rate --add-request-header --backend-tls-sni-field --subcert --help --frontend-frame-debug --pid-file --frontend-http2-dump-request-header --daemon --write-rate --altsvc --user --add-x-forwarded-for --syslog-facility --frontend-read-timeout --tls-ticket-key-memcached-max-fail --backlog --write-burst --backend-http2-window-bits --padding --stream-write-timeout --cacert --version --verify-client --request-phase-file --backend-read-timeout --frontend --accesslog-file --http2-proxy --max-header-fields --backend-no-tls --client-private-key-file --client-cert-file --accept-proxy-protocol --add-response-header --read-rate ' -- "$cur" ) )
;;
*)
_filedir

View File

@@ -41,6 +41,8 @@ import sys, os
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
sys.path.append(os.path.abspath('_exts'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
@@ -48,7 +50,7 @@ import sys, os
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = []
extensions = ['sphinxcontrib.rubydomain']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['@top_srcdir@/_templates']

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "H2LOAD" "1" "March 27, 2015" "0.7.9" "nghttp2"
.TH "H2LOAD" "1" "September 12, 2015" "1.3.1" "nghttp2"
.SH NAME
h2load \- HTTP/2 benchmarking tool
.
@@ -44,7 +44,8 @@ URIs are used in this order for each client. All URIs
are used, then first URI is used and then 2nd URI, and
so on. The scheme, host and port in the subsequent
URIs, if present, are ignored. Those in the first URI
are used solely.
are used solely. Definition of a base URI overrides all
scheme, host or port values.
.UNINDENT
.SH OPTIONS
.INDENT 0.0
@@ -70,15 +71,16 @@ Default: \fB1\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-i, \-\-input\-file=<FILE>
Path of a file with multiple URIs are seperated by EOLs.
.B \-i, \-\-input\-file=<PATH>
Path of a file with multiple URIs are separated by EOLs.
This option will disable URIs getting from command\-line.
If \(aq\-\(aq is given as <FILE>, URIs will be read from stdin.
If \(aq\-\(aq is given as <PATH>, URIs will be read from stdin.
URIs are used in this order for each client. All URIs
are used, then first URI is used and then 2nd URI, and
so on. The scheme, host and port in the subsequent
URIs, if present, are ignored. Those in the first URI
are used solely.
are used solely. Definition of a base URI overrides all
scheme, host or port values.
.UNINDENT
.INDENT 0.0
.TP
@@ -93,6 +95,8 @@ Default: \fBauto\fP
.B \-w, \-\-window\-bits=<N>
Sets the stream level initial window size to (2**<N>)\-1.
For SPDY, 2**<N> is used instead.
.sp
Default: \fB30\fP
.UNINDENT
.INDENT 0.0
.TP
@@ -101,6 +105,8 @@ Sets the connection level initial window size to
(2**<N>)\-1. For SPDY, if <N> is strictly less than 16,
this option is ignored. Otherwise 2**<N> is used for
SPDY.
.sp
Default: \fB30\fP
.UNINDENT
.INDENT 0.0
.TP
@@ -109,21 +115,100 @@ Add/Override a header to the requests.
.UNINDENT
.INDENT 0.0
.TP
.B \-p, \-\-no\-tls\-proto=<PROTOID>
Specify ALPN identifier of the protocol to be used when
accessing http URI without SSL/TLS.
Available protocols: spdy/2, spdy/3, spdy/3.1 and h2c\-14
.sp
Default: \fBh2c\-14\fP
.B \-\-ciphers=<SUITE>
Set allowed cipher list. The format of the string is
described in OpenSSL ciphers(1).
.UNINDENT
.INDENT 0.0
.TP
.B \-d, \-\-data=<FILE>
.B \-p, \-\-no\-tls\-proto=<PROTOID>
Specify ALPN identifier of the protocol to be used when
accessing http URI without SSL/TLS.
Available protocols: spdy/2, spdy/3, spdy/3.1 and h2c
.sp
Default: \fBh2c\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-d, \-\-data=<PATH>
Post FILE to server. The request method is changed to
POST.
.UNINDENT
.INDENT 0.0
.TP
.B \-r, \-\-rate=<N>
Specifies the fixed rate at which connections are
created. The rate must be a positive integer,
representing the number of connections to be made per
second. When the rate is 0, the program will run as it
normally does, creating connections at whatever variable
rate it wants. The default value for this option is 0.
.UNINDENT
.INDENT 0.0
.TP
.B \-C, \-\-num\-conns=<N>
Specifies the total number of connections to create.
The total number of connections must be a positive
integer. On each connection, \fI\%\-m\fP requests are made. The
test stops once as soon as the <N> connections have
either completed or failed. When the number of
connections is 0, the program will run as it normally
does, creating as many connections as it needs in order
to make the \fI\%\-n\fP requests specified. The default value
for this option is 0. The \fI\%\-n\fP option is not required if
the \fI\%\-C\fP option is being used.
.UNINDENT
.INDENT 0.0
.TP
.B \-T, \-\-connection\-active\-timeout=<N>
Specifies the maximum time that h2load is willing to
keep a connection open, regardless of the activity on
said connection. <N> must be a positive integer,
specifying the number of seconds to wait. When no
timeout value is set (either active or inactive), h2load
will keep a connection open indefinitely, waiting for a
response.
.UNINDENT
.INDENT 0.0
.TP
.B \-N, \-\-connection\-inactivity\-timeout=<N>
Specifies the amount of time that h2load is willing to
wait to see activity on a given connection. <N> must be
a positive integer, specifying the number of seconds to
wait. When no timeout value is set (either active or
inactive), h2load will keep a connection open
indefinitely, waiting for a response.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-timing\-script\-file=<PATH>
Path of a file containing one or more lines separated by
EOLs. Each script line is composed of two tab\-separated
fields. The first field represents the time offset from
the start of execution, expressed as a positive value of
milliseconds with microsecond resolution. The second
field represents the URI. This option will disable URIs
getting from command\-line. If \(aq\-\(aq is given as <PATH>,
script lines will be read from stdin. Script lines are
used in order for each client. If \fI\%\-n\fP is given, it must be
less than or equal to the number of script lines, larger
values are clamped to the number of script lines. If \fI\%\-n\fP
is not given, the number of requests will default to the
number of script lines. The scheme, host and port defined
in the first URI are used solely. Values contained in
other URIs, if present, are ignored. Definition of a
base URI overrides all scheme, host or port values.
.UNINDENT
.INDENT 0.0
.TP
.B \-B, \-\-base\-uri=<URI>
Specify URI from which the scheme, host and port will be
used for all requests. The base URI overrides all
values defined either at the command line or inside
input files.
.UNINDENT
.INDENT 0.0
.TP
.B \-v, \-\-verbose
Output debug information.
.UNINDENT
@@ -162,9 +247,14 @@ The number of requests failed, including HTTP level failures
.TP
.B errored
The number of requests failed, except for HTTP level failures.
status code. This is the subset of the number reported in
\fBfailed\fP and most likely the network level failures or stream
was reset by RST_STREAM.
This is the subset of the number reported in \fBfailed\fP and most
likely the network level failures or stream was reset by
RST_STREAM.
.TP
.B timeout
The number of requests whose connection timed out before they were
completed. This is the subset of the number reported in
\fBerrored\fP\&.
.UNINDENT
.TP
.B status codes
@@ -201,13 +291,63 @@ The maximum time taken for request and response.
The mean time taken for request and response.
.TP
.B sd
The standard deviation of the time for request and response.
The standard deviation of the time taken for request and response.
.TP
.B +/\- sd
The fraction of the number of requests within standard deviation
range (mean +/\- sd) against total number of successful requests.
.UNINDENT
.TP
.B time for connect
.INDENT 7.0
.TP
.B min
The minimum time taken to connect to a server.
.TP
.B max
The maximum time taken to connect to a server.
.TP
.B mean
The mean time taken to connect to a server.
.TP
.B sd
The standard deviation of the time taken to connect to a server.
.TP
.B +/\- sd
The fraction of the number of connections within standard
deviation range (mean +/\- sd) against total number of successful
connections.
.UNINDENT
.TP
.B time for 1st byte (of (decrypted in case of TLS) application data)
.INDENT 7.0
.TP
.B min
The minimum time taken to get 1st byte from a server.
.TP
.B max
The maximum time taken to get 1st byte from a server.
.TP
.B mean
The mean time taken to get 1st byte from a server.
.TP
.B sd
The standard deviation of the time taken to get 1st byte from a
server.
.TP
.B +/\- sd
The fraction of the number of connections within standard
deviation range (mean +/\- sd) against total number of successful
connections.
.UNINDENT
.UNINDENT
.SH FLOW CONTROL
.sp
h2load sets large flow control window by default, and effectively
disables flow control to avoid under utilization of server
performance. To set smaller flow control window, use \fI\%\-w\fP and
\fI\%\-W\fP options. For example, use \fB\-w16 \-W16\fP to set default
window size described in HTTP/2 and SPDY protocol specification.
.SH SEE ALSO
.sp
\fInghttp(1)\fP, \fInghttpd(1)\fP, \fInghttpx(1)\fP

View File

@@ -1,4 +1,8 @@
.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY.
.. program:: h2load
h2load(1)
=========
@@ -19,7 +23,8 @@ benchmarking tool for HTTP/2 and SPDY server
are used, then first URI is used and then 2nd URI, and
so on. The scheme, host and port in the subsequent
URIs, if present, are ignored. Those in the first URI
are used solely.
are used solely. Definition of a base URI overrides all
scheme, host or port values.
OPTIONS
-------
@@ -42,16 +47,17 @@ OPTIONS
Default: ``1``
.. option:: -i, --input-file=<FILE>
.. option:: -i, --input-file=<PATH>
Path of a file with multiple URIs are seperated by EOLs.
Path of a file with multiple URIs are separated by EOLs.
This option will disable URIs getting from command-line.
If '-' is given as <FILE>, URIs will be read from stdin.
If '-' is given as <PATH>, URIs will be read from stdin.
URIs are used in this order for each client. All URIs
are used, then first URI is used and then 2nd URI, and
so on. The scheme, host and port in the subsequent
URIs, if present, are ignored. Those in the first URI
are used solely.
are used solely. Definition of a base URI overrides all
scheme, host or port values.
.. option:: -m, --max-concurrent-streams=(auto|<N>)
@@ -65,6 +71,8 @@ OPTIONS
Sets the stream level initial window size to (2\*\*<N>)-1.
For SPDY, 2**<N> is used instead.
Default: ``30``
.. option:: -W, --connection-window-bits=<N>
Sets the connection level initial window size to
@@ -72,23 +80,97 @@ OPTIONS
this option is ignored. Otherwise 2\*\*<N> is used for
SPDY.
Default: ``30``
.. option:: -H, --header=<HEADER>
Add/Override a header to the requests.
.. option:: --ciphers=<SUITE>
Set allowed cipher list. The format of the string is
described in OpenSSL ciphers(1).
.. option:: -p, --no-tls-proto=<PROTOID>
Specify ALPN identifier of the protocol to be used when
accessing http URI without SSL/TLS.
Available protocols: spdy/2, spdy/3, spdy/3.1 and h2c-14
Available protocols: spdy/2, spdy/3, spdy/3.1 and h2c
Default: ``h2c-14``
Default: ``h2c``
.. option:: -d, --data=<FILE>
.. option:: -d, --data=<PATH>
Post FILE to server. The request method is changed to
POST.
.. option:: -r, --rate=<N>
Specifies the fixed rate at which connections are
created. The rate must be a positive integer,
representing the number of connections to be made per
second. When the rate is 0, the program will run as it
normally does, creating connections at whatever variable
rate it wants. The default value for this option is 0.
.. option:: -C, --num-conns=<N>
Specifies the total number of connections to create.
The total number of connections must be a positive
integer. On each connection, :option:`-m` requests are made. The
test stops once as soon as the <N> connections have
either completed or failed. When the number of
connections is 0, the program will run as it normally
does, creating as many connections as it needs in order
to make the :option:`-n` requests specified. The default value
for this option is 0. The :option:`-n` option is not required if
the :option:`-C` option is being used.
.. option:: -T, --connection-active-timeout=<N>
Specifies the maximum time that h2load is willing to
keep a connection open, regardless of the activity on
said connection. <N> must be a positive integer,
specifying the number of seconds to wait. When no
timeout value is set (either active or inactive), h2load
will keep a connection open indefinitely, waiting for a
response.
.. option:: -N, --connection-inactivity-timeout=<N>
Specifies the amount of time that h2load is willing to
wait to see activity on a given connection. <N> must be
a positive integer, specifying the number of seconds to
wait. When no timeout value is set (either active or
inactive), h2load will keep a connection open
indefinitely, waiting for a response.
.. option:: --timing-script-file=<PATH>
Path of a file containing one or more lines separated by
EOLs. Each script line is composed of two tab-separated
fields. The first field represents the time offset from
the start of execution, expressed as a positive value of
milliseconds with microsecond resolution. The second
field represents the URI. This option will disable URIs
getting from command-line. If '-' is given as <PATH>,
script lines will be read from stdin. Script lines are
used in order for each client. If :option:`-n` is given, it must be
less than or equal to the number of script lines, larger
values are clamped to the number of script lines. If :option:`-n`
is not given, the number of requests will default to the
number of script lines. The scheme, host and port defined
in the first URI are used solely. Values contained in
other URIs, if present, are ignored. Definition of a
base URI overrides all scheme, host or port values.
.. option:: -B, --base-uri=<URI>
Specify URI from which the scheme, host and port will be
used for all requests. The base URI overrides all
values defined either at the command line or inside
input files.
.. option:: -v, --verbose
Output debug information.
@@ -119,9 +201,13 @@ requests
(non-successful HTTP status code).
errored
The number of requests failed, except for HTTP level failures.
status code. This is the subset of the number reported in
``failed`` and most likely the network level failures or stream
was reset by RST_STREAM.
This is the subset of the number reported in ``failed`` and most
likely the network level failures or stream was reset by
RST_STREAM.
timeout
The number of requests whose connection timed out before they were
completed. This is the subset of the number reported in
``errored``.
status codes
The number of status code h2load received.
@@ -147,11 +233,49 @@ time for request
mean
The mean time taken for request and response.
sd
The standard deviation of the time for request and response.
The standard deviation of the time taken for request and response.
+/- sd
The fraction of the number of requests within standard deviation
range (mean +/- sd) against total number of successful requests.
time for connect
min
The minimum time taken to connect to a server.
max
The maximum time taken to connect to a server.
mean
The mean time taken to connect to a server.
sd
The standard deviation of the time taken to connect to a server.
+/- sd
The fraction of the number of connections within standard
deviation range (mean +/- sd) against total number of successful
connections.
time for 1st byte (of (decrypted in case of TLS) application data)
min
The minimum time taken to get 1st byte from a server.
max
The maximum time taken to get 1st byte from a server.
mean
The mean time taken to get 1st byte from a server.
sd
The standard deviation of the time taken to get 1st byte from a
server.
+/- sd
The fraction of the number of connections within standard
deviation range (mean +/- sd) against total number of successful
connections.
FLOW CONTROL
------------
h2load sets large flow control window by default, and effectively
disables flow control to avoid under utilization of server
performance. To set smaller flow control window, use :option:`-w` and
:option:`-W` options. For example, use ``-w16 -W16`` to set default
window size described in HTTP/2 and SPDY protocol specification.
SEE ALSO
--------

View File

@@ -16,9 +16,13 @@ requests
(non-successful HTTP status code).
errored
The number of requests failed, except for HTTP level failures.
status code. This is the subset of the number reported in
``failed`` and most likely the network level failures or stream
was reset by RST_STREAM.
This is the subset of the number reported in ``failed`` and most
likely the network level failures or stream was reset by
RST_STREAM.
timeout
The number of requests whose connection timed out before they were
completed. This is the subset of the number reported in
``errored``.
status codes
The number of status code h2load received.
@@ -44,11 +48,49 @@ time for request
mean
The mean time taken for request and response.
sd
The standard deviation of the time for request and response.
The standard deviation of the time taken for request and response.
+/- sd
The fraction of the number of requests within standard deviation
range (mean +/- sd) against total number of successful requests.
time for connect
min
The minimum time taken to connect to a server.
max
The maximum time taken to connect to a server.
mean
The mean time taken to connect to a server.
sd
The standard deviation of the time taken to connect to a server.
+/- sd
The fraction of the number of connections within standard
deviation range (mean +/- sd) against total number of successful
connections.
time for 1st byte (of (decrypted in case of TLS) application data)
min
The minimum time taken to get 1st byte from a server.
max
The maximum time taken to get 1st byte from a server.
mean
The mean time taken to get 1st byte from a server.
sd
The standard deviation of the time taken to get 1st byte from a
server.
+/- sd
The fraction of the number of connections within standard
deviation range (mean +/- sd) against total number of successful
connections.
FLOW CONTROL
------------
h2load sets large flow control window by default, and effectively
disables flow control to avoid under utilization of server
performance. To set smaller flow control window, use :option:`-w` and
:option:`-W` options. For example, use ``-w16 -W16`` to set default
window size described in HTTP/2 and SPDY protocol specification.
SEE ALSO
--------

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# nghttp2 - HTTP/2 C Library
# Copyright (c) 2012 Tatsuhiro Tsujikawa
@@ -23,20 +24,24 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Generates API reference from C source code.
from __future__ import unicode_literals
from __future__ import print_function # At least python 2.6 is required
import re, sys, argparse
import re, sys, argparse, os.path
class FunctionDoc:
def __init__(self, name, content, domain):
self.name = name
self.content = content
self.domain = domain
if self.domain == 'function':
self.funcname = re.search(r'(nghttp2_[^ )]+)\(', self.name).group(1)
def write(self, out):
print('''.. {}:: {}'''.format(self.domain, self.name))
print('')
out.write('.. {}:: {}\n'.format(self.domain, self.name))
out.write('\n')
for line in self.content:
print(' {}'.format(line))
out.write(' {}\n'.format(line))
class StructDoc:
def __init__(self, name, content, members, member_domain):
@@ -47,17 +52,17 @@ class StructDoc:
def write(self, out):
if self.name:
print('''.. type:: {}'''.format(self.name))
print('')
out.write('.. type:: {}\n'.format(self.name))
out.write('\n')
for line in self.content:
print(' {}'.format(line))
print('')
out.write(' {}\n'.format(line))
out.write('\n')
for name, content in self.members:
print(''' .. {}:: {}'''.format(self.member_domain, name))
print('')
out.write(' .. {}:: {}\n'.format(self.member_domain, name))
out.write('\n')
for line in content:
print(''' {}'''.format(line))
print('')
out.write(' {}\n'.format(line))
out.write('\n')
class MacroDoc:
def __init__(self, name, content):
@@ -65,10 +70,10 @@ class MacroDoc:
self.content = content
def write(self, out):
print('''.. macro:: {}'''.format(self.name))
print('')
out.write('''.. macro:: {}\n'''.format(self.name))
out.write('\n')
for line in self.content:
print(' {}'.format(line))
out.write(' {}\n'.format(line))
def make_api_ref(infiles):
macros = []
@@ -93,19 +98,65 @@ def make_api_ref(infiles):
enums.append(process_enum(infile))
elif doctype == '@macro':
macros.append(process_macro(infile))
return macros, enums, types, functions
alldocs = [('Macros', macros),
('Enums', enums),
('Types (structs, unions and typedefs)', types),
('Functions', functions)]
for title, docs in alldocs:
if not docs:
continue
print(title)
print('-'*len(title))
for doc in docs:
doc.write(sys.stdout)
print('')
print('')
def output(
indexfile, macrosfile, enumsfile, typesfile, funcsdir,
macros, enums, types, functions):
indexfile.write('''
API Reference
=============
.. toctree::
:maxdepth: 1
macros
enums
types
''')
for doc in functions:
indexfile.write(' {}\n'.format(doc.funcname))
macrosfile.write('''
Macros
======
''')
for doc in macros:
doc.write(macrosfile)
enumsfile.write('''
Enums
=====
''')
for doc in enums:
doc.write(enumsfile)
typesfile.write('''
Types (structs, unions and typedefs)
====================================
''')
for doc in types:
doc.write(typesfile)
for doc in functions:
with open(os.path.join(funcsdir, doc.funcname + '.rst'), 'w') as f:
f.write('''
{funcname}
{secul}
Synopsis
--------
*#include <nghttp2/nghttp2.h>*
'''.format(funcname=doc.funcname, secul='='*len(doc.funcname)))
doc.write(f)
def process_macro(infile):
content = read_content(infile)
@@ -174,6 +225,7 @@ def process_function(domain, infile):
func_proto = ''.join(func_proto)
func_proto = re.sub(r';\n$', '', func_proto)
func_proto = re.sub(r'\s+', ' ', func_proto)
func_proto = re.sub(r'NGHTTP2_EXTERN ', '', func_proto)
return FunctionDoc(func_proto, content, domain)
def read_content(infile):
@@ -199,12 +251,30 @@ def transform_content(content):
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Generate API reference")
parser.add_argument('--header', type=argparse.FileType('r'),
help='header inserted at the top of the page')
parser.add_argument('index', type=argparse.FileType('w'),
help='index output file')
parser.add_argument('macros', type=argparse.FileType('w'),
help='macros section output file. The filename should be macros.rst')
parser.add_argument('enums', type=argparse.FileType('w'),
help='enums section output file. The filename should be enums.rst')
parser.add_argument('types', type=argparse.FileType('w'),
help='types section output file. The filename should be types.rst')
parser.add_argument('funcsdir',
help='functions doc output dir')
parser.add_argument('files', nargs='+', type=argparse.FileType('r'),
help='source file')
args = parser.parse_args()
if args.header:
print(args.header.read())
macros = []
enums = []
types = []
funcs = []
for infile in args.files:
make_api_ref(args.files)
m, e, t, f = make_api_ref(args.files)
macros.extend(m)
enums.extend(e)
types.extend(t)
funcs.extend(f)
funcs.sort(key=lambda x: x.funcname)
output(
args.index, args.macros, args.enums, args.types, args.funcsdir,
macros, enums, types, funcs)

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "NGHTTP" "1" "March 27, 2015" "0.7.9" "nghttp2"
.TH "NGHTTP" "1" "September 12, 2015" "1.3.1" "nghttp2"
.SH NAME
nghttp \- HTTP/2 experimental client
.
@@ -64,8 +64,9 @@ yet.
.UNINDENT
.INDENT 0.0
.TP
.B \-t, \-\-timeout=<SEC>
Timeout each request after <SEC> seconds.
.B \-t, \-\-timeout=<DURATION>
Timeout each request after <DURATION>. Set 0 to disable
timeout.
.UNINDENT
.INDENT 0.0
.TP
@@ -104,8 +105,8 @@ Add a header to the requests. Example: \fI\%\-H\fP\(aq:method: PUT\(aq
.B \-\-trailer=<HEADER>
Add a trailer header to the requests. <HEADER> must not
include pseudo header field (header field name starting
with \(aq:\(aq). To send trailer, one must use \fI\-d\fP option to
send request body. Example: \fI\-\-trailer\fP \(aqfoo: bar\(aq.
with \(aq:\(aq). To send trailer, one must use \fI\%\-d\fP option to
send request body. Example: \fI\%\-\-trailer\fP \(aqfoo: bar\(aq.
.UNINDENT
.INDENT 0.0
.TP
@@ -121,7 +122,7 @@ PEM format.
.UNINDENT
.INDENT 0.0
.TP
.B \-d, \-\-data=<FILE>
.B \-d, \-\-data=<PATH>
Post FILE to server. If \(aq\-\(aq is given, data will be read
from stdin.
.UNINDENT
@@ -135,7 +136,7 @@ requested twice. This option disables it too.
.TP
.B \-u, \-\-upgrade
Perform HTTP Upgrade for HTTP/2. This option is ignored
if the request URI has https scheme. If \fI\-d\fP is used, the
if the request URI has https scheme. If \fI\%\-d\fP is used, the
HTTP upgrade request is performed with OPTIONS method.
.UNINDENT
.INDENT 0.0
@@ -166,8 +167,8 @@ Specify 0 to disable padding.
.UNINDENT
.INDENT 0.0
.TP
.B \-r, \-\-har=<FILE>
Output HTTP transactions <FILE> in HAR format. If \(aq\-\(aq
.B \-r, \-\-har=<PATH>
Output HTTP transactions <PATH> in HAR format. If \(aq\-\(aq
is given, data is written to stdout.
.UNINDENT
.INDENT 0.0
@@ -192,11 +193,6 @@ Don\(aqt send dependency based priority hint to server.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-dep\-idle
Use idle streams as anchor nodes to express priority.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-hexdump
Display the incoming traffic in hexadecimal (Canonical
hex+ASCII display). If SSL/TLS is used, decrypted data
@@ -204,6 +200,17 @@ are used.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-no\-push
Disable server push.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-max\-concurrent\-streams=<N>
The number of concurrent pushed streams this client
accepts.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-version
Display version information and exit.
.UNINDENT
@@ -215,6 +222,68 @@ Display this help and exit.
.sp
The <SIZE> argument is an integer and an optional unit (e.g., 10K is
10 * 1024). Units are K, M and G (powers of 1024).
.sp
The <DURATION> argument is an integer and an optional unit (e.g., 1s
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
(hours, minutes, seconds and milliseconds, respectively). If a unit
is omitted, a second is used as unit.
.SH DEPENDENCY BASED PRIORITY
.sp
nghttp sends priority hints to server by default unless
\fI\%\-\-no\-dep\fP is used. nghttp mimics the way Firefox employs to
manages dependency using idle streams. We follows the behaviour of
Firefox Nightly as of April, 2015, and nghttp\(aqs behaviour is very
static and could be different from Firefox in detail. But reproducing
the same behaviour of Firefox is not our goal. The goal is provide
the easy way to test out the dependency priority in server
implementation.
.sp
When connection is established, nghttp sends 5 PRIORITY frames to idle
streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency
tree:
.INDENT 0.0
.INDENT 3.5
.sp
.nf
.ft C
+\-\-\-\-\-+
|id=0 |
+\-\-\-\-\-+
^ ^ ^
w=201 / | \e w=1
/ | \e
/ w=101| \e
+\-\-\-\-\-+ +\-\-\-\-\-+ +\-\-\-\-\-+
|id=3 | |id=5 | |id=7 |
+\-\-\-\-\-+ +\-\-\-\-\-+ +\-\-\-\-\-+
^ ^
w=1 | w=1 |
| |
+\-\-\-\-\-+ +\-\-\-\-\-+
|id=11| |id=9 |
+\-\-\-\-\-+ +\-\-\-\-\-+
.ft P
.fi
.UNINDENT
.UNINDENT
.sp
In the above figure, \fBid\fP means stream ID, and \fBw\fP means weight.
The stream 0 is non\-existence stream, and forms the root of the tree.
The stream 7 and 9 are not used for now.
.sp
The URIs given in the command\-line depend on stream 11 with the weight
given in \fI\%\-p\fP option, which defaults to 16.
.sp
If \fI\%\-a\fP option is used, nghttp parses the resource pointed by
URI given in command\-line as html, and extracts resource links from
it. When requesting those resources, nghttp uses dependency according
to its resource type.
.sp
For CSS, and Javascript files inside "head" element, they depend on
stream 3 with the weight 2. The Javascript files outside "head"
element depend on stream 5 with the weight 2. The mages depend on
stream 11 with the weight 12. The other resources (e.g., icon) depend
on stream 11 with the weight 2.
.SH SEE ALSO
.sp
\fInghttpd(1)\fP, \fInghttpx(1)\fP, \fIh2load(1)\fP

View File

@@ -1,4 +1,8 @@
.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY.
.. program:: nghttp
nghttp(1)
=========
@@ -36,9 +40,10 @@ OPTIONS
'index.html' is used as a filename. Not implemented
yet.
.. option:: -t, --timeout=<SEC>
.. option:: -t, --timeout=<DURATION>
Timeout each request after <SEC> seconds.
Timeout each request after <DURATION>. Set 0 to disable
timeout.
.. option:: -w, --window-bits=<N>
@@ -84,7 +89,7 @@ OPTIONS
Use the client private key file. The file must be in
PEM format.
.. option:: -d, --data=<FILE>
.. option:: -d, --data=<PATH>
Post FILE to server. If '-' is given, data will be read
from stdin.
@@ -122,9 +127,9 @@ OPTIONS
Add at most <N> bytes to a frame payload as padding.
Specify 0 to disable padding.
.. option:: -r, --har=<FILE>
.. option:: -r, --har=<PATH>
Output HTTP transactions <FILE> in HAR format. If '-'
Output HTTP transactions <PATH> in HAR format. If '-'
is given, data is written to stdout.
.. option:: --color
@@ -143,16 +148,21 @@ OPTIONS
Don't send dependency based priority hint to server.
.. option:: --dep-idle
Use idle streams as anchor nodes to express priority.
.. option:: --hexdump
Display the incoming traffic in hexadecimal (Canonical
hex+ASCII display). If SSL/TLS is used, decrypted data
are used.
.. option:: --no-push
Disable server push.
.. option:: --max-concurrent-streams=<N>
The number of concurrent pushed streams this client
accepts.
.. option:: --version
Display version information and exit.
@@ -162,9 +172,66 @@ OPTIONS
Display this help and exit.
The <SIZE> argument is an integer and an optional unit (e.g., 10K is
10 * 1024). Units are K, M and G (powers of 1024).
The <DURATION> argument is an integer and an optional unit (e.g., 1s
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
(hours, minutes, seconds and milliseconds, respectively). If a unit
is omitted, a second is used as unit.
DEPENDENCY BASED PRIORITY
-------------------------
nghttp sends priority hints to server by default unless
:option:`--no-dep` is used. nghttp mimics the way Firefox employs to
manages dependency using idle streams. We follows the behaviour of
Firefox Nightly as of April, 2015, and nghttp's behaviour is very
static and could be different from Firefox in detail. But reproducing
the same behaviour of Firefox is not our goal. The goal is provide
the easy way to test out the dependency priority in server
implementation.
When connection is established, nghttp sends 5 PRIORITY frames to idle
streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency
tree::
+-----+
|id=0 |
+-----+
^ ^ ^
w=201 / | \ w=1
/ | \
/ w=101| \
+-----+ +-----+ +-----+
|id=3 | |id=5 | |id=7 |
+-----+ +-----+ +-----+
^ ^
w=1 | w=1 |
| |
+-----+ +-----+
|id=11| |id=9 |
+-----+ +-----+
In the above figure, ``id`` means stream ID, and ``w`` means weight.
The stream 0 is non-existence stream, and forms the root of the tree.
The stream 7 and 9 are not used for now.
The URIs given in the command-line depend on stream 11 with the weight
given in :option:`-p` option, which defaults to 16.
If :option:`-a` option is used, nghttp parses the resource pointed by
URI given in command-line as html, and extracts resource links from
it. When requesting those resources, nghttp uses dependency according
to its resource type.
For CSS, and Javascript files inside "head" element, they depend on
stream 3 with the weight 2. The Javascript files outside "head"
element depend on stream 5 with the weight 2. The mages depend on
stream 11 with the weight 12. The other resources (e.g., icon) depend
on stream 11 with the weight 2.
SEE ALSO
--------

View File

@@ -1,3 +1,54 @@
DEPENDENCY BASED PRIORITY
-------------------------
nghttp sends priority hints to server by default unless
:option:`--no-dep` is used. nghttp mimics the way Firefox employs to
manages dependency using idle streams. We follows the behaviour of
Firefox Nightly as of April, 2015, and nghttp's behaviour is very
static and could be different from Firefox in detail. But reproducing
the same behaviour of Firefox is not our goal. The goal is provide
the easy way to test out the dependency priority in server
implementation.
When connection is established, nghttp sends 5 PRIORITY frames to idle
streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency
tree::
+-----+
|id=0 |
+-----+
^ ^ ^
w=201 / | \ w=1
/ | \
/ w=101| \
+-----+ +-----+ +-----+
|id=3 | |id=5 | |id=7 |
+-----+ +-----+ +-----+
^ ^
w=1 | w=1 |
| |
+-----+ +-----+
|id=11| |id=9 |
+-----+ +-----+
In the above figure, ``id`` means stream ID, and ``w`` means weight.
The stream 0 is non-existence stream, and forms the root of the tree.
The stream 7 and 9 are not used for now.
The URIs given in the command-line depend on stream 11 with the weight
given in :option:`-p` option, which defaults to 16.
If :option:`-a` option is used, nghttp parses the resource pointed by
URI given in command-line as html, and extracts resource links from
it. When requesting those resources, nghttp uses dependency according
to its resource type.
For CSS, and Javascript files inside "head" element, they depend on
stream 3 with the weight 2. The Javascript files outside "head"
element depend on stream 5 with the weight 2. The mages depend on
stream 11 with the weight 12. The other resources (e.g., icon) depend
on stream 11 with the weight 2.
SEE ALSO
--------

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "NGHTTPD" "1" "March 27, 2015" "0.7.9" "nghttp2"
.TH "NGHTTPD" "1" "September 12, 2015" "1.3.1" "nghttp2"
.SH NAME
nghttpd \- HTTP/2 experimental server
.
@@ -63,7 +63,7 @@ address determined by getaddrinfo is used.
.INDENT 0.0
.TP
.B \-D, \-\-daemon
Run in a background. If \fI\-D\fP is used, the current working
Run in a background. If \fI\%\-D\fP is used, the current working
directory is changed to \(aq\fI/\fP\(aq. Therefore if this option
is used, \fI\%\-d\fP option must be specified.
.UNINDENT
@@ -109,7 +109,7 @@ Push resources <PUSH_PATH>s when <PATH> is requested.
This option can be used repeatedly to specify multiple
push configurations. <PATH> and <PUSH_PATH>s are
relative to document root. See \fI\%\-\-htdocs\fP option.
Example: \fI\-p\fP/=/foo.png \fI\-p\fP/doc=/bar.css
Example: \fI\%\-p\fP/=/foo.png \fI\%\-p\fP/doc=/bar.css
.UNINDENT
.INDENT 0.0
.TP
@@ -119,6 +119,14 @@ Specify 0 to disable padding.
.UNINDENT
.INDENT 0.0
.TP
.B \-m, \-\-max\-concurrent\-streams=<N>
Set the maximum number of the concurrent streams in one
HTTP/2 session.
.sp
Default: \fB100\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-n, \-\-workers=<N>
Set the number of worker threads.
.sp
@@ -159,6 +167,11 @@ are used.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-echo\-upload
Send back uploaded content if method is POST or PUT.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-version
Display version information and exit.
.UNINDENT

View File

@@ -1,4 +1,8 @@
.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY.
.. program:: nghttpd
nghttpd(1)
==========
@@ -83,6 +87,13 @@ OPTIONS
Add at most <N> bytes to a frame payload as padding.
Specify 0 to disable padding.
.. option:: -m, --max-concurrent-streams=<N>
Set the maximum number of the concurrent streams in one
HTTP/2 session.
Default: ``100``
.. option:: -n, --workers=<N>
Set the number of worker threads.
@@ -117,6 +128,10 @@ OPTIONS
hex+ASCII display). If SSL/TLS is used, decrypted data
are used.
.. option:: --echo-upload
Send back uploaded content if method is POST or PUT.
.. option:: --version
Display version information and exit.
@@ -126,6 +141,7 @@ OPTIONS
Display this help and exit.
The <SIZE> argument is an integer and an optional unit (e.g., 10K is
10 * 1024). Units are K, M and G (powers of 1024).

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "NGHTTPX" "1" "March 27, 2015" "0.7.9" "nghttp2"
.TH "NGHTTPX" "1" "September 12, 2015" "1.3.1" "nghttp2"
.SH NAME
nghttpx \- HTTP/2 experimental proxy
.
@@ -46,7 +46,8 @@ Set path to server\(aqs private key. Required unless \fI\%\-p\fP,
.TP
.B <CERT>
Set path to server\(aqs certificate. Required unless \fI\%\-p\fP,
\fI\%\-\-client\fP or \fI\%\-\-frontend\-no\-tls\fP are given.
\fI\%\-\-client\fP or \fI\%\-\-frontend\-no\-tls\fP are given. To make OCSP
stapling work, this must be absolute path.
.UNINDENT
.SH OPTIONS
.sp
@@ -54,17 +55,69 @@ The options are categorized into several groups.
.SS Connections
.INDENT 0.0
.TP
.B \-b, \-\-backend=<HOST,PORT>
.B \-b, \-\-backend=(<HOST>,<PORT>|unix:<PATH>)[;<PATTERN>[:...]]
Set backend host and port. The multiple backend
addresses are accepted by repeating this option. UNIX
domain socket can be specified by prefixing path name
with "unix:" (e.g., unix:/var/run/backend.sock)
with "unix:" (e.g., unix:/var/run/backend.sock).
.sp
Optionally, if <PATTERN>s are given, the backend address
is only used if request matches the pattern. If \fI\%\-s\fP or
\fI\%\-p\fP is used, <PATTERN>s are ignored. The pattern
matching is closely designed to ServeMux in net/http
package of Go programming language. <PATTERN> consists
of path, host + path or just host. The path must start
with "\fI/\fP". If it ends with "\fI/\fP", it matches all request
path in its subtree. To deal with the request to the
directory without trailing slash, the path which ends
with "\fI/\fP" also matches the request path which only lacks
trailing \(aq\fI/\fP\(aq (e.g., path "\fI/foo/\fP" matches request path
"\fI/foo\fP"). If it does not end with "\fI/\fP", it performs exact
match against the request path. If host is given, it
performs exact match against the request host. If host
alone is given, "\fI/\fP" is appended to it, so that it
matches all request paths under the host (e.g.,
specifying "nghttp2.org" equals to "nghttp2.org/").
.sp
Patterns with host take precedence over patterns with
just path. Then, longer patterns take precedence over
shorter ones, breaking a tie by the order of the
appearance in the configuration.
.sp
If <PATTERN> is omitted, "\fI/\fP" is used as pattern, which
matches all request paths (catch\-all pattern). The
catch\-all backend must be given.
.sp
When doing a match, nghttpx made some normalization to
pattern, request host and path. For host part, they are
converted to lower case. For path part, percent\-encoded
unreserved characters defined in RFC 3986 are decoded,
and any dot\-segments (".." and ".") are resolved and
removed.
.sp
For example, \fI\%\-b\fP\(aq127.0.0.1,8080;nghttp2.org/httpbin/\(aq
matches the request host "nghttp2.org" and the request
path "\fI/httpbin/get\fP", but does not match the request host
"nghttp2.org" and the request path "\fI/index.html\fP".
.sp
The multiple <PATTERN>s can be specified, delimiting
them by ":". Specifying
\fI\%\-b\fP\(aq127.0.0.1,8080;nghttp2.org:www.nghttp2.org\(aq has the
same effect to specify \fI\%\-b\fP\(aq127.0.0.1,8080;nghttp2.org\(aq
and \fI\%\-b\fP\(aq127.0.0.1,8080;www.nghttp2.org\(aq.
.sp
The backend addresses sharing same <PATTERN> are grouped
together forming load balancing group.
.sp
Since ";" and ":" are used as delimiter, <PATTERN> must
not contain these characters. Since ";" has special
meaning in shell, the option value must be quoted.
.sp
Default: \fB127.0.0.1,80\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-f, \-\-frontend=<HOST,PORT>
.B \-f, \-\-frontend=(<HOST>,<PORT>|unix:<PATH>)
Set frontend host and port. If <HOST> is \(aq*\(aq, it
assumes all addresses including both IPv4 and IPv6.
UNIX domain socket can be specified by prefixing path
@@ -105,6 +158,11 @@ timeouts when connecting and making CONNECT request can
be specified by \fI\%\-\-backend\-read\-timeout\fP and
\fI\%\-\-backend\-write\-timeout\fP options.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-accept\-proxy\-protocol
Accept PROXY protocol version 1 on frontend connection.
.UNINDENT
.SS Performance
.INDENT 0.0
.TP
@@ -194,17 +252,24 @@ Default: \fB0\fP
.INDENT 0.0
.TP
.B \-\-backend\-http2\-connections\-per\-worker=<N>
Set maximum number of HTTP/2 connections per worker.
The default value is 0, which means the number of
backend addresses specified by \fI\%\-b\fP option.
Set maximum number of backend HTTP/2 physical
connections per worker. If pattern is used in \fI\%\-b\fP
option, this limit is applied to each pattern group (in
other words, each pattern group can have maximum <N>
HTTP/2 connections). The default value is 0, which
means that the value is adjusted to the number of
backend addresses. If pattern is used, this adjustment
is done for each pattern group.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-backend\-http1\-connections\-per\-host=<N>
Set maximum number of backend concurrent HTTP/1
connections per host. This option is meaningful when \fI\%\-s\fP
option is used. To limit the number of connections per
frontend for default mode, use
connections per origin host. This option is meaningful
when \fI\%\-s\fP option is used. The origin host is determined
by authority portion of requset URI (or :authority
header field for HTTP/2). To limit the number of
connections per frontend for default mode, use
\fI\%\-\-backend\-http1\-connections\-per\-frontend\fP\&.
.sp
Default: \fB8\fP
@@ -249,14 +314,14 @@ Default: \fB16K\fP
Specify read timeout for HTTP/2 and SPDY frontend
connection.
.sp
Default: \fB180s\fP
Default: \fB3m\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-frontend\-read\-timeout=<DURATION>
Specify read timeout for HTTP/1.1 frontend connection.
.sp
Default: \fB180s\fP
Default: \fB3m\fP
.UNINDENT
.INDENT 0.0
.TP
@@ -286,7 +351,7 @@ Default: \fB0\fP
.B \-\-backend\-read\-timeout=<DURATION>
Specify read timeout for backend connection.
.sp
Default: \fB180s\fP
Default: \fB3m\fP
.UNINDENT
.INDENT 0.0
.TP
@@ -348,7 +413,8 @@ password protected it\(aqll be requested interactively.
Specify additional certificate and private key file.
nghttpx will choose certificates based on the hostname
indicated by client using TLS SNI extension. This
option can be used multiple times.
option can be used multiple times. To make OCSP
stapling work, <CERTPATH> must be absolute path.
.UNINDENT
.INDENT 0.0
.TP
@@ -414,33 +480,102 @@ Default: \fBTLSv1.2,TLSv1.1\fP
.INDENT 0.0
.TP
.B \-\-tls\-ticket\-key\-file=<PATH>
Path to file that contains 48 bytes random data to
construct TLS session ticket parameters. This options
can be used repeatedly to specify multiple ticket
parameters. If several files are given, only the first
key is used to encrypt TLS session tickets. Other keys
are accepted but server will issue new session ticket
with first key. This allows session key rotation.
Please note that key rotation does not occur
automatically. User should rearrange files or change
options values and restart nghttpx gracefully. If
opening or reading given file fails, all loaded keys are
discarded and it is treated as if none of this option is
given. If this option is not given or an error occurred
while opening or reading a file, key is generated
automatically and renewed every 12hrs. At most 2 keys
are stored in memory.
Path to file that contains random data to construct TLS
session ticket parameters. If aes\-128\-cbc is given in
\fI\%\-\-tls\-ticket\-key\-cipher\fP, the file must contain exactly
48 bytes. If aes\-256\-cbc is given in
\fI\%\-\-tls\-ticket\-key\-cipher\fP, the file must contain exactly
80 bytes. This options can be used repeatedly to
specify multiple ticket parameters. If several files
are given, only the first key is used to encrypt TLS
session tickets. Other keys are accepted but server
will issue new session ticket with first key. This
allows session key rotation. Please note that key
rotation does not occur automatically. User should
rearrange files or change options values and restart
nghttpx gracefully. If opening or reading given file
fails, all loaded keys are discarded and it is treated
as if none of this option is given. If this option is
not given or an error occurred while opening or reading
a file, key is generated every 1 hour internally and
they are valid for 12 hours. This is recommended if
ticket key sharing between nghttpx instances is not
required.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-tls\-ctx\-per\-worker
Create OpenSSL\(aqs SSL_CTX per worker, so that no internal
locking is required. This may improve scalability with
multi threaded configuration. If this option is
enabled, session ID is no longer shared accross SSL_CTX
objects, which means session ID generated by one worker
is not acceptable by another worker. On the other hand,
session ticket key is shared across all worker threads.
.B \-\-tls\-ticket\-key\-memcached=<HOST>,<PORT>
Specify address of memcached server to store session
cache. This enables shared TLS ticket key between
multiple nghttpx instances. nghttpx does not set TLS
ticket key to memcached. The external ticket key
generator is required. nghttpx just gets TLS ticket
keys from memcached, and use them, possibly replacing
current set of keys. It is up to extern TLS ticket key
generator to rotate keys frequently. See "TLS SESSION
TICKET RESUMPTION" section in manual page to know the
data format in memcached entry.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-tls\-ticket\-key\-memcached\-interval=<DURATION>
Set interval to get TLS ticket keys from memcached.
.sp
Default: \fB10m\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-tls\-ticket\-key\-memcached\-max\-retry=<N>
Set maximum number of consecutive retries before
abandoning TLS ticket key retrieval. If this number is
reached, the attempt is considered as failure, and
"failure" count is incremented by 1, which contributed
to the value controlled
\fI\%\-\-tls\-ticket\-key\-memcached\-max\-fail\fP option.
.sp
Default: \fB3\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-tls\-ticket\-key\-memcached\-max\-fail=<N>
Set maximum number of consecutive failure before
disabling TLS ticket until next scheduled key retrieval.
.sp
Default: \fB2\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-tls\-ticket\-key\-cipher=<CIPHER>
Specify cipher to encrypt TLS session ticket. Specify
either aes\-128\-cbc or aes\-256\-cbc. By default,
aes\-128\-cbc is used.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-fetch\-ocsp\-response\-file=<PATH>
Path to fetch\-ocsp\-response script file. It should be
absolute path.
.sp
Default: \fB/usr/local/share/nghttp2/fetch\-ocsp\-response\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-ocsp\-update\-interval=<DURATION>
Set interval to update OCSP response cache.
.sp
Default: \fB4h\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-no\-ocsp
Disable OCSP stapling.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-tls\-session\-cache\-memcached=<HOST>,<PORT>
Specify address of memcached server to store session
cache. This enables shared session cache between
multiple nghttpx instances.
.UNINDENT
.SS HTTP/2 and SPDY
.INDENT 0.0
@@ -613,15 +748,28 @@ $pid: PID of the running process.
$alpn: ALPN identifier of the protocol which generates
the response. For HTTP/1, ALPN is always http/1.1,
regardless of minor version.
.IP \(bu 2
$ssl_cipher: cipher used for SSL/TLS connection.
.IP \(bu 2
$ssl_protocol: protocol for SSL/TLS connection.
.IP \(bu 2
$ssl_session_id: session ID for SSL/TLS connection.
.IP \(bu 2
$ssl_session_reused: "r" if SSL/TLS session was
reused. Otherwise, "."
.UNINDENT
.sp
The variable can be enclosed by "{" and "}" for
disambiguation (e.g., ${remote_addr}).
.sp
Default: \fB$remote_addr \- \- [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-errorlog\-file=<PATH>
Set path to write error log. To reopen file, send USR1
signal to nghttpx.
signal to nghttpx. stderr will be redirected to the
error log file unless \fI\%\-\-errorlog\-syslog\fP is used.
.sp
Default: \fB/dev/stderr\fP
.UNINDENT
@@ -667,8 +815,8 @@ altered regardless of this option.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-no\-host\-rewrite
Don\(aqt rewrite host and :authority header fields on
.B \-\-host\-rewrite
Rewrite host and :authority header fields on
\fI\%\-\-http2\-bridge\fP, \fI\%\-\-client\fP and default mode. For
\fI\%\-\-http2\-proxy\fP and \fI\%\-\-client\-proxy\fP mode, these headers
will not be altered regardless of this option.
@@ -678,10 +826,19 @@ will not be altered regardless of this option.
.B \-\-altsvc=<PROTOID,PORT[,HOST,[ORIGIN]]>
Specify protocol ID, port, host and origin of
alternative service. <HOST> and <ORIGIN> are optional.
They are advertised in alt\-svc header field or HTTP/2
ALTSVC frame. This option can be used multiple times to
specify multiple alternative services. Example:
\fI\%\-\-altsvc\fP=h2,443
They are advertised in alt\-svc header field only in
HTTP/1.1 frontend. This option can be used multiple
times to specify multiple alternative services.
Example: \fI\%\-\-altsvc\fP=h2,443
.UNINDENT
.INDENT 0.0
.TP
.B \-\-add\-request\-header=<HEADER>
Specify additional header field to add to request header
set. This option just appends header field and won\(aqt
replace anything already set. This option can be used
several times to specify multiple header fields.
Example: \fI\%\-\-add\-request\-header\fP="foo: bar"
.UNINDENT
.INDENT 0.0
.TP
@@ -692,6 +849,23 @@ won\(aqt replace anything already set. This option can be
used several times to specify multiple header fields.
Example: \fI\%\-\-add\-response\-header\fP="foo: bar"
.UNINDENT
.INDENT 0.0
.TP
.B \-\-header\-field\-buffer=<SIZE>
Set maximum buffer size for incoming HTTP header field
list. This is the sum of header name and value in
bytes.
.sp
Default: \fB64K\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-max\-header\-fields=<N>
Set maximum number of incoming HTTP header fields, which
appear in one request or response header field list.
.sp
Default: \fB100\fP
.UNINDENT
.SS Debug
.INDENT 0.0
.TP
@@ -736,6 +910,21 @@ Set path to save PID of this program.
Run this program as <USER>. This option is intended to
be used to drop root privileges.
.UNINDENT
.SS Scripting
.INDENT 0.0
.TP
.B \-\-request\-phase\-file=<PATH>
Set mruby script file which will be executed when
request header fields are completely received from
frontend. This hook is called request phase hook.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-response\-phase\-file=<PATH>
Set mruby script file which will be executed when
response header fields are completely received from
backend. This hook is called response phase hook.
.UNINDENT
.SS Misc
.INDENT 0.0
.TP
@@ -746,6 +935,14 @@ Default: \fB/etc/nghttpx/nghttpx.conf\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-include=<PATH>
Load additional configurations from <PATH>. File <PATH>
is read when configuration parser encountered this
option. This option can be used multiple times, or even
recursively.
.UNINDENT
.INDENT 0.0
.TP
.B \-v, \-\-version
Print version and exit.
.UNINDENT
@@ -759,8 +956,9 @@ The <SIZE> argument is an integer and an optional unit (e.g., 10K is
10 * 1024). Units are K, M and G (powers of 1024).
.sp
The <DURATION> argument is an integer and an optional unit (e.g., 1s
is 1 second and 500ms is 500 milliseconds). Units are s or ms. If
a unit is omitted, a second is used as unit.
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
(hours, minutes, seconds and milliseconds, respectively). If a unit
is omitted, a second is used as unit.
.SH FILES
.INDENT 0.0
.TP
@@ -782,7 +980,7 @@ argument in the configuration file. Specify \fByes\fP as an argument
ignored.
.sp
To specify private key and certificate file which are given as
positional arguments in commnad\-line, use \fBprivate\-key\-file\fP and
positional arguments in command\-line, use \fBprivate\-key\-file\fP and
\fBcertificate\-file\fP\&.
.sp
\fI\%\-\-conf\fP option cannot be used in the configuration file and
@@ -825,19 +1023,14 @@ Link: </css/theme.css>; rel=preload
.UNINDENT
.UNINDENT
.sp
Currently, the following restrictions are applied for server push:
Currently, the following restriction is applied for server push:
.INDENT 0.0
.IP 1. 3
URI\-reference must not contain authority. If it exists, it is not
pushed. \fB/fonts/font.woff\fP and \fBcss/theme.css\fP are eligible to
be pushed. \fBhttps://example.org/fonts/font.woff\fP and
\fB//example.org/css/theme.css\fP are not.
.IP 2. 3
The associated stream must have method "GET" or "POST". The
associated stream\(aqs status code must be 200.
.UNINDENT
.sp
These limitations may be loosened in the future release.
This limitation may be loosened in the future release.
.SH UNIX DOMAIN SOCKET
.sp
nghttpx supports UNIX domain socket with a filename for both frontend
@@ -849,6 +1042,352 @@ specified socket already exists in the file system, nghttpx first
deletes it. However, if SIGUSR2 is used to execute new binary and
both old and new configurations use same filename, new binary does not
delete the socket and continues to use it.
.SH OCSP STAPLING
.sp
OCSP query is done using external Python script
\fBfetch\-ocsp\-response\fP, which has been originally developed in Perl
as part of h2o project (\fI\%https://github.com/h2o/h2o\fP), and was
translated into Python.
.sp
The script file is usually installed under
\fB$(prefix)/share/nghttp2/\fP directory. The actual path to script can
be customized using \fI\%\-\-fetch\-ocsp\-response\-file\fP option.
.sp
If OCSP query is failed, previous OCSP response, if any, is continued
to be used.
.SH TLS SESSION RESUMPTION
.sp
nghttpx supports TLS session resumption through both session ID and
session ticket.
.SS SESSION ID RESUMPTION
.sp
By default, session ID is shared by all worker threads.
.sp
If \fI\%\-\-tls\-session\-cache\-memcached\fP is given, nghttpx will
insert serialized session data to memcached with
\fBnghttpx:tls\-session\-cache:\fP + lowercased hex string of session ID
as a memcached entry key, with expiry time 12 hours. Session timeout
is set to 12 hours.
.SS TLS SESSION TICKET RESUMPTION
.sp
By default, session ticket is shared by all worker threads. The
automatic key rotation is also enabled by default. Every an hour, new
encryption key is generated, and previous encryption key becomes
decryption only key. We set session timeout to 12 hours, and thus we
keep at most 12 keys.
.sp
If \fI\%\-\-tls\-ticket\-key\-memcached\fP is given, encryption keys are
retrieved from memcached. nghttpx just reads keys from memcached; one
has to deploy key generator program to update keys frequently (e.g.,
every 1 hour). The example key generator tlsticketupdate.go is
available under contrib directory in nghttp2 archive. The memcached
entry key is \fBnghttpx:tls\-ticket\-key\fP\&. The data format stored in
memcached is the binary format described below:
.INDENT 0.0
.INDENT 3.5
.sp
.nf
.ft C
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
| VERSION (4) |LEN (2)|KEY(48 or 80) ...
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
^ |
| |
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
(LEN, KEY) pair can be repeated
.ft P
.fi
.UNINDENT
.UNINDENT
.sp
All numbers in the above figure is bytes. All integer fields are
network byte order.
.sp
First 4 bytes integer VERSION field, which must be 1. The 2 bytes
integer LEN field gives the length of following KEY field, which
contains key. If \fI\%\-\-tls\-ticket\-key\-cipher\fP=aes\-128\-cbc is
used, LEN must be 48. If
\fI\%\-\-tls\-ticket\-key\-cipher\fP=aes\-256\-cbc is used, LEN must be
80. LEN and KEY pair can be repeated multiple times to store multiple
keys. The key appeared first is used as encryption key. All the
remaining keys are used as decryption only.
.sp
If \fI\%\-\-tls\-ticket\-key\-file\fP is given, encryption key is read
from the given file. In this case, nghttpx does not rotate key
automatically. To rotate key, one has to restart nghttpx (see
SIGNALS).
.SH MRUBY SCRIPTING
.sp
\fBWARNING:\fP
.INDENT 0.0
.INDENT 3.5
The current mruby extension API is experimental and not frozen. The
API is subject to change in the future release.
.UNINDENT
.UNINDENT
.sp
nghttpx allows users to extend its capability using mruby scripts.
nghttpx has 2 hook points to execute mruby script: request phase and
response phase. The request phase hook is invoked after all request
header fields are received from client. The response phase hook is
invoked after all response header fields are received from backend
server. These hooks allows users to modify header fields, or common
HTTP variables, like authority or request path, and even return custom
response without forwarding request to backend servers.
.sp
To set request phase hook, use \fI\%\-\-request\-phase\-file\fP option.
To set response phase hook, use \fI\%\-\-response\-phase\-file\fP
option.
.sp
For request and response phase hook, user calls \fI\%Nghttpx.run\fP
with block. The \fI\%Nghttpx::Env\fP is passed to the block.
User can can access \fI\%Nghttpx::Request\fP and
\fI\%Nghttpx::Response\fP objects via \fI\%Nghttpx::Env#req\fP
and \fI\%Nghttpx::Env#resp\fP respectively.
.INDENT 0.0
.TP
.B classmethod .Nghttpx.run(&block)
Run request or response phase hook with given \fIblock\fP\&.
\fI\%Nghttpx::Env\fP object is passed to the given block.
.UNINDENT
.INDENT 0.0
.TP
.B Nghttpx::REQUEST_PHASE
Constant to represent request phase.
.UNINDENT
.INDENT 0.0
.TP
.B Nghttpx::RESPONSE_PHASE
Constant to represent response phase.
.UNINDENT
.INDENT 0.0
.TP
.B class Nghttpx::Env
Object to represent current request specific context.
.INDENT 7.0
.TP
.B attribute [R] req
Return \fI\%Request\fP object.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] resp
Return \fI\%Response\fP object.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] ctx
Return Ruby hash object. It persists until request finishes.
So values set in request phase hoo can be retrieved in
response phase hook.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] phase
Return the current phase.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] remote_addr
Return IP address of a remote client.
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B class Nghttpx::Request
Object to represent request from client. The modification to
Request object is allowed only in request phase hook.
.INDENT 7.0
.TP
.B attribute [R] http_version_major
Return HTTP major version.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] http_version_minor
Return HTTP minor version.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R/W] method
HTTP method. On assignment, copy of given value is assigned.
We don\(aqt accept arbitrary method name. We will document them
later, but well known methods, like GET, PUT and POST, are all
supported.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R/W] authority
Authority (i.e., example.org), including optional port
component . On assignment, copy of given value is assigned.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R/W] scheme
Scheme (i.e., http, https). On assignment, copy of given
value is assigned.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R/W] path
Request path, including query component (i.e., /index.html).
On assignment, copy of given value is assigned. The path does
not include authority component of URI.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] headers
Return Ruby hash containing copy of request header fields.
Changing values in returned hash does not change request
header fields actually used in request processing. Use
\fI\%Nghttpx::Request#add_header\fP or
\fI\%Nghttpx::Request#set_header\fP to change request
header fields.
.UNINDENT
.INDENT 7.0
.TP
.B add_header(key, value)
Add header entry associated with key. The value can be single
string or array of string. It does not replace any existing
values associated with key.
.UNINDENT
.INDENT 7.0
.TP
.B set_header(key, value)
Set header entry associated with key. The value can be single
string or array of string. It replaces any existing values
associated with key.
.UNINDENT
.INDENT 7.0
.TP
.B clear_headers()
Clear all existing request header fields.
.UNINDENT
.INDENT 7.0
.TP
.B push uri
Initiate to push resource identified by \fIuri\fP\&. Only HTTP/2
protocol supports this feature. For the other protocols, this
method is noop. \fIuri\fP can be absolute URI, absolute path or
relative path to the current request. For absolute or
relative path, scheme and authority are inherited from the
current request. Currently, method is always GET. nghttpx
will issue request to backend servers to fulfill this request.
The request and response phase hooks will be called for pushed
resource as well.
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B class Nghttpx::Response
Object to represent response from backend server.
.INDENT 7.0
.TP
.B attribute [R] http_version_major
Return HTTP major version.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] http_version_minor
Return HTTP minor version.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R/W] status
HTTP status code. It must be in the range [200, 999],
inclusive. The non\-final status code is not supported in
mruby scripting at the moment.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] headers
Return Ruby hash containing copy of response header fields.
Changing values in returned hash does not change response
header fields actually used in response processing. Use
\fI\%Nghttpx::Response#add_header\fP or
\fI\%Nghttpx::Response#set_header\fP to change response
header fields.
.UNINDENT
.INDENT 7.0
.TP
.B add_header(key, value)
Add header entry associated with key. The value can be single
string or array of string. It does not replace any existing
values associated with key.
.UNINDENT
.INDENT 7.0
.TP
.B set_header(key, value)
Set header entry associated with key. The value can be single
string or array of string. It replaces any existing values
associated with key.
.UNINDENT
.INDENT 7.0
.TP
.B clear_headers()
Clear all existing response header fields.
.UNINDENT
.INDENT 7.0
.TP
.B return(body)
Return custom response \fIbody\fP to a client. When this method
is called in request phase hook, the request is not forwarded
to the backend, and response phase hook for this request will
not be invoked. When this method is called in resonse phase
hook, response from backend server is canceled and discarded.
The status code and response header fields should be set
before using this method. To set status code, use :rb:meth To
set response header fields, use
\fI\%Nghttpx::Response#status\fP\&. If status code is not
set, 200 is used. \fI\%Nghttpx::Response#add_header\fP and
\fI\%Nghttpx::Response#set_header\fP\&. When this method is
invoked in response phase hook, the response headers are
filled with the ones received from backend server. To send
completely custom header fields, first call
\fI\%Nghttpx::Response#clear_headers\fP to erase all
existing header fields, and then add required header fields.
It is an error to call this method twice for a given request.
.UNINDENT
.UNINDENT
.SS MRUBY EXAMPLES
.sp
Modify requet path:
.INDENT 0.0
.INDENT 3.5
.sp
.nf
.ft C
Nghttpx.run do |env|
env.req.path = "/apps#{env.req.path}"
end
.ft P
.fi
.UNINDENT
.UNINDENT
.sp
Note that the file containing the above script must be set with
\fI\%\-\-request\-phase\-file\fP option since we modify request path.
.sp
Restrict permission of viewing a content to a specific client
addresses:
.INDENT 0.0
.INDENT 3.5
.sp
.nf
.ft C
Nghttpx.run do |env|
allowed_clients = ["127.0.0.1", "::1"]
if env.req.path.start_with?("/log/") &&
!allowed_clients.include?(env.remote_addr) then
env.resp.status = 404
env.resp.return "permission denied"
end
end
.ft P
.fi
.UNINDENT
.UNINDENT
.SH SEE ALSO
.sp
\fInghttp(1)\fP, \fInghttpd(1)\fP, \fIh2load(1)\fP

View File

@@ -1,4 +1,8 @@
.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY.
.. program:: nghttpx
nghttpx(1)
==========
@@ -21,7 +25,8 @@ A reverse proxy for HTTP/2, HTTP/1 and SPDY.
.. describe:: <CERT>
Set path to server's certificate. Required unless :option:`-p`\,
:option:`--client` or :option:`\--frontend-no-tls` are given.
:option:`--client` or :option:`\--frontend-no-tls` are given. To make OCSP
stapling work, this must be absolute path.
OPTIONS
@@ -32,16 +37,69 @@ The options are categorized into several groups.
Connections
~~~~~~~~~~~
.. option:: -b, --backend=<HOST,PORT>
.. option:: -b, --backend=(<HOST>,<PORT>|unix:<PATH>)[;<PATTERN>[:...]]
Set backend host and port. The multiple backend
addresses are accepted by repeating this option. UNIX
domain socket can be specified by prefixing path name
with "unix:" (e.g., unix:/var/run/backend.sock)
with "unix:" (e.g., unix:/var/run/backend.sock).
Optionally, if <PATTERN>s are given, the backend address
is only used if request matches the pattern. If :option:`-s` or
:option:`-p` is used, <PATTERN>s are ignored. The pattern
matching is closely designed to ServeMux in net/http
package of Go programming language. <PATTERN> consists
of path, host + path or just host. The path must start
with "*/*". If it ends with "*/*", it matches all request
path in its subtree. To deal with the request to the
directory without trailing slash, the path which ends
with "*/*" also matches the request path which only lacks
trailing '*/*' (e.g., path "*/foo/*" matches request path
"*/foo*"). If it does not end with "*/*", it performs exact
match against the request path. If host is given, it
performs exact match against the request host. If host
alone is given, "*/*" is appended to it, so that it
matches all request paths under the host (e.g.,
specifying "nghttp2.org" equals to "nghttp2.org/").
Patterns with host take precedence over patterns with
just path. Then, longer patterns take precedence over
shorter ones, breaking a tie by the order of the
appearance in the configuration.
If <PATTERN> is omitted, "*/*" is used as pattern, which
matches all request paths (catch-all pattern). The
catch-all backend must be given.
When doing a match, nghttpx made some normalization to
pattern, request host and path. For host part, they are
converted to lower case. For path part, percent-encoded
unreserved characters defined in RFC 3986 are decoded,
and any dot-segments (".." and ".") are resolved and
removed.
For example, :option:`-b`\'127.0.0.1,8080;nghttp2.org/httpbin/'
matches the request host "nghttp2.org" and the request
path "*/httpbin/get*", but does not match the request host
"nghttp2.org" and the request path "*/index.html*".
The multiple <PATTERN>s can be specified, delimiting
them by ":". Specifying
:option:`-b`\'127.0.0.1,8080;nghttp2.org:www.nghttp2.org' has the
same effect to specify :option:`-b`\'127.0.0.1,8080;nghttp2.org'
and :option:`-b`\'127.0.0.1,8080;www.nghttp2.org'.
The backend addresses sharing same <PATTERN> are grouped
together forming load balancing group.
Since ";" and ":" are used as delimiter, <PATTERN> must
not contain these characters. Since ";" has special
meaning in shell, the option value must be quoted.
Default: ``127.0.0.1,80``
.. option:: -f, --frontend=<HOST,PORT>
.. option:: -f, --frontend=(<HOST>,<PORT>|unix:<PATH>)
Set frontend host and port. If <HOST> is '\*', it
assumes all addresses including both IPv4 and IPv6.
@@ -79,6 +137,10 @@ Connections
be specified by :option:`--backend-read-timeout` and
:option:`--backend-write-timeout` options.
.. option:: --accept-proxy-protocol
Accept PROXY protocol version 1 on frontend connection.
Performance
~~~~~~~~~~~
@@ -160,16 +222,23 @@ Performance
.. option:: --backend-http2-connections-per-worker=<N>
Set maximum number of HTTP/2 connections per worker.
The default value is 0, which means the number of
backend addresses specified by :option:`-b` option.
Set maximum number of backend HTTP/2 physical
connections per worker. If pattern is used in :option:`-b`
option, this limit is applied to each pattern group (in
other words, each pattern group can have maximum <N>
HTTP/2 connections). The default value is 0, which
means that the value is adjusted to the number of
backend addresses. If pattern is used, this adjustment
is done for each pattern group.
.. option:: --backend-http1-connections-per-host=<N>
Set maximum number of backend concurrent HTTP/1
connections per host. This option is meaningful when :option:`-s`
option is used. To limit the number of connections per
frontend for default mode, use
connections per origin host. This option is meaningful
when :option:`-s` option is used. The origin host is determined
by authority portion of requset URI (or :authority
header field for HTTP/2). To limit the number of
connections per frontend for default mode, use
:option:`--backend-http1-connections-per-frontend`\.
Default: ``8``
@@ -212,13 +281,13 @@ Timeout
Specify read timeout for HTTP/2 and SPDY frontend
connection.
Default: ``180s``
Default: ``3m``
.. option:: --frontend-read-timeout=<DURATION>
Specify read timeout for HTTP/1.1 frontend connection.
Default: ``180s``
Default: ``3m``
.. option:: --frontend-write-timeout=<DURATION>
@@ -244,7 +313,7 @@ Timeout
Specify read timeout for backend connection.
Default: ``180s``
Default: ``3m``
.. option:: --backend-write-timeout=<DURATION>
@@ -301,7 +370,8 @@ SSL/TLS
Specify additional certificate and private key file.
nghttpx will choose certificates based on the hostname
indicated by client using TLS SNI extension. This
option can be used multiple times.
option can be used multiple times. To make OCSP
stapling work, <CERTPATH> must be absolute path.
.. option:: --backend-tls-sni-field=<HOST>
@@ -358,32 +428,93 @@ SSL/TLS
.. option:: --tls-ticket-key-file=<PATH>
Path to file that contains 48 bytes random data to
construct TLS session ticket parameters. This options
can be used repeatedly to specify multiple ticket
parameters. If several files are given, only the first
key is used to encrypt TLS session tickets. Other keys
are accepted but server will issue new session ticket
with first key. This allows session key rotation.
Please note that key rotation does not occur
automatically. User should rearrange files or change
options values and restart nghttpx gracefully. If
opening or reading given file fails, all loaded keys are
discarded and it is treated as if none of this option is
given. If this option is not given or an error occurred
while opening or reading a file, key is generated
automatically and renewed every 12hrs. At most 2 keys
are stored in memory.
Path to file that contains random data to construct TLS
session ticket parameters. If aes-128-cbc is given in
:option:`--tls-ticket-key-cipher`\, the file must contain exactly
48 bytes. If aes-256-cbc is given in
:option:`--tls-ticket-key-cipher`\, the file must contain exactly
80 bytes. This options can be used repeatedly to
specify multiple ticket parameters. If several files
are given, only the first key is used to encrypt TLS
session tickets. Other keys are accepted but server
will issue new session ticket with first key. This
allows session key rotation. Please note that key
rotation does not occur automatically. User should
rearrange files or change options values and restart
nghttpx gracefully. If opening or reading given file
fails, all loaded keys are discarded and it is treated
as if none of this option is given. If this option is
not given or an error occurred while opening or reading
a file, key is generated every 1 hour internally and
they are valid for 12 hours. This is recommended if
ticket key sharing between nghttpx instances is not
required.
.. option:: --tls-ctx-per-worker
.. option:: --tls-ticket-key-memcached=<HOST>,<PORT>
Create OpenSSL's SSL_CTX per worker, so that no internal
locking is required. This may improve scalability with
multi threaded configuration. If this option is
enabled, session ID is no longer shared accross SSL_CTX
objects, which means session ID generated by one worker
is not acceptable by another worker. On the other hand,
session ticket key is shared across all worker threads.
Specify address of memcached server to store session
cache. This enables shared TLS ticket key between
multiple nghttpx instances. nghttpx does not set TLS
ticket key to memcached. The external ticket key
generator is required. nghttpx just gets TLS ticket
keys from memcached, and use them, possibly replacing
current set of keys. It is up to extern TLS ticket key
generator to rotate keys frequently. See "TLS SESSION
TICKET RESUMPTION" section in manual page to know the
data format in memcached entry.
.. option:: --tls-ticket-key-memcached-interval=<DURATION>
Set interval to get TLS ticket keys from memcached.
Default: ``10m``
.. option:: --tls-ticket-key-memcached-max-retry=<N>
Set maximum number of consecutive retries before
abandoning TLS ticket key retrieval. If this number is
reached, the attempt is considered as failure, and
"failure" count is incremented by 1, which contributed
to the value controlled
:option:`--tls-ticket-key-memcached-max-fail` option.
Default: ``3``
.. option:: --tls-ticket-key-memcached-max-fail=<N>
Set maximum number of consecutive failure before
disabling TLS ticket until next scheduled key retrieval.
Default: ``2``
.. option:: --tls-ticket-key-cipher=<CIPHER>
Specify cipher to encrypt TLS session ticket. Specify
either aes-128-cbc or aes-256-cbc. By default,
aes-128-cbc is used.
.. option:: --fetch-ocsp-response-file=<PATH>
Path to fetch-ocsp-response script file. It should be
absolute path.
Default: ``/usr/local/share/nghttp2/fetch-ocsp-response``
.. option:: --ocsp-update-interval=<DURATION>
Set interval to update OCSP response cache.
Default: ``4h``
.. option:: --no-ocsp
Disable OCSP stapling.
.. option:: --tls-session-cache-memcached=<HOST>,<PORT>
Specify address of memcached server to store session
cache. This enables shared session cache between
multiple nghttpx instances.
HTTP/2 and SPDY
@@ -535,6 +666,14 @@ Logging
* $alpn: ALPN identifier of the protocol which generates
the response. For HTTP/1, ALPN is always http/1.1,
regardless of minor version.
* $ssl_cipher: cipher used for SSL/TLS connection.
* $ssl_protocol: protocol for SSL/TLS connection.
* $ssl_session_id: session ID for SSL/TLS connection.
* $ssl_session_reused: "r" if SSL/TLS session was
reused. Otherwise, "."
The variable can be enclosed by "{" and "}" for
disambiguation (e.g., ${remote_addr}).
Default: ``$remote_addr - - [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"``
@@ -542,7 +681,8 @@ Logging
.. option:: --errorlog-file=<PATH>
Set path to write error log. To reopen file, send USR1
signal to nghttpx.
signal to nghttpx. stderr will be redirected to the
error log file unless :option:`--errorlog-syslog` is used.
Default: ``/dev/stderr``
@@ -583,9 +723,9 @@ HTTP
:option:`--client-proxy` mode, location header field will not be
altered regardless of this option.
.. option:: --no-host-rewrite
.. option:: --host-rewrite
Don't rewrite host and :authority header fields on
Rewrite host and :authority header fields on
:option:`--http2-bridge`\, :option:`--client` and default mode. For
:option:`--http2-proxy` and :option:`\--client-proxy` mode, these headers
will not be altered regardless of this option.
@@ -594,10 +734,18 @@ HTTP
Specify protocol ID, port, host and origin of
alternative service. <HOST> and <ORIGIN> are optional.
They are advertised in alt-svc header field or HTTP/2
ALTSVC frame. This option can be used multiple times to
specify multiple alternative services. Example:
:option:`--altsvc`\=h2,443
They are advertised in alt-svc header field only in
HTTP/1.1 frontend. This option can be used multiple
times to specify multiple alternative services.
Example: :option:`--altsvc`\=h2,443
.. option:: --add-request-header=<HEADER>
Specify additional header field to add to request header
set. This option just appends header field and won't
replace anything already set. This option can be used
several times to specify multiple header fields.
Example: :option:`--add-request-header`\="foo: bar"
.. option:: --add-response-header=<HEADER>
@@ -607,6 +755,21 @@ HTTP
used several times to specify multiple header fields.
Example: :option:`--add-response-header`\="foo: bar"
.. option:: --header-field-buffer=<SIZE>
Set maximum buffer size for incoming HTTP header field
list. This is the sum of header name and value in
bytes.
Default: ``64K``
.. option:: --max-header-fields=<N>
Set maximum number of incoming HTTP header fields, which
appear in one request or response header field list.
Default: ``100``
Debug
~~~~~
@@ -652,6 +815,22 @@ Process
be used to drop root privileges.
Scripting
~~~~~~~~~
.. option:: --request-phase-file=<PATH>
Set mruby script file which will be executed when
request header fields are completely received from
frontend. This hook is called request phase hook.
.. option:: --response-phase-file=<PATH>
Set mruby script file which will be executed when
response header fields are completely received from
backend. This hook is called response phase hook.
Misc
~~~~
@@ -661,6 +840,13 @@ Misc
Default: ``/etc/nghttpx/nghttpx.conf``
.. option:: --include=<PATH>
Load additional configurations from <PATH>. File <PATH>
is read when configuration parser encountered this
option. This option can be used multiple times, or even
recursively.
.. option:: -v, --version
Print version and exit.
@@ -670,12 +856,14 @@ Misc
Print this help and exit.
The <SIZE> argument is an integer and an optional unit (e.g., 10K is
10 * 1024). Units are K, M and G (powers of 1024).
The <DURATION> argument is an integer and an optional unit (e.g., 1s
is 1 second and 500ms is 500 milliseconds). Units are s or ms. If
a unit is omitted, a second is used as unit.
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
(hours, minutes, seconds and milliseconds, respectively). If a unit
is omitted, a second is used as unit.
FILES
-----
@@ -698,7 +886,7 @@ FILES
ignored.
To specify private key and certificate file which are given as
positional arguments in commnad-line, use ``private-key-file`` and
positional arguments in command-line, use ``private-key-file`` and
``certificate-file``.
:option:`--conf` option cannot be used in the configuration file and
@@ -738,17 +926,12 @@ header field to initiate server push:
Link: </fonts/font.woff>; rel=preload
Link: </css/theme.css>; rel=preload
Currently, the following restrictions are applied for server push:
Currently, the following restriction is applied for server push:
1. URI-reference must not contain authority. If it exists, it is not
pushed. ``/fonts/font.woff`` and ``css/theme.css`` are eligible to
be pushed. ``https://example.org/fonts/font.woff`` and
``//example.org/css/theme.css`` are not.
2. The associated stream must have method "GET" or "POST". The
1. The associated stream must have method "GET" or "POST". The
associated stream's status code must be 200.
These limitations may be loosened in the future release.
This limitation may be loosened in the future release.
UNIX DOMAIN SOCKET
------------------
@@ -763,6 +946,313 @@ deletes it. However, if SIGUSR2 is used to execute new binary and
both old and new configurations use same filename, new binary does not
delete the socket and continues to use it.
OCSP STAPLING
-------------
OCSP query is done using external Python script
``fetch-ocsp-response``, which has been originally developed in Perl
as part of h2o project (https://github.com/h2o/h2o), and was
translated into Python.
The script file is usually installed under
``$(prefix)/share/nghttp2/`` directory. The actual path to script can
be customized using :option:`--fetch-ocsp-response-file` option.
If OCSP query is failed, previous OCSP response, if any, is continued
to be used.
TLS SESSION RESUMPTION
----------------------
nghttpx supports TLS session resumption through both session ID and
session ticket.
SESSION ID RESUMPTION
~~~~~~~~~~~~~~~~~~~~~
By default, session ID is shared by all worker threads.
If :option:`--tls-session-cache-memcached` is given, nghttpx will
insert serialized session data to memcached with
``nghttpx:tls-session-cache:`` + lowercased hex string of session ID
as a memcached entry key, with expiry time 12 hours. Session timeout
is set to 12 hours.
TLS SESSION TICKET RESUMPTION
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
By default, session ticket is shared by all worker threads. The
automatic key rotation is also enabled by default. Every an hour, new
encryption key is generated, and previous encryption key becomes
decryption only key. We set session timeout to 12 hours, and thus we
keep at most 12 keys.
If :option:`--tls-ticket-key-memcached` is given, encryption keys are
retrieved from memcached. nghttpx just reads keys from memcached; one
has to deploy key generator program to update keys frequently (e.g.,
every 1 hour). The example key generator tlsticketupdate.go is
available under contrib directory in nghttp2 archive. The memcached
entry key is ``nghttpx:tls-ticket-key``. The data format stored in
memcached is the binary format described below::
+--------------+-------+----------------+
| VERSION (4) |LEN (2)|KEY(48 or 80) ...
+--------------+-------+----------------+
^ |
| |
+------------------------+
(LEN, KEY) pair can be repeated
All numbers in the above figure is bytes. All integer fields are
network byte order.
First 4 bytes integer VERSION field, which must be 1. The 2 bytes
integer LEN field gives the length of following KEY field, which
contains key. If :option:`--tls-ticket-key-cipher`\=aes-128-cbc is
used, LEN must be 48. If
:option:`--tls-ticket-key-cipher`\=aes-256-cbc is used, LEN must be
80. LEN and KEY pair can be repeated multiple times to store multiple
keys. The key appeared first is used as encryption key. All the
remaining keys are used as decryption only.
If :option:`--tls-ticket-key-file` is given, encryption key is read
from the given file. In this case, nghttpx does not rotate key
automatically. To rotate key, one has to restart nghttpx (see
SIGNALS).
MRUBY SCRIPTING
---------------
.. warning::
The current mruby extension API is experimental and not frozen. The
API is subject to change in the future release.
nghttpx allows users to extend its capability using mruby scripts.
nghttpx has 2 hook points to execute mruby script: request phase and
response phase. The request phase hook is invoked after all request
header fields are received from client. The response phase hook is
invoked after all response header fields are received from backend
server. These hooks allows users to modify header fields, or common
HTTP variables, like authority or request path, and even return custom
response without forwarding request to backend servers.
To set request phase hook, use :option:`--request-phase-file` option.
To set response phase hook, use :option:`--response-phase-file`
option.
For request and response phase hook, user calls :rb:meth:`Nghttpx.run`
with block. The :rb:class:`Nghttpx::Env` is passed to the block.
User can can access :rb:class:`Nghttpx::Request` and
:rb:class:`Nghttpx::Response` objects via :rb:attr:`Nghttpx::Env#req`
and :rb:attr:`Nghttpx::Env#resp` respectively.
.. rb:module:: Nghttpx
.. rb:classmethod:: run(&block)
Run request or response phase hook with given *block*.
:rb:class:`Nghttpx::Env` object is passed to the given block.
.. rb:const:: REQUEST_PHASE
Constant to represent request phase.
.. rb:const:: RESPONSE_PHASE
Constant to represent response phase.
.. rb:class:: Env
Object to represent current request specific context.
.. rb:attr_reader:: req
Return :rb:class:`Request` object.
.. rb:attr_reader:: resp
Return :rb:class:`Response` object.
.. rb:attr_reader:: ctx
Return Ruby hash object. It persists until request finishes.
So values set in request phase hoo can be retrieved in
response phase hook.
.. rb:attr_reader:: phase
Return the current phase.
.. rb:attr_reader:: remote_addr
Return IP address of a remote client.
.. rb:class:: Request
Object to represent request from client. The modification to
Request object is allowed only in request phase hook.
.. rb:attr_reader:: http_version_major
Return HTTP major version.
.. rb:attr_reader:: http_version_minor
Return HTTP minor version.
.. rb:attr_accessor:: method
HTTP method. On assignment, copy of given value is assigned.
We don't accept arbitrary method name. We will document them
later, but well known methods, like GET, PUT and POST, are all
supported.
.. rb:attr_accessor:: authority
Authority (i.e., example.org), including optional port
component . On assignment, copy of given value is assigned.
.. rb:attr_accessor:: scheme
Scheme (i.e., http, https). On assignment, copy of given
value is assigned.
.. rb:attr_accessor:: path
Request path, including query component (i.e., /index.html).
On assignment, copy of given value is assigned. The path does
not include authority component of URI.
.. rb:attr_reader:: headers
Return Ruby hash containing copy of request header fields.
Changing values in returned hash does not change request
header fields actually used in request processing. Use
:rb:meth:`Nghttpx::Request#add_header` or
:rb:meth:`Nghttpx::Request#set_header` to change request
header fields.
.. rb:method:: add_header(key, value)
Add header entry associated with key. The value can be single
string or array of string. It does not replace any existing
values associated with key.
.. rb:method:: set_header(key, value)
Set header entry associated with key. The value can be single
string or array of string. It replaces any existing values
associated with key.
.. rb:method:: clear_headers
Clear all existing request header fields.
.. rb:method:: push uri
Initiate to push resource identified by *uri*. Only HTTP/2
protocol supports this feature. For the other protocols, this
method is noop. *uri* can be absolute URI, absolute path or
relative path to the current request. For absolute or
relative path, scheme and authority are inherited from the
current request. Currently, method is always GET. nghttpx
will issue request to backend servers to fulfill this request.
The request and response phase hooks will be called for pushed
resource as well.
.. rb:class:: Response
Object to represent response from backend server.
.. rb:attr_reader:: http_version_major
Return HTTP major version.
.. rb:attr_reader:: http_version_minor
Return HTTP minor version.
.. rb:attr_accessor:: status
HTTP status code. It must be in the range [200, 999],
inclusive. The non-final status code is not supported in
mruby scripting at the moment.
.. rb:attr_reader:: headers
Return Ruby hash containing copy of response header fields.
Changing values in returned hash does not change response
header fields actually used in response processing. Use
:rb:meth:`Nghttpx::Response#add_header` or
:rb:meth:`Nghttpx::Response#set_header` to change response
header fields.
.. rb:method:: add_header(key, value)
Add header entry associated with key. The value can be single
string or array of string. It does not replace any existing
values associated with key.
.. rb:method:: set_header(key, value)
Set header entry associated with key. The value can be single
string or array of string. It replaces any existing values
associated with key.
.. rb:method:: clear_headers
Clear all existing response header fields.
.. rb:method:: return(body)
Return custom response *body* to a client. When this method
is called in request phase hook, the request is not forwarded
to the backend, and response phase hook for this request will
not be invoked. When this method is called in resonse phase
hook, response from backend server is canceled and discarded.
The status code and response header fields should be set
before using this method. To set status code, use :rb:meth To
set response header fields, use
:rb:attr:`Nghttpx::Response#status`. If status code is not
set, 200 is used. :rb:meth:`Nghttpx::Response#add_header` and
:rb:meth:`Nghttpx::Response#set_header`. When this method is
invoked in response phase hook, the response headers are
filled with the ones received from backend server. To send
completely custom header fields, first call
:rb:meth:`Nghttpx::Response#clear_headers` to erase all
existing header fields, and then add required header fields.
It is an error to call this method twice for a given request.
MRUBY EXAMPLES
~~~~~~~~~~~~~~
Modify requet path:
.. code-block:: ruby
Nghttpx.run do |env|
env.req.path = "/apps#{env.req.path}"
end
Note that the file containing the above script must be set with
:option:`--request-phase-file` option since we modify request path.
Restrict permission of viewing a content to a specific client
addresses:
.. code-block:: ruby
Nghttpx.run do |env|
allowed_clients = ["127.0.0.1", "::1"]
if env.req.path.start_with?("/log/") &&
!allowed_clients.include?(env.remote_addr) then
env.resp.status = 404
env.resp.return "permission denied"
end
end
SEE ALSO
--------

View File

@@ -19,7 +19,7 @@ FILES
ignored.
To specify private key and certificate file which are given as
positional arguments in commnad-line, use ``private-key-file`` and
positional arguments in command-line, use ``private-key-file`` and
``certificate-file``.
:option:`--conf` option cannot be used in the configuration file and
@@ -59,17 +59,12 @@ header field to initiate server push:
Link: </fonts/font.woff>; rel=preload
Link: </css/theme.css>; rel=preload
Currently, the following restrictions are applied for server push:
Currently, the following restriction is applied for server push:
1. URI-reference must not contain authority. If it exists, it is not
pushed. ``/fonts/font.woff`` and ``css/theme.css`` are eligible to
be pushed. ``https://example.org/fonts/font.woff`` and
``//example.org/css/theme.css`` are not.
2. The associated stream must have method "GET" or "POST". The
1. The associated stream must have method "GET" or "POST". The
associated stream's status code must be 200.
These limitations may be loosened in the future release.
This limitation may be loosened in the future release.
UNIX DOMAIN SOCKET
------------------
@@ -84,6 +79,313 @@ deletes it. However, if SIGUSR2 is used to execute new binary and
both old and new configurations use same filename, new binary does not
delete the socket and continues to use it.
OCSP STAPLING
-------------
OCSP query is done using external Python script
``fetch-ocsp-response``, which has been originally developed in Perl
as part of h2o project (https://github.com/h2o/h2o), and was
translated into Python.
The script file is usually installed under
``$(prefix)/share/nghttp2/`` directory. The actual path to script can
be customized using :option:`--fetch-ocsp-response-file` option.
If OCSP query is failed, previous OCSP response, if any, is continued
to be used.
TLS SESSION RESUMPTION
----------------------
nghttpx supports TLS session resumption through both session ID and
session ticket.
SESSION ID RESUMPTION
~~~~~~~~~~~~~~~~~~~~~
By default, session ID is shared by all worker threads.
If :option:`--tls-session-cache-memcached` is given, nghttpx will
insert serialized session data to memcached with
``nghttpx:tls-session-cache:`` + lowercased hex string of session ID
as a memcached entry key, with expiry time 12 hours. Session timeout
is set to 12 hours.
TLS SESSION TICKET RESUMPTION
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
By default, session ticket is shared by all worker threads. The
automatic key rotation is also enabled by default. Every an hour, new
encryption key is generated, and previous encryption key becomes
decryption only key. We set session timeout to 12 hours, and thus we
keep at most 12 keys.
If :option:`--tls-ticket-key-memcached` is given, encryption keys are
retrieved from memcached. nghttpx just reads keys from memcached; one
has to deploy key generator program to update keys frequently (e.g.,
every 1 hour). The example key generator tlsticketupdate.go is
available under contrib directory in nghttp2 archive. The memcached
entry key is ``nghttpx:tls-ticket-key``. The data format stored in
memcached is the binary format described below::
+--------------+-------+----------------+
| VERSION (4) |LEN (2)|KEY(48 or 80) ...
+--------------+-------+----------------+
^ |
| |
+------------------------+
(LEN, KEY) pair can be repeated
All numbers in the above figure is bytes. All integer fields are
network byte order.
First 4 bytes integer VERSION field, which must be 1. The 2 bytes
integer LEN field gives the length of following KEY field, which
contains key. If :option:`--tls-ticket-key-cipher`\=aes-128-cbc is
used, LEN must be 48. If
:option:`--tls-ticket-key-cipher`\=aes-256-cbc is used, LEN must be
80. LEN and KEY pair can be repeated multiple times to store multiple
keys. The key appeared first is used as encryption key. All the
remaining keys are used as decryption only.
If :option:`--tls-ticket-key-file` is given, encryption key is read
from the given file. In this case, nghttpx does not rotate key
automatically. To rotate key, one has to restart nghttpx (see
SIGNALS).
MRUBY SCRIPTING
---------------
.. warning::
The current mruby extension API is experimental and not frozen. The
API is subject to change in the future release.
nghttpx allows users to extend its capability using mruby scripts.
nghttpx has 2 hook points to execute mruby script: request phase and
response phase. The request phase hook is invoked after all request
header fields are received from client. The response phase hook is
invoked after all response header fields are received from backend
server. These hooks allows users to modify header fields, or common
HTTP variables, like authority or request path, and even return custom
response without forwarding request to backend servers.
To set request phase hook, use :option:`--request-phase-file` option.
To set response phase hook, use :option:`--response-phase-file`
option.
For request and response phase hook, user calls :rb:meth:`Nghttpx.run`
with block. The :rb:class:`Nghttpx::Env` is passed to the block.
User can can access :rb:class:`Nghttpx::Request` and
:rb:class:`Nghttpx::Response` objects via :rb:attr:`Nghttpx::Env#req`
and :rb:attr:`Nghttpx::Env#resp` respectively.
.. rb:module:: Nghttpx
.. rb:classmethod:: run(&block)
Run request or response phase hook with given *block*.
:rb:class:`Nghttpx::Env` object is passed to the given block.
.. rb:const:: REQUEST_PHASE
Constant to represent request phase.
.. rb:const:: RESPONSE_PHASE
Constant to represent response phase.
.. rb:class:: Env
Object to represent current request specific context.
.. rb:attr_reader:: req
Return :rb:class:`Request` object.
.. rb:attr_reader:: resp
Return :rb:class:`Response` object.
.. rb:attr_reader:: ctx
Return Ruby hash object. It persists until request finishes.
So values set in request phase hoo can be retrieved in
response phase hook.
.. rb:attr_reader:: phase
Return the current phase.
.. rb:attr_reader:: remote_addr
Return IP address of a remote client.
.. rb:class:: Request
Object to represent request from client. The modification to
Request object is allowed only in request phase hook.
.. rb:attr_reader:: http_version_major
Return HTTP major version.
.. rb:attr_reader:: http_version_minor
Return HTTP minor version.
.. rb:attr_accessor:: method
HTTP method. On assignment, copy of given value is assigned.
We don't accept arbitrary method name. We will document them
later, but well known methods, like GET, PUT and POST, are all
supported.
.. rb:attr_accessor:: authority
Authority (i.e., example.org), including optional port
component . On assignment, copy of given value is assigned.
.. rb:attr_accessor:: scheme
Scheme (i.e., http, https). On assignment, copy of given
value is assigned.
.. rb:attr_accessor:: path
Request path, including query component (i.e., /index.html).
On assignment, copy of given value is assigned. The path does
not include authority component of URI.
.. rb:attr_reader:: headers
Return Ruby hash containing copy of request header fields.
Changing values in returned hash does not change request
header fields actually used in request processing. Use
:rb:meth:`Nghttpx::Request#add_header` or
:rb:meth:`Nghttpx::Request#set_header` to change request
header fields.
.. rb:method:: add_header(key, value)
Add header entry associated with key. The value can be single
string or array of string. It does not replace any existing
values associated with key.
.. rb:method:: set_header(key, value)
Set header entry associated with key. The value can be single
string or array of string. It replaces any existing values
associated with key.
.. rb:method:: clear_headers
Clear all existing request header fields.
.. rb:method:: push uri
Initiate to push resource identified by *uri*. Only HTTP/2
protocol supports this feature. For the other protocols, this
method is noop. *uri* can be absolute URI, absolute path or
relative path to the current request. For absolute or
relative path, scheme and authority are inherited from the
current request. Currently, method is always GET. nghttpx
will issue request to backend servers to fulfill this request.
The request and response phase hooks will be called for pushed
resource as well.
.. rb:class:: Response
Object to represent response from backend server.
.. rb:attr_reader:: http_version_major
Return HTTP major version.
.. rb:attr_reader:: http_version_minor
Return HTTP minor version.
.. rb:attr_accessor:: status
HTTP status code. It must be in the range [200, 999],
inclusive. The non-final status code is not supported in
mruby scripting at the moment.
.. rb:attr_reader:: headers
Return Ruby hash containing copy of response header fields.
Changing values in returned hash does not change response
header fields actually used in response processing. Use
:rb:meth:`Nghttpx::Response#add_header` or
:rb:meth:`Nghttpx::Response#set_header` to change response
header fields.
.. rb:method:: add_header(key, value)
Add header entry associated with key. The value can be single
string or array of string. It does not replace any existing
values associated with key.
.. rb:method:: set_header(key, value)
Set header entry associated with key. The value can be single
string or array of string. It replaces any existing values
associated with key.
.. rb:method:: clear_headers
Clear all existing response header fields.
.. rb:method:: return(body)
Return custom response *body* to a client. When this method
is called in request phase hook, the request is not forwarded
to the backend, and response phase hook for this request will
not be invoked. When this method is called in resonse phase
hook, response from backend server is canceled and discarded.
The status code and response header fields should be set
before using this method. To set status code, use :rb:meth To
set response header fields, use
:rb:attr:`Nghttpx::Response#status`. If status code is not
set, 200 is used. :rb:meth:`Nghttpx::Response#add_header` and
:rb:meth:`Nghttpx::Response#set_header`. When this method is
invoked in response phase hook, the response headers are
filled with the ones received from backend server. To send
completely custom header fields, first call
:rb:meth:`Nghttpx::Response#clear_headers` to erase all
existing header fields, and then add required header fields.
It is an error to call this method twice for a given request.
MRUBY EXAMPLES
~~~~~~~~~~~~~~
Modify requet path:
.. code-block:: ruby
Nghttpx.run do |env|
env.req.path = "/apps#{env.req.path}"
end
Note that the file containing the above script must be set with
:option:`--request-phase-file` option since we modify request path.
Restrict permission of viewing a content to a specific client
addresses:
.. code-block:: ruby
Nghttpx.run do |env|
allowed_clients = ["127.0.0.1", "::1"]
if env.req.path.start_with?("/log/") &&
!allowed_clients.include?(env.remote_addr) then
env.resp.status = 404
env.resp.return "permission denied"
end
end
SEE ALSO
--------

View File

@@ -1,5 +1,5 @@
API Reference
=============
Programmers' Guide
==================
Includes
--------
@@ -20,17 +20,17 @@ nghttp2 callback functions directly or indirectly. It will lead to the
crash. You can submit requests or frames in the callbacks then call
these functions outside the callbacks.
Currently, `nghttp2_session_send()` and `nghttp2_session_mem_send()`
do not send client connection preface
(:macro:`NGHTTP2_CLIENT_CONNECTION_PREFACE`). The applications are
responsible to send it before sending any HTTP/2 frames using these
functions if :type:`nghttp2_session` is configured as client.
Similarly, `nghttp2_session_recv()` and `nghttp2_session_mem_recv()`
do not consume client connection preface unless
`nghttp2_option_set_recv_client_preface()` is used with nonzero option
value. The applications are responsible to receive it before calling
these functions if :type:`nghttp2_session` is configured as server and
`nghttp2_option_set_recv_client_preface()` is not used.
`nghttp2_session_send()` and `nghttp2_session_mem_send()` send first
24 bytes of client magic string (MAGIC)
(:macro:`NGHTTP2_CLIENT_MAGIC`) on client configuration. The
applications are responsible to send SETTINGS frame as part of
connection preface using `nghttp2_submit_settings()`. Similarly,
`nghttp2_session_recv()` and `nghttp2_session_mem_recv()` consume
MAGIC on server configuration unless
`nghttp2_option_set_no_recv_client_magic()` is used with nonzero
option value.
.. _http-messaging:
HTTP Messaging
--------------

View File

@@ -36,8 +36,9 @@ with the toolchain and installed under ``$ANDROID_HOME/usr/local``.
We recommend to build these libraries as static library to make the
deployment easier. libxml2 support is currently disabled.
We use zlib which comes with Android NDK, so we don't have to build it
by ourselves.
Although zlib comes with Android NDK, it seems not to be a part of
public API, so we have to built it for our own. That also provides us
proper .pc file as a bonus.
If SPDY support is required for nghttpx and h2load, build and install
spdylay as well.
@@ -95,10 +96,41 @@ patch, to configure libev, use the following script:
And run ``make install`` to build and install.
To configure zlib, use the following script:
.. code-block:: sh
#!/bin/sh -e
if [ -z "$ANDROID_HOME" ]; then
echo 'No $ANDROID_HOME specified.'
exit 1
fi
PREFIX=$ANDROID_HOME/usr/local
TOOLCHAIN=$ANDROID_HOME/toolchain
PATH=$TOOLCHAIN/bin:$PATH
HOST=arm-linux-androideabi
CC=$HOST-gcc \
AR=$HOST-ar \
LD=$HOST-ld \
RANLIB=$HOST-ranlib \
STRIP=$HOST-strip \
./configure \
--prefix=$PREFIX \
--libdir=$PREFIX/lib \
--includedir=$PREFIX/include \
--static
And run ``make install`` to build and install.
To configure spdylay, use the following script:
.. code-block:: sh
#!/bin/sh -e
if [ -z "$ANDROID_HOME" ]; then
echo 'No $ANDROID_HOME specified.'
exit 1
@@ -119,11 +151,7 @@ To configure spdylay, use the following script:
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
LDFLAGS="-L$PREFIX/lib"
And run ``make install`` to build and install. After spdylay
installation, edit $ANDROID_HOME/usr/local/lib/pkgconfig/libspdylay.pc
and remove the following line::
Requires.private: zlib
And run ``make install`` to build and install.
After prerequisite libraries are prepared, run ``android-config`` and
then ``android-make`` to compile nghttp2 source files.

View File

@@ -50,8 +50,9 @@ Flow Control
------------
HTTP/2 and SPDY/3 or later employ flow control and it may affect
benchmarking results. To adjust receiver flow control window size,
there is following options:
benchmarking results. By default, h2load uses large enough flow
control window, which effectively disables flow control. To adjust
receiver flow control window size, there are following options:
``-w``
Sets the stream level initial window size to
@@ -86,5 +87,5 @@ If multiple URIs are specified, they are used in round robin manner.
.. note::
Please note that h2load uses sheme, host and port in the first URI
Please note that h2load uses scheme, host and port in the first URI
and ignores those parts in the rest of the URIs.

View File

@@ -28,6 +28,7 @@ Contents:
h2load.1
nghttpx-howto
h2load-howto
programmers-guide
apiref
libnghttp2_asio
python-apiref
@@ -48,5 +49,5 @@ https://github.com/tatsuhiro-t/nghttp2/releases
Resources
---------
* http://tools.ietf.org/html/draft-ietf-httpbis-http2-14
* http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09
* HTTP/2 https://tools.ietf.org/html/rfc7540
* HPACK https://tools.ietf.org/html/rfc7541

View File

@@ -80,7 +80,7 @@ status code, in the above example, which is 200. The second argument,
which is omitted in the above example, is additional header fields to
send.
``nghttp2::asio_http2::server::response::end`` sends responde body.
``nghttp2::asio_http2::server::response::end`` sends response body.
In the above example, we send string "hello, world".
The life time of req and res object ends after the callback set by
@@ -277,7 +277,7 @@ response header fields and response body to the console screen:
``boost::asio::io_service`` object and remote server address. When
connection is made, the callback function passed to
``nghttp2::asio_http2::client::on_connect`` is invoked with connected
address as its paramter. After this callback call, use
address as its parameter. After this callback call, use
``nghttp2::asio_http2::session::submit`` to send request to the
server. You can submit multiple requests at once without waiting for
the completion of previous request.

View File

@@ -21,7 +21,7 @@ SSL/TLS, the frontend also supports SPDY protocol.
By default, this mode's frontend connection is encrypted using
SSL/TLS. So server's private key and certificate must be supplied to
the command line (or through configuration file). In this case, the
fontend protocol selection will is done via ALPN or NPN.
frontend protocol selection will be done via ALPN or NPN.
With ``--frontend-no-tls`` option, user can turn off SSL/TLS in
frontend connection. In this case, SPDY protocol is not available
@@ -243,7 +243,7 @@ Read/write rate limit
---------------------
nghttpx supports transfer rate limiting on frontend connections. You
can do rate limit per frontend connection for reading and writeing
can do rate limit per frontend connection for reading and writing
individually.
To perform rate limit for reading, use ``--read-rate`` and

View File

@@ -220,6 +220,10 @@ HTTP/2 servers
This is a value of ``:path`` header field.
.. py:attribute:: headers
Request header fields.
A :py:class:`BaseRequestHandler` has the following methods:
.. py:method:: on_headers()
@@ -249,10 +253,28 @@ HTTP/2 servers
Send response. The *status* is HTTP status code. The *headers*
is additional response headers. The *:status* header field will
be appended by the library. The *body* is the response body.
It could be ``None`` if response body is empty. Or it must be
instance of either ``str``, ``bytes`` or :py:class:`io.IOBase`.
If instance of ``str`` is specified, it will be encoded using
UTF-8.
It could be ``None`` if response body is empty. Or it must be
instance of either ``str``, ``bytes``, :py:class:`io.IOBase` or
callable, called body generator, which takes one parameter,
size. The body generator generates response body. It can pause
generation of response so that it can wait for slow backend data
generation. When invoked, it should return tuple, byte string
at most size length and flag. The flag is either
:py:data:`DATA_OK`, :py:data:`DATA_EOF` or
:py:data:`DATA_DEFERRED`. For non-empty byte string and it is
not the last chunk of response, :py:data:`DATA_OK` must be
returned as flag. If this is the last chunk of the response
(byte string could be ``None``), :py:data:`DATA_EOF` must be
returned as flag. If there is no data available right now, but
additional data are anticipated, return tuple (``None``,
:py:data:`DATA_DEFERRED`). When data arrived, call
:py:meth:`resume()` and restart response body transmission.
Only the body generator can pause response body generation;
instance of :py:class:`io.IOBase` must not block.
If instance of ``str`` is specified as *body*, it will be
encoded using UTF-8.
The *headers* is a list of tuple of the form ``(name,
value)``. The ``name`` and ``value`` can be either byte string
@@ -273,10 +295,8 @@ HTTP/2 servers
The *status* is HTTP status code. The *headers* is additional
response headers. The ``:status`` header field is appended by
the library. The *body* is the response body. It could be
``None`` if response body is empty. Or it must be instance of
either ``str``, ``bytes`` or ``io.IOBase``. If instance of
``str`` is specified, it is encoded using UTF-8.
the library. The *body* is the response body. It has the same
semantics of *body* parameter of :py:meth:`send_response()`.
The headers and request_headers are a list of tuple of the form
``(name, value)``. The ``name`` and ``value`` can be either byte
@@ -288,6 +308,27 @@ HTTP/2 servers
Raises the exception if any error occurs.
.. py:method:: resume()
Signals the restarting of response body transmission paused by
``DATA_DEFERRED`` from the body generator (see
:py:meth:`send_response()` about the body generator). It is not
an error calling this method while response body transmission is
not paused.
.. py:data:: DATA_OK
``DATA_OK`` indicates non empty data is generated from body generator.
.. py:data:: DATA_EOF
``DATA_EOF`` indicates the end of response body.
.. py:data:: DATA_DEFERRED
``DATA_DEFERRED`` indicates that data are not available right now
and response should be paused.
The following example illustrates :py:class:`HTTP2Server` and
:py:class:`BaseRequestHandler` usage:
@@ -296,6 +337,7 @@ The following example illustrates :py:class:`HTTP2Server` and
#!/usr/bin/env python
import io, ssl
import nghttp2
class Handler(nghttp2.BaseRequestHandler):
@@ -311,9 +353,85 @@ The following example illustrates :py:class:`HTTP2Server` and
body=io.BytesIO(b'nghttp2-python FTW'))
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ctx.options = ssl.OP_ALL | ssl.OP_NO_SSLv2
ctx.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3
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()
The following example illustrates HTTP/2 server using asynchronous
response body generation. This is simplified reverse proxy:
.. code-block:: python
#!/usr/bin/env python
import ssl
import os
import urllib
import asyncio
import io
import nghttp2
@asyncio.coroutine
def get_http_header(handler, url):
url = urllib.parse.urlsplit(url)
ssl = url.scheme == 'https'
if url.port == None:
if url.scheme == 'https':
port = 443
else:
port = 80
else:
port = url.port
connect = asyncio.open_connection(url.hostname, port, ssl=ssl)
reader, writer = yield from connect
req = 'GET {path} HTTP/1.0\r\n\r\n'.format(path=url.path or '/')
writer.write(req.encode('utf-8'))
# skip response header fields
while True:
line = yield from reader.readline()
line = line.rstrip()
if not line:
break
# read body
while True:
b = yield from reader.read(4096)
if not b:
break
handler.buf.write(b)
writer.close()
handler.buf.seek(0)
handler.eof = True
handler.resume()
class Body:
def __init__(self, handler):
self.handler = handler
self.handler.eof = False
self.handler.buf = io.BytesIO()
def generate(self, n):
buf = self.handler.buf
data = buf.read1(n)
if not data and not self.handler.eof:
return None, nghttp2.DATA_DEFERRED
return data, nghttp2.DATA_EOF if self.handler.eof else nghttp2.DATA_OK
class Handler(nghttp2.BaseRequestHandler):
def on_headers(self):
body = Body(self)
asyncio.async(get_http_header(
self, 'http://localhost' + self.path.decode('utf-8')))
self.send_response(status=200, body=body.generate)
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ctx.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3
ctx.load_cert_chain('server.crt', 'server.key')
server = nghttp2.HTTP2Server(('127.0.0.1', 8443), Handler, ssl=ctx)
server.serve_forever()

View File

@@ -1,25 +1,25 @@
Tutorial: HTTP/2 client
=========================
In this tutorial, we are going to write very primitive HTTP/2
In this tutorial, we are going to write a very primitive HTTP/2
client. The complete source code, `libevent-client.c`_, is attached at
the end of this page. It also resides in examples directory in the
archive or repository.
the end of this page. It also resides in the examples directory in
the archive or repository.
This simple client takes 1 argument, HTTPS URI, and retrieves the
resource denoted by the URI. Its synopsis is like this::
This simple client takes a single HTTPS URI and retrieves the resource
at the URI. The synopsis is::
$ libevent-client HTTPS_URI
We use libevent in this tutorial to handle networking I/O. Please
note that nghttp2 itself does not depend on libevent.
First we do some setup routine for libevent and OpenSSL library in
function ``main()`` and ``run()``, which is not so relevant to nghttp2
library use. The one thing you should look at is setup NPN callback.
The NPN callback is used for the client to select the next application
protocol over the SSL/TLS transport. In this tutorial, we use
`nghttp2_select_next_protocol()` function to select the HTTP/2
The client starts with some libevent and OpenSSL setup in the
``main()`` and ``run()`` functions. This setup isn't specific to
nghttp2, but one thing you should look at is setup of the NPN
callback. The NPN callback is used by the client to select the next
application protocol over TLS. In this tutorial, we use the
`nghttp2_select_next_protocol()` helper function to select the HTTP/2
protocol the library supports::
static int select_next_proto_cb(SSL *ssl _U_, unsigned char **out,
@@ -31,8 +31,8 @@ protocol the library supports::
return SSL_TLSEXT_ERR_OK;
}
The callback is set to the SSL_CTX object using
``SSL_CTX_set_next_proto_select_cb()`` function::
The callback is added to the SSL_CTX object using
``SSL_CTX_set_next_proto_select_cb()``::
static SSL_CTX *create_ssl_ctx(void) {
SSL_CTX *ssl_ctx;
@@ -49,8 +49,10 @@ The callback is set to the SSL_CTX object using
return ssl_ctx;
}
We use ``http2_session_data`` structure to store the data related to
the HTTP/2 session::
The example client defines a couple of structs:
We define and use a ``http2_session_data`` structure to store data
related to the HTTP/2 session::
typedef struct {
nghttp2_session *session;
@@ -59,17 +61,17 @@ the HTTP/2 session::
http2_stream_data *stream_data;
} http2_session_data;
Since this program only handles 1 URI, it uses only 1 stream. We store
its stream specific data in ``http2_stream_data`` structure and the
``stream_data`` points to it. The ``struct http2_stream_data`` is
defined as follows::
Since this program only handles one URI, it uses only one stream. We
store the single stream's data in a ``http2_stream_data`` structure
and the ``stream_data`` points to it. The ``http2_stream_data``
structure is defined as follows::
typedef struct {
/* The NULL-terminated URI string to retreive. */
/* The NULL-terminated URI string to retrieve. */
const char *uri;
/* Parsed result of the |uri| */
struct http_parser_url *u;
/* The authroity portion of the |uri|, not NULL-terminated */
/* The authority portion of the |uri|, not NULL-terminated */
char *authority;
/* The path portion of the |uri|, including query, not
NULL-terminated */
@@ -82,12 +84,12 @@ defined as follows::
int32_t stream_id;
} http2_stream_data;
We creates and initializes these structures in
We create and initialize these structures in
``create_http2_session_data()`` and ``create_http2_stream_data()``
respectively.
Then we call function ``initiate_connection()`` to start connecting to
the remote server::
``initiate_connection()`` is called to start the connection to the
remote server. It's defined as::
static void initiate_connection(struct event_base *evbase, SSL_CTX *ssl_ctx,
const char *host, uint16_t port,
@@ -110,11 +112,11 @@ the remote server::
session_data->bev = bev;
}
We set 3 callbacks for the bufferevent: ``reacb``, ``writecb`` and
``eventcb``.
``initiate_connection()`` creates a bufferevent for the connection and
sets up three callbacks: ``readcb``, ``writecb``, and ``eventcb``.
The ``eventcb()`` is invoked by libevent event loop when an event
(e.g., connection has been established, timeout, etc) happens on the
The ``eventcb()`` is invoked by the libevent event loop when an event
(e.g. connection has been established, timeout, etc.) occurs on the
underlying network socket::
static void eventcb(struct bufferevent *bev, short events, void *ptr) {
@@ -142,11 +144,15 @@ underlying network socket::
delete_http2_session_data(session_data);
}
For ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR`` and ``BEV_EVENT_TIMEOUT``
event, we just simply tear down the connection. The
``BEV_EVENT_CONNECTED`` event is invoked when SSL/TLS handshake is
finished successfully. We first initialize nghttp2 session object in
``initialize_nghttp2_session()`` function::
For ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR``, and ``BEV_EVENT_TIMEOUT``
events, we just simply tear down the connection.
The ``BEV_EVENT_CONNECTED`` event is invoked when the SSL/TLS
handshake has completed successfully. After this we're ready to begin
communicating via HTTP/2.
The ``initialize_nghttp2_session()`` function initializes the nghttp2
session object and several callbacks::
static void initialize_nghttp2_session(http2_session_data *session_data) {
nghttp2_session_callbacks *callbacks;
@@ -175,18 +181,19 @@ finished successfully. We first initialize nghttp2 session object in
nghttp2_session_callbacks_del(callbacks);
}
Since we are creating client, we use `nghttp2_session_client_new()` to
initialize nghttp2 session object. We setup 7 callbacks for the
nghttp2 session. We'll explain these callbacks later.
Since we are creating a client, we use `nghttp2_session_client_new()`
to initialize the nghttp2 session object. The callbacks setup are
explained later.
The `delete_http2_session_data()` destroys ``session_data`` and frees
its bufferevent, so it closes underlying connection as well. It also
calls `nghttp2_session_del()` to delete nghttp2 session object.
The `delete_http2_session_data()` function destroys ``session_data``
and frees its bufferevent, so the underlying connection is closed. It
also calls `nghttp2_session_del()` to delete the nghttp2 session
object.
We begin HTTP/2 communication by sending client connection preface,
which is 24 bytes magic byte sequence
(:macro:`NGHTTP2_CLIENT_CONNECTION_PREFACE`) and SETTINGS frame. The
transmission of client connection header is done in
A HTTP/2 connection begins by sending the client connection preface,
which is a 24 byte magic byte string (:macro:`NGHTTP2_CLIENT_MAGIC`),
followed by a SETTINGS frame. The 24 byte magic string is sent
automatically by nghttp2. We send the SETTINGS frame in
``send_client_connection_header()``::
static void send_client_connection_header(http2_session_data *session_data) {
@@ -194,8 +201,7 @@ transmission of client connection header is done in
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
int rv;
bufferevent_write(session_data->bev, NGHTTP2_CLIENT_CONNECTION_PREFACE,
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
/* client 24 bytes magic string will be sent by nghttp2 library */
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv,
ARRLEN(iv));
if (rv != 0) {
@@ -203,17 +209,17 @@ transmission of client connection header is done in
}
}
Here we specify SETTINGS_MAX_CONCURRENT_STREAMS to 100, which is
really not needed for this tiny example progoram, but we are
demonstrating the use of SETTINGS frame. To queue the SETTINGS frame
for the transmission, we use `nghttp2_submit_settings()`. Note that
`nghttp2_submit_settings()` function only queues the frame and not
actually send it. All ``nghttp2_submit_*()`` family functions have
this property. To actually send the frame, `nghttp2_session_send()` is
used, which is described about later.
Here we specify SETTINGS_MAX_CONCURRENT_STREAMS as 100. This is not
needed for this tiny example program, it just demonstrates use of the
SETTINGS frame. To queue the SETTINGS frame for transmission, we call
`nghttp2_submit_settings()`. Note that `nghttp2_submit_settings()`
only queues the frame for transmission, and doesn't actually send it.
All ``nghttp2_submit_*()`` family functions have this property. To
actually send the frame, `nghttp2_session_send()` has to be called,
which is described (and called) later.
After the transmission of client connection header, we enqueue HTTP
request in ``submit_request()`` function::
After the transmission of the client connection header, we enqueue the
HTTP request in the ``submit_request()`` function::
static void submit_request(http2_session_data *session_data) {
int32_t stream_id;
@@ -237,17 +243,18 @@ request in ``submit_request()`` function::
stream_data->stream_id = stream_id;
}
We build HTTP request header fields in ``hdrs`` which is an array of
:type:`nghttp2_nv`. There are 4 header fields to be sent: ``:method``,
``:scheme``, ``:authority`` and ``:path``. To queue this HTTP request,
we use `nghttp2_submit_request()` function. The `stream_data` is
passed in *stream_user_data* parameter. It is used in nghttp2
callbacks which we'll describe about later.
We build the HTTP request header fields in ``hdrs``, which is an array
of :type:`nghttp2_nv`. There are four header fields to be sent:
``:method``, ``:scheme``, ``:authority``, and ``:path``. To queue the
HTTP request, we call `nghttp2_submit_request()`. The ``stream_data``
is passed via the *stream_user_data* parameter, which is helpfully
later passed back to callback functions.
`nghttp2_submit_request()` returns the newly assigned stream ID for
this request.
the request.
The next bufferevent callback is ``readcb()``, which is invoked when
data is available to read in the bufferevent input buffer::
data is available to read from the bufferevent input buffer::
static void readcb(struct bufferevent *bev, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
@@ -273,12 +280,13 @@ data is available to read in the bufferevent input buffer::
}
}
In this function, we feed all unprocessed, received data to nghttp2
session object using `nghttp2_session_mem_recv()` function. The
In this function we feed all unprocessed, received data to the nghttp2
session object using the `nghttp2_session_mem_recv()` function.
`nghttp2_session_mem_recv()` processes the received data and may
invoke nghttp2 callbacks and also queue frames. Since there may be
pending frames, we call ``session_send()`` function to send those
frames. The ``session_send()`` function is defined as follows::
invoke nghttp2 callbacks and queue frames for transmission. Since
there may be pending frames for transmission, we call immediately
``session_send()`` to send them. ``session_send()`` is defined as
follows::
static int session_send(http2_session_data *session_data) {
int rv;
@@ -291,10 +299,10 @@ frames. The ``session_send()`` function is defined as follows::
return 0;
}
The `nghttp2_session_send()` function serializes the frame into wire
format and call ``send_callback()`` function of type
:type:`nghttp2_send_callback`. The ``send_callback()`` is defined as
follows::
The `nghttp2_session_send()` function serializes pending frames into
wire format and calls the ``send_callback()`` function to send them.
``send_callback()`` has type :type:`nghttp2_send_callback` and is
defined as::
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
size_t length, int flags _U_, void *user_data) {
@@ -307,18 +315,18 @@ follows::
Since we use bufferevent to abstract network I/O, we just write the
data to the bufferevent object. Note that `nghttp2_session_send()`
continues to write all frames queued so far. If we were writing the
data to the non-blocking socket directly using ``write()`` system call
in the ``send_callback()``, we will surely get ``EAGAIN`` or
``EWOULDBLOCK`` since the socket has limited send buffer. If that
happens, we can return :macro:`NGHTTP2_ERR_WOULDBLOCK` to signal the
nghttp2 library to stop sending further data. But writing to the
bufferevent, we have to regulate the amount data to be buffered by
ourselves to avoid possible huge memory consumption. In this example
client, we do not limit anything. To see how to regulate the amount of
buffered data, see the ``send_callback()`` in the server tutorial.
data to the non-blocking socket directly using the ``write()`` system
call, we'd soon receive an ``EAGAIN`` or ``EWOULDBLOCK`` error, since
sockets have a limited send buffer. If that happens, it's possible to
return :macro:`NGHTTP2_ERR_WOULDBLOCK` to signal the nghttp2 library
to stop sending further data. When writing to a bufferevent, you
should regulate the amount of data written, to avoid possible huge
memory consumption. In this example client however we don't implement
a limit. To see how to regulate the amount of buffered data, see the
``send_callback()`` in the server tutorial.
The third bufferevent callback is ``writecb()``, which is invoked when
all data written in the bufferevent output buffer have been sent::
all data written in the bufferevent output buffer has been sent::
static void writecb(struct bufferevent *bev _U_, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
@@ -330,25 +338,25 @@ all data written in the bufferevent output buffer have been sent::
}
As described earlier, we just write off all data in `send_callback()`,
we have no data to write in this function. All we have to do is check
we have to drop connection or not. The nghttp2 session object keeps
track of reception and transmission of GOAWAY frame and other error
conditions as well. Using these information, nghttp2 session object
will tell whether the connection should be dropped or not. More
specifically, both `nghttp2_session_want_read()` and
`nghttp2_session_want_write()` return 0, we have no business in the
connection. But since we are using bufferevent and its deferred
callback option, the bufferevent output buffer may contain the pending
data when the ``writecb()`` is called. To handle this situation, we
also check whether the output buffer is empty or not. If these
conditions are met, we drop connection.
so there is no data to write in this function. All we have to do is
check if the connection should be dropped or not. The nghttp2 session
object keeps track of reception and transmission of GOAWAY frames and
other error conditions. Using this information, the nghttp2 session
object can state whether the connection should be dropped or not.
More specifically, when both `nghttp2_session_want_read()` and
`nghttp2_session_want_write()` return 0, the connection is no-longer
required and can be closed. Since we're using bufferevent and its
deferred callback option, the bufferevent output buffer may still
contain pending data when the ``writecb()`` is called. To handle this
situation, we also check whether the output buffer is empty or not. If
all of these conditions are met, then we drop the connection.
We have already described about nghttp2 callback ``send_callback()``.
Let's describe remaining nghttp2 callbacks we setup in
Now let's look at the remaining nghttp2 callbacks setup in the
``initialize_nghttp2_setup()`` function.
Each request header name/value pair is emitted via
``on_header_callback`` function::
A server responds to the request by first sending a HEADERS frame.
The HEADERS frame consists of response header name/value pairs, and
the ``on_header_callback()`` is called for each name/value pair::
static int on_header_callback(nghttp2_session *session _U_,
const nghttp2_frame *frame, const uint8_t *name,
@@ -368,10 +376,11 @@ Each request header name/value pair is emitted via
return 0;
}
In this tutorial, we just print the name/value pair.
In this tutorial, we just print the name/value pairs on stdout.
After all name/value pairs are emitted for a frame,
``on_frame_recv_callback`` function is called::
After the HEADERS frame has been fully received (and thus all response
header name/value pairs have been received), the
``on_frame_recv_callback()`` function is called::
static int on_frame_recv_callback(nghttp2_session *session _U_,
const nghttp2_frame *frame, void *user_data) {
@@ -387,13 +396,16 @@ After all name/value pairs are emitted for a frame,
return 0;
}
In this tutorial, we are just interested in the HTTP response
HEADERS. We check te frame type and its category (it should be
:macro:`NGHTTP2_HCAT_RESPONSE` for HTTP response HEADERS). Also check
its stream ID.
``on_frame_recv_callback()`` is called for other frame types too.
The ``on_data_chunk_recv_callback()`` function is invoked when a chunk
of data is received from the remote peer::
In this tutorial, we are just interested in the HTTP response HEADERS
frame. We check the frame type and its category (it should be
:macro:`NGHTTP2_HCAT_RESPONSE` for HTTP response HEADERS). We also
check its stream ID.
Next, zero or more DATA frames can be received. The
``on_data_chunk_recv_callback()`` function is invoked when a chunk of
data is received from the remote peer::
static int on_data_chunk_recv_callback(nghttp2_session *session _U_,
uint8_t flags _U_, int32_t stream_id,
@@ -406,10 +418,10 @@ of data is received from the remote peer::
return 0;
}
In our case, a chunk of data is response body. After checking stream
ID, we just write the recieved data to the stdout. Note that the
output in the terminal may be corrupted if the response body contains
some binary data.
In our case, a chunk of data is HTTP response body. After checking the
stream ID, we just write the received data to stdout. Note the output
in the terminal may be corrupted if the response body contains some
binary data.
The ``on_stream_close_callback()`` function is invoked when the stream
is about to close::
@@ -432,9 +444,9 @@ is about to close::
}
If the stream ID matches the one we initiated, it means that its
stream is going to be closed. Since we have finished to get the
resource we want (or the stream was reset by RST_STREAM from the
stream is going to be closed. Since we have finished receiving
resource we wanted (or the stream was reset by RST_STREAM from the
remote peer), we call `nghttp2_session_terminate_session()` to
commencing the closure of the HTTP/2 session gracefully. If you have
commence closure of the HTTP/2 session gracefully. If you have
some data associated for the stream to be closed, you may delete it
here.

View File

@@ -1,118 +1,129 @@
Tutorial: HPACK API
===================
In this tutorial, we describe basic use of HPACK API in nghttp2
library. We briefly describe APIs for deflating and inflating header
fields. The example of using these APIs are presented as complete
source code `deflate.c`_.
In this tutorial, we describe basic use of nghttp2's HPACK API. We
briefly describe the APIs for deflating and inflating header fields.
The full example of using these APIs, `deflate.c`_, is attached at the
end of this page. It also resides in the examples directory in the
archive or repository.
Deflating (encoding) headers
----------------------------
First we need to initialize :type:`nghttp2_hd_deflater` object using
`nghttp2_hd_deflate_new()` function::
First we need to initialize a :type:`nghttp2_hd_deflater` object using
the `nghttp2_hd_deflate_new()` function::
int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
size_t deflate_hd_table_bufsize_max);
This function allocates :type:`nghttp2_hd_deflater` object and
initializes it and assigns its pointer to ``*deflater_ptr`` passed by
parameter. The *deflate_hd_table_bufsize_max* is the upper bound of
header table size the deflater will use. This will limit the memory
usage in deflater object for dynamic header table. If you doubt, just
This function allocates a :type:`nghttp2_hd_deflater` object,
initializes it, and assigns its pointer to ``*deflater_ptr``. The
*deflate_hd_table_bufsize_max* is the upper bound of header table size
the deflater will use. This will limit the memory usage by the
deflater object for the dynamic header table. If in doubt, just
specify 4096 here, which is the default upper bound of dynamic header
table buffer size.
To encode header fields, `nghttp2_hd_deflate_hd()` function::
To encode header fields, use the `nghttp2_hd_deflate_hd()` function::
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
uint8_t *buf, size_t buflen,
const nghttp2_nv *nva, size_t nvlen);
The *deflater* is the deflater object initialized by
`nghttp2_hd_deflate_new()` function described above. The *buf* is a
pointer to buffer to store encoded byte string. The *buflen* is
capacity of *buf*. The *nva* is a pointer to :type:`nghttp2_nv`,
which is an array of header fields to deflate. The *nvlen* is the
number of header fields which *nva* contains.
`nghttp2_hd_deflate_new()` described above. The encoded byte string is
written to the buffer *buf*, which has length *buflen*. The *nva* is
a pointer to an array of headers fields, each of type
:type:`nghttp2_nv`. *nvlen* is the number of header fields which
*nva* contains.
It is important to initialize and assign all members of
:type:`nghttp2_nv`. If a header field should not be inserted in
dynamic header table for a security reason, set
:macro:`NGHTTP2_NV_FLAG_NO_INDEX` flag in :member:`nghttp2_nv.flags`.
:type:`nghttp2_nv`. For security sensitive header fields (such as
cookies), set the :macro:`NGHTTP2_NV_FLAG_NO_INDEX` flag in
:member:`nghttp2_nv.flags`. Setting this flag prevents recovery of
sensitive header fields by compression based attacks: This is achieved
by not inserting the header field into the dynamic header table.
`nghttp2_hd_deflate_hd()` processes all headers given in *nva*. The
*nva* must include all request or response header fields to be sent in
one HEADERS (or optionally following (multiple) CONTINUATION
frame(s)). The *buf* must have enough space to store the encoded
result. Otherwise, the function will fail. To estimate the upper
bound of encoded result, use `nghttp2_hd_deflate_bound()` function::
result, otherwise the function will fail. To estimate the upper bound
of the encoded result length, use `nghttp2_hd_deflate_bound()`::
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
const nghttp2_nv *nva, size_t nvlen);
Pass this function with the same paramters *deflater*, *nva* and
*nvlen* which will be passed to `nghttp2_hd_deflate_hd()`.
Pass this function the same parameters (*deflater*, *nva*, and
*nvlen*) which will be passed to `nghttp2_hd_deflate_hd()`.
The subsequent call of `nghttp2_hd_deflate_hd()` will use current
encoder state and perform differential encoding which is the
fundamental compression gain for HPACK.
Subsequent calls to `nghttp2_hd_deflate_hd()` will use the current
encoder state and perform differential encoding, which yields HPAC's
fundamental compression gain.
Once `nghttp2_hd_deflate_hd()` fails, it cannot be undone and its
further call with the same deflater object shall fail. So it is very
important to use `nghttp2_hd_deflate_bound()` to know the required
size of buffer.
If `nghttp2_hd_deflate_hd()` fails, the failure is fatal and any
further calls with the same deflater object will fail. Thus it's very
important to use `nghttp2_hd_deflate_bound()` to determine the
required size of the output buffer.
To delete :type:`nghttp2_hd_deflater` object, use `nghttp2_hd_deflate_del()`
function.
To delete a :type:`nghttp2_hd_deflater` object, use the
`nghttp2_hd_deflate_del()` function.
Inflating (decoding) headers
----------------------------
We use :type:`nghttp2_hd_inflater` object to inflate compressed header
data. To initialize the object, use `nghttp2_hd_inflate_new()`::
A :type:`nghttp2_hd_inflater` object is used to inflate compressed
header data. To initialize the object, use
`nghttp2_hd_inflate_new()`::
int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr);
To inflate header data, use `nghttp2_hd_inflate_hd()` function::
To inflate header data, use `nghttp2_hd_inflate_hd()`::
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
nghttp2_nv *nv_out, int *inflate_flags,
uint8_t *in, size_t inlen, int in_final);
`nghttp2_hd_inflate_hd()` reads a stream of bytes and outputs a single
header field at a time. Multiple calls are normally required to read a
full stream of bytes and output all of the header fields.
The *inflater* is the inflater object initialized above. The *nv_out*
is a pointer to :type:`nghttp2_nv` to store the result. The *in* is a
pointer to input data and *inlen* is its length. The caller is not
required to specify whole deflated header data to *in* at once. It
can call this function multiple times for portion of the data in
streaming way. If *in_final* is nonzero, it tells the function that
the passed data is the final sequence of deflated header data. The
*inflate_flags* is output parameter and successful call of this
function stores a set of flags in it. It will be described later.
is a pointer to a :type:`nghttp2_nv` into which one header field may
be stored. The *in* is a pointer to input data, and *inlen* is its
length. The caller is not required to specify the whole deflated
header data via *in* at once: Instead it can call this function
multiple times as additional data bytes become available. If
*in_final* is nonzero, it tells the function that the passed data is
the final sequence of deflated header data.
The *inflate_flags* is an output parameter; on success the function
sets it to a bitset of flags. It will be described later.
This function returns when each header field is inflated. When this
happens, the function sets :macro:`NGHTTP2_HD_INFLATE_EMIT` flag to
*inflate_flag* parameter and header field is stored in *nv_out*. The
return value indicates the number of data read from *in* to processed
so far. It may be less than *inlen*. The caller should call the
function repeatedly until all data are processed by adjusting *in* and
*inlen* with the processed bytes.
happens, the function sets the :macro:`NGHTTP2_HD_INFLATE_EMIT` flag
in *inflate_flags*, and a header field is stored in *nv_out*. The
return value indicates the number of bytes read from *in* processed so
far, which may be less than *inlen*. The caller should call the
function repeatedly until all bytes are processed. Processed bytes
should be removed from *in*, and *inlen* should be adjusted
appropriately.
If *in_final* is nonzero and all given data was processed, the
function sets :macro:`NGHTTP2_HD_INFLATE_FINAL` flag to
*inflate_flag*. If the caller sees this flag set, call
function sets the :macro:`NGHTTP2_HD_INFLATE_FINAL` flag in
*inflate_flags*. When you see this flag set, call the
`nghttp2_hd_inflate_end_headers()` function.
If *in_final* is zero and :macro:`NGHTTP2_HD_INFLATE_EMIT` flag is not
set, it indicates that all given data was processed. The caller is
required to pass subsequent data.
If *in_final* is zero and the :macro:`NGHTTP2_HD_INFLATE_EMIT` flag is
not set, it indicates that all given data was processed. The caller
is required to pass additional data.
It is important to note that the function may produce one or more
header fields even if *inlen* is 0 when *in_final* is nonzero, due to
differential encoding.
The example use of `nghttp2_hd_inflate_hd()` is shown in
Example usage of `nghttp2_hd_inflate_hd()` is shown in the
`inflate_header_block()` function in `deflate.c`_.
To delete :type:`nghttp2_hd_inflater` object, use `nghttp2_hd_inflate_del()`
function.
Finally, to delete a :type:`nghttp2_hd_inflater` object, use
`nghttp2_hd_inflate_del()`.

View File

@@ -1,30 +1,31 @@
Tutorial: HTTP/2 server
=========================
In this tutorial, we are going to write single-threaded, event-based
HTTP/2 web server, which supports HTTPS only. It can handle
concurrent multiple requests, but only the GET method is supported. The
complete source code, `libevent-server.c`_, is attached at the end of
this page. It also resides in examples directory in the archive or
repository.
In this tutorial, we are going to write a single-threaded, event-based
HTTP/2 web server, which supports HTTPS only. It can handle concurrent
multiple requests, but only the GET method is supported. The complete
source code, `libevent-server.c`_, is attached at the end of this
page. The source also resides in the examples directory in the
archive or repository.
This simple server takes 3 arguments, a port number to listen to, a path to
your SSL/TLS private key file and a path to your certificate file. Its
synopsis is like this::
This simple server takes 3 arguments: The port number to listen on,
the path to your SSL/TLS private key file, and the path to your
certificate file. The synopsis is::
$ libevent-server PORT /path/to/server.key /path/to/server.crt
We use libevent in this tutorial to handle networking I/O. Please
note that nghttp2 itself does not depend on libevent.
First we create a setup routine for libevent and OpenSSL in the functions
``main()`` and ``run()``. One thing in there you should look at, is the setup
of the NPN callback. The NPN callback is used for the server to advertise
which application protocols the server supports to a client. In this example
program, when creating ``SSL_CTX`` object, we store the application protocol
name in the wire format of NPN in a statically allocated buffer. This is safe
because we only create one ``SSL_CTX`` object in the program's entire life
time::
The server starts with some libevent and OpenSSL setup in the
``main()`` and ``run()`` functions. This setup isn't specific to
nghttp2, but one thing you should look at is setup of the NPN
callback. The NPN callback is used by the server to advertise which
application protocols the server supports to a client. In this
example program, when creating the ``SSL_CTX`` object, we store the
application protocol name in the wire format of NPN in a statically
allocated buffer. This is safe because we only create one ``SSL_CTX``
object in the program's entire lifetime::
static unsigned char next_proto_list[256];
static size_t next_proto_list_len;
@@ -53,17 +54,20 @@ time::
return ssl_ctx;
}
The wire format of NPN is a sequence of length prefixed string. Exactly one
byte is used to specify the length of each protocol identifier. In this
tutorial, we advertise the specific HTTP/2 protocol version the current
nghttp2 library supports. The nghttp2 library exports its identifier in
:macro:`NGHTTP2_PROTO_VERSION_ID`. The ``next_proto_cb()`` function is the
server-side NPN callback. In the OpenSSL implementation, we just assign the
pointer to the NPN buffers we filled in earlier. The NPN callback function is
set to the ``SSL_CTX`` object using
``SSL_CTX_set_next_protos_advertised_cb()``.
The wire format of NPN is a sequence of length prefixed strings, with
exactly one byte used to specify the length of each protocol
identifier. In this tutorial, we advertise the specific HTTP/2
protocol version the current nghttp2 library supports, which is
exported in the identifier :macro:`NGHTTP2_PROTO_VERSION_ID`. The
``next_proto_cb()`` function is the server-side NPN callback. In the
OpenSSL implementation, we just assign the pointer to the NPN buffers
we filled in earlier. The NPN callback function is set to the
``SSL_CTX`` object using ``SSL_CTX_set_next_protos_advertised_cb()``.
We use the ``app_content`` structure to store application-wide data::
Next, let's take a look at the main structures used by the example
application:
We use the ``app_context`` structure to store application-wide data::
struct app_context {
SSL_CTX *ssl_ctx;
@@ -90,18 +94,21 @@ We use the ``http2_stream_data`` structure to store stream-level data::
int fd;
} http2_stream_data;
A single HTTP/2 session can have multiple streams. We manage these
multiple streams with a doubly linked list. The first element of this
list is pointed to by the ``root->next`` in ``http2_session_data``.
Initially, ``root->next`` is ``NULL``. We use libevent's bufferevent
structure to perform network I/O. Note that the bufferevent object is
kept in ``http2_session_data`` and not in ``http2_stream_data``. This
is because ``http2_stream_data`` is just a logical stream multiplexed
over the single connection managed by bufferevent in
A single HTTP/2 session can have multiple streams. To manage them, we
use a doubly linked list: The first element of this list is pointed
to by the ``root->next`` in ``http2_session_data``. Initially,
``root->next`` is ``NULL``.
libevent's bufferevent structure is used to perform network I/O, with
the pointer to the bufferevent stored in the ``http2_session_data``
structure. Note that the bufferevent object is kept in
``http2_session_data`` and not in ``http2_stream_data``. This is
because ``http2_stream_data`` is just a logical stream multiplexed
over the single connection managed by the bufferevent in
``http2_session_data``.
We first create a listener object to accept incoming connections. We use
libevent's ``struct evconnlistener`` for this purpose::
We first create a listener object to accept incoming connections.
libevent's ``struct evconnlistener`` is used for this purpose::
static void start_listen(struct event_base *evbase, const char *service,
app_context *app_ctx) {
@@ -135,7 +142,7 @@ libevent's ``struct evconnlistener`` for this purpose::
errx(1, "Could not start listener");
}
We specify the ``acceptcb`` callback which is called when a new connection is
We specify the ``acceptcb`` callback, which is called when a new connection is
accepted::
static void acceptcb(struct evconnlistener *listener _U_, int fd,
@@ -148,13 +155,13 @@ accepted::
bufferevent_setcb(session_data->bev, readcb, writecb, eventcb, session_data);
}
Here we create the ``http2_session_data`` object. The bufferevent for
this connection is also initialized at this time. We specify three
callbacks for the bufferevent: ``readcb``, ``writecb`` and
Here we create the ``http2_session_data`` object. The connection's
bufferevent is initialized at the same time. We specify three
callbacks for the bufferevent: ``readcb``, ``writecb``, and
``eventcb``.
The ``eventcb()`` callback is invoked by the libevent event loop when an event
(e.g., connection has been established, timeout, etc) happens on the
(e.g. connection has been established, timeout, etc.) occurs on the
underlying network socket::
static void eventcb(struct bufferevent *bev _U_, short events, void *ptr) {
@@ -181,28 +188,23 @@ underlying network socket::
delete_http2_session_data(session_data);
}
For the ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR`` and
For the ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR``, and
``BEV_EVENT_TIMEOUT`` events, we just simply tear down the connection.
The ``delete_http2_session_data()`` function destroys the
``http2_session_data`` object and thus also its bufferevent member.
As a result, the underlying connection is closed. The
``BEV_EVENT_CONNECTED`` event is invoked when SSL/TLS handshake is
finished successfully. Now we are ready to start the HTTP/2
communication.
``http2_session_data`` object and its associated bufferevent member.
As a result, the underlying connection is closed.
We initialize a nghttp2 session object which is done in
``initialize_nghttp2_session()``::
The
``BEV_EVENT_CONNECTED`` event is invoked when SSL/TLS handshake has
completed successfully. After this we are ready to begin communicating
via HTTP/2.
The ``initialize_nghttp2_session()`` function initializes the nghttp2
session object and several callbacks::
static void initialize_nghttp2_session(http2_session_data *session_data) {
nghttp2_option *option;
nghttp2_session_callbacks *callbacks;
nghttp2_option_new(&option);
/* Tells nghttp2_session object that it handles client connection
preface */
nghttp2_option_set_recv_client_preface(option, 1);
nghttp2_session_callbacks_new(&callbacks);
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
@@ -219,23 +221,18 @@ We initialize a nghttp2 session object which is done in
nghttp2_session_callbacks_set_on_begin_headers_callback(
callbacks, on_begin_headers_callback);
nghttp2_session_server_new2(&session_data->session, callbacks, session_data,
option);
nghttp2_session_server_new(&session_data->session, callbacks, session_data);
nghttp2_session_callbacks_del(callbacks);
nghttp2_option_del(option);
}
Since we are creating a server and uses options, the nghttp2 session
object is created using `nghttp2_session_server_new2()` function. We
registers five callbacks for nghttp2 session object. We'll talk about
these callbacks later. Our server only speaks HTTP/2. In this case,
we use `nghttp2_option_set_recv_client_preface()` to make
:type:`nghttp2_session` object handle client connection preface, which
saves some lines of application code.
Since we are creating a server, we use `nghttp2_session_server_new()`
to initialize the nghttp2 session object. We also setup 5 callbacks
for the nghttp2 session, these are explained later.
After initialization of the nghttp2 session object, we are going to send
a server connection header in ``send_server_connection_header()``::
The server now begins by sending the server connection preface, which
always consists of a SETTINGS frame.
``send_server_connection_header()`` configures and submits it::
static int send_server_connection_header(http2_session_data *session_data) {
nghttp2_settings_entry iv[1] = {
@@ -251,11 +248,10 @@ a server connection header in ``send_server_connection_header()``::
return 0;
}
The server connection header is a SETTINGS frame. We specify
SETTINGS_MAX_CONCURRENT_STREAMS to 100 in the SETTINGS frame. To queue
the SETTINGS frame for the transmission, we use
`nghttp2_submit_settings()`. Note that `nghttp2_submit_settings()`
function only queues the frame and it does not actually send it. All
In the example SETTINGS frame we've set
SETTINGS_MAX_CONCURRENT_STREAMS to 100. `nghttp2_submit_settings()`
is used to queue the frame for transmission, but note it only queues
the frame for transmission, and doesn't actually send it. All
functions in the ``nghttp2_submit_*()`` family have this property. To
actually send the frame, `nghttp2_session_send()` should be used, as
described later.
@@ -286,12 +282,14 @@ this pending data. To process the received data, we call the
return 0;
}
In this function, we feed all unprocessed but already received data to the
nghttp2 session object using the `nghttp2_session_mem_recv()` function. The
`nghttp2_session_mem_recv()` function processes the data and may invoke the
nghttp2 callbacks and also queue outgoing frames. Since there may be pending
outgoing frames, we call ``session_send()`` function to send off those
frames. The ``session_send()`` function is defined as follows::
In this function, we feed all unprocessed but already received data to
the nghttp2 session object using the `nghttp2_session_mem_recv()`
function. The `nghttp2_session_mem_recv()` function processes the data
and may both invoke the previously setup callbacks and also queue
outgoing frames. To send any pending outgoing frames, we immediately
call ``session_send()``.
The ``session_send()`` function is defined as follows::
static int session_send(http2_session_data *session_data) {
int rv;
@@ -304,7 +302,7 @@ frames. The ``session_send()`` function is defined as follows::
}
The `nghttp2_session_send()` function serializes the frame into wire
format and calls ``send_callback()`` of type
format and calls the ``send_callback()``, which is of type
:type:`nghttp2_send_callback`. The ``send_callback()`` is defined as
follows::
@@ -324,17 +322,16 @@ follows::
Since we use bufferevent to abstract network I/O, we just write the
data to the bufferevent object. Note that `nghttp2_session_send()`
continues to write all frames queued so far. If we were writing the
data to a non-blocking socket directly using ``write()`` system call
in the ``send_callback()``, we would surely get ``EAGAIN`` or
``EWOULDBLOCK`` back since the socket has limited send buffer. If that
happens, we can return :macro:`NGHTTP2_ERR_WOULDBLOCK` to signal the
nghttp2 library to stop sending further data. But when writing to the
bufferevent, we have to regulate the amount data to get buffered
ourselves to avoid using huge amounts of memory. To achieve this, we
check the size of the output buffer and if it reaches more than or
equal to ``OUTPUT_WOULDBLOCK_THRESHOLD`` bytes, we stop writing data
and return :macro:`NGHTTP2_ERR_WOULDBLOCK` to tell the library to stop
calling send_callback.
data to a non-blocking socket directly using the ``write()`` system
call in the ``send_callback()``, we'd soon receive an ``EAGAIN`` or
``EWOULDBLOCK`` error since sockets have a limited send buffer. If
that happens, it's possible to return :macro:`NGHTTP2_ERR_WOULDBLOCK`
to signal the nghttp2 library to stop sending further data. But here,
when writing to the bufferevent, we have to regulate the amount data
to buffered ourselves to avoid using huge amounts of memory. To
achieve this, we check the size of the output buffer and if it reaches
more than or equal to ``OUTPUT_WOULDBLOCK_THRESHOLD`` bytes, we stop
writing data and return :macro:`NGHTTP2_ERR_WOULDBLOCK`.
The next bufferevent callback is ``readcb()``, which is invoked when
data is available to read in the bufferevent input buffer::
@@ -369,16 +366,18 @@ data in the bufferevent output buffer has been sent::
}
}
First we check whether we should drop the connection or not. The nghttp2
session object keeps track of reception and transmission of GOAWAY frames and
other error conditions as well. Using this information, the nghttp2 session
object will tell whether the connection should be dropped or not. More
specifically, if both `nghttp2_session_want_read()` and
`nghttp2_session_want_write()` return 0, we have no business left in the
connection. But since we are using bufferevent and its deferred callback
option, the bufferevent output buffer may contain pending data when the
``writecb()`` is called. To handle this, we check whether the output buffer is
empty or not. If all these conditions are met, we drop connection.
First we check whether we should drop the connection or not. The
nghttp2 session object keeps track of reception and transmission of
GOAWAY frames and other error conditions as well. Using this
information, the nghttp2 session object can state whether the
connection should be dropped or not. More specifically, if both
`nghttp2_session_want_read()` and `nghttp2_session_want_write()`
return 0, the connection is no-longer required and can be closed.
Since we are using bufferevent and its deferred callback option, the
bufferevent output buffer may still contain pending data when the
``writecb()`` is called. To handle this, we check whether the output
buffer is empty or not. If all of these conditions are met, we drop
connection.
Otherwise, we call ``session_send()`` to process the pending output
data. Remember that in ``send_callback()``, we must not write all data to
@@ -386,7 +385,7 @@ bufferevent to avoid excessive buffering. We continue processing pending data
when the output buffer becomes empty.
We have already described the nghttp2 callback ``send_callback()``. Let's
learn about the remaining nghttp2 callbacks we setup in
learn about the remaining nghttp2 callbacks setup in
``initialize_nghttp2_setup()`` function.
The ``on_begin_headers_callback()`` function is invoked when the reception of
@@ -408,13 +407,15 @@ a header block in HEADERS or PUSH_PROMISE frame is started::
return 0;
}
We are only interested in the HEADERS frame in this function. Since the
HEADERS frame has several roles in the HTTP/2 protocol, we check that it is a
request HEADERS, which opens new stream. If the frame is a request HEADERS, we
create a ``http2_stream_data`` object to store the stream related data. We
associate the created ``http2_stream_data`` object with the stream in the
nghttp2 session object using `nghttp2_set_stream_user_data()` to get the
object without searching through the doubly linked list.
We are only interested in the HEADERS frame in this function. Since
the HEADERS frame has several roles in the HTTP/2 protocol, we check
that it is a request HEADERS, which opens new stream. If the frame is
a request HEADERS, we create a ``http2_stream_data`` object to store
the stream related data. We associate the created
``http2_stream_data`` object with the stream in the nghttp2 session
object using `nghttp2_set_stream_user_data()`. The
``http2_stream_data`` object can later be easily retrieved from the
stream, without searching through the doubly linked list.
In this example server, we want to serve files relative to the current working
directory in which the program was invoked. Each header name/value pair is
@@ -449,10 +450,10 @@ emitted via ``on_header_callback`` function, which is called after
return 0;
}
We search for the ``:path`` header field among the request headers and store
the requested path in the ``http2_stream_data`` object. In this example
program, we ignore ``:method`` header field and always treat the request as a
GET request.
We search for the ``:path`` header field among the request headers and
store the requested path in the ``http2_stream_data`` object. In this
example program, we ignore the ``:method`` header field and always
treat the request as a GET request.
The ``on_frame_recv_callback()`` function is invoked when a frame is
fully received::
@@ -482,15 +483,15 @@ fully received::
return 0;
}
First we retrieve the ``http2_stream_data`` object associated with the stream
in ``on_begin_headers_callback()``. It is done using
`nghttp2_session_get_stream_user_data()`. If the requested path cannot be
served for some reason (e.g., file is not found), we send a 404 response,
which is done in ``error_reply()``. Otherwise, we open the requested file and
send its content. We send the header field ``:status`` as a single response
header.
First we retrieve the ``http2_stream_data`` object associated with the
stream in ``on_begin_headers_callback()`` using
`nghttp2_session_get_stream_user_data()`. If the requested path
cannot be served for some reason (e.g. file is not found), we send a
404 response using ``error_reply()``. Otherwise, we open
the requested file and send its content. We send the header field
``:status`` as a single response header.
Sending the content of the file is done in ``send_response()`` function::
Sending the file content is performed by the ``send_response()`` function::
static int send_response(nghttp2_session *session, int32_t stream_id,
nghttp2_nv *nva, size_t nvlen, int fd) {
@@ -507,12 +508,13 @@ Sending the content of the file is done in ``send_response()`` function::
return 0;
}
The nghttp2 library uses the :type:`nghttp2_data_provider` structure to
send entity body to the remote peer. The ``source`` member of this
structure is a union and it can be either void pointer or int which is
intended to be used as file descriptor. In this example server, we use
the file descriptor. We also set the ``file_read_callback()`` callback
function to read the contents of the file::
nghttp2 uses the :type:`nghttp2_data_provider` structure to send the
entity body to the remote peer. The ``source`` member of this
structure is a union, which can be either a void pointer or an int
(which is intended to be used as file descriptor). In this example
server, we use it as a file descriptor. We also set the
``file_read_callback()`` callback function to read the contents of the
file::
static ssize_t file_read_callback(nghttp2_session *session _U_,
int32_t stream_id _U_, uint8_t *buf,
@@ -532,11 +534,11 @@ function to read the contents of the file::
return r;
}
If an error happens while reading the file, we return
If an error occurs while reading the file, we return
:macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. This tells the
library to send RST_STREAM to the stream. When all data has been read, set
the :macro:`NGHTTP2_DATA_FLAG_EOF` flag to ``*data_flags`` to tell the
nghttp2 library that we have finished reading the file.
library to send RST_STREAM to the stream. When all data has been
read, the :macro:`NGHTTP2_DATA_FLAG_EOF` flag is set to signal nghttp2
that we have finished reading the file.
The `nghttp2_submit_response()` function is used to send the response to the
remote peer.
@@ -558,5 +560,5 @@ is about to close::
return 0;
}
We destroy the ``http2_stream_data`` object in this function since the stream
is about to close and we no longer use that object.
Lastly, we destroy the ``http2_stream_data`` object in this function,
since the stream is about to close and we no longer need the object.

View File

@@ -35,8 +35,12 @@
//
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif // HAVE_UNISTD_H
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif // HAVE_FCNTL_H
#include <iostream>
#include <string>

View File

@@ -28,16 +28,26 @@
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* !HAVE_CONFIG_H */
#endif /* HAVE_CONFIG_H */
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif /* HAVE_FCNTL_H */
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif /* HAVE_SYS_SOCKET_H */
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif /* HAVE_NETDB_H */
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
#include <netinet/tcp.h>
#include <poll.h>
#include <signal.h>
@@ -528,14 +538,6 @@ static void fetch_uri(const struct URI *uri) {
connection.ssl = ssl;
connection.want_io = IO_NONE;
/* Send connection header in blocking I/O mode */
rv = SSL_write(ssl, NGHTTP2_CLIENT_CONNECTION_PREFACE,
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
if (rv <= 0) {
dief("SSL_write failed: could not send connection preface",
ERR_error_string(ERR_get_error(), NULL));
}
/* Here make file descriptor non-block */
make_non_block(fd);
set_tcp_nodelay(fd);
@@ -687,10 +689,10 @@ int main(int argc, char **argv) {
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, 0);
OPENSSL_config(NULL);
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
rv = parse_uri(&uri, argv[1]);
if (rv != 0) {

View File

@@ -22,16 +22,35 @@
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef __sgi
#include <string.h>
#define errx(exitcode, format, args...) \
{ \
warnx(format, ##args); \
exit(exitcode); \
}
#define warnx(format, args...) fprintf(stderr, format "\n", ##args)
char *strndup(const char *s, size_t size);
#endif
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* !HAVE_CONFIG_H */
#endif /* HAVE_CONFIG_H */
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif /* HAVE_SYS_SOCKET_H */
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
#include <netinet/tcp.h>
#ifndef __sgi
#include <err.h>
#endif
#include <signal.h>
#include <openssl/ssl.h>
@@ -50,11 +69,11 @@
#define ARRLEN(x) (sizeof(x) / sizeof(x[0]))
typedef struct {
/* The NULL-terminated URI string to retreive. */
/* The NULL-terminated URI string to retrieve. */
const char *uri;
/* Parsed result of the |uri| */
struct http_parser_url *u;
/* The authroity portion of the |uri|, not NULL-terminated */
/* The authority portion of the |uri|, not NULL-terminated */
char *authority;
/* The path portion of the |uri|, including query, not
NULL-terminated */
@@ -94,7 +113,8 @@ static http2_stream_data *create_http2_stream_data(const char *uri,
":%u", u->port);
}
stream_data->pathlen = 0;
/* If we don't have path in URI, we use "/" as path. */
stream_data->pathlen = 1;
if (u->field_set & (1 << UF_PATH)) {
stream_data->pathlen = u->field_data[UF_PATH].len;
}
@@ -102,19 +122,22 @@ static http2_stream_data *create_http2_stream_data(const char *uri,
/* +1 for '?' character */
stream_data->pathlen += u->field_data[UF_QUERY].len + 1;
}
if (stream_data->pathlen > 0) {
stream_data->path = malloc(stream_data->pathlen);
if (u->field_set & (1 << UF_PATH)) {
memcpy(stream_data->path, &uri[u->field_data[UF_PATH].off],
u->field_data[UF_PATH].len);
}
if (u->field_set & (1 << UF_QUERY)) {
memcpy(stream_data->path + u->field_data[UF_PATH].len + 1,
&uri[u->field_data[UF_QUERY].off], u->field_data[UF_QUERY].len);
}
stream_data->path = malloc(stream_data->pathlen);
if (u->field_set & (1 << UF_PATH)) {
memcpy(stream_data->path, &uri[u->field_data[UF_PATH].off],
u->field_data[UF_PATH].len);
} else {
stream_data->path = NULL;
stream_data->path[0] = '/';
}
if (u->field_set & (1 << UF_QUERY)) {
stream_data->path[stream_data->pathlen - u->field_data[UF_QUERY].len - 1] =
'?';
memcpy(stream_data->path + stream_data->pathlen -
u->field_data[UF_QUERY].len,
&uri[u->field_data[UF_QUERY].off], u->field_data[UF_QUERY].len);
}
return stream_data;
}
@@ -258,8 +281,7 @@ static int on_data_chunk_recv_callback(nghttp2_session *session _U_,
stream), if it is closed, we send GOAWAY and tear down the
session */
static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
uint32_t error_code,
void *user_data) {
uint32_t error_code, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
int rv;
@@ -345,8 +367,7 @@ static void send_client_connection_header(http2_session_data *session_data) {
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
int rv;
bufferevent_write(session_data->bev, NGHTTP2_CLIENT_CONNECTION_PREFACE,
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
/* client 24 bytes magic string will be sent by nghttp2 library */
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv,
ARRLEN(iv));
if (rv != 0) {
@@ -547,10 +568,10 @@ int main(int argc, char **argv) {
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL);
OPENSSL_config(NULL);
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
run(argv[1]);
return 0;

View File

@@ -22,21 +22,43 @@
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef __sgi
#define errx(exitcode, format, args...) \
{ \
warnx(format, ##args); \
exit(exitcode); \
}
#define warn(format, args...) warnx(format ": %s", ##args, strerror(errno))
#define warnx(format, args...) fprintf(stderr, format "\n", ##args)
#endif
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* !HAVE_CONFIG_H */
#endif /* HAVE_CONFIG_H */
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif /* HAVE_SYS_SOCKET_H */
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif /* HAVE_NETDB_H */
#include <signal.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <sys/stat.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif /* HAVE_FCNTL_H */
#include <ctype.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
#include <netinet/tcp.h>
#ifndef __sgi
#include <err.h>
#endif
#include <openssl/ssl.h>
#include <openssl/err.h>
@@ -537,15 +559,8 @@ static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
}
static void initialize_nghttp2_session(http2_session_data *session_data) {
nghttp2_option *option;
nghttp2_session_callbacks *callbacks;
nghttp2_option_new(&option);
/* Tells nghttp2_session object that it handles client connection
preface */
nghttp2_option_set_recv_client_preface(option, 1);
nghttp2_session_callbacks_new(&callbacks);
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
@@ -562,11 +577,9 @@ static void initialize_nghttp2_session(http2_session_data *session_data) {
nghttp2_session_callbacks_set_on_begin_headers_callback(
callbacks, on_begin_headers_callback);
nghttp2_session_server_new2(&session_data->session, callbacks, session_data,
option);
nghttp2_session_server_new(&session_data->session, callbacks, session_data);
nghttp2_session_callbacks_del(callbacks);
nghttp2_option_del(option);
}
/* Send HTTP/2 client connection header, which includes 24 bytes
@@ -671,7 +684,7 @@ static void start_listen(struct event_base *evbase, const char *service,
rv = getaddrinfo(NULL, service, &hints, &res);
if (rv != 0) {
errx(1, NULL);
errx(1, "Could not resolve server address");
}
for (rp = res; rp; rp = rp->ai_next) {
struct evconnlistener *listener;
@@ -723,10 +736,10 @@ int main(int argc, char **argv) {
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL);
OPENSSL_config(NULL);
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
run(argv[1], argv[2], argv[3]);
return 0;

View File

@@ -30,18 +30,30 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* !HAVE_CONFIG_H */
#endif /* HAVE_CONFIG_H */
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif /* HAVE_SYS_SOCKET_H */
#include <sys/stat.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif /* HAVE_FCNTL_H */
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif /* HAVE_NETDB_H */
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
#include <netinet/tcp.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <stdlib.h>
#ifdef HAVE_TIME_H
#include <time.h>
#endif /* HAVE_TIME_H */
#include <string.h>
#include <stdio.h>
#include <errno.h>
@@ -153,7 +165,6 @@ const char *docroot;
size_t docrootlen;
nghttp2_session_callbacks *shared_callbacks;
nghttp2_option *shared_option;
static int handle_accept(io_loop *loop, uint32_t events, void *ptr);
static int handle_connection(io_loop *loop, uint32_t events, void *ptr);
@@ -190,7 +201,7 @@ typedef enum {
NGHTTP2_TOKEN__METHOD,
NGHTTP2_TOKEN__PATH,
NGHTTP2_TOKEN__SCHEME,
NGHTTP2_TOKEN_HOST,
NGHTTP2_TOKEN_HOST
} nghttp2_token;
/* Inspired by h2o header lookup. https://github.com/h2o/h2o */
@@ -388,8 +399,7 @@ static connection *connection_new(int fd) {
conn = malloc(sizeof(connection));
rv = nghttp2_session_server_new2(&conn->session, shared_callbacks, conn,
shared_option);
rv = nghttp2_session_server_new(&conn->session, shared_callbacks, conn);
if (rv != 0) {
goto cleanup;
@@ -658,19 +668,52 @@ static void stream_error(connection *conn, int32_t stream_id,
error_code);
}
static int send_data_callback(nghttp2_session *session _U_,
nghttp2_frame *frame, const uint8_t *framehd,
size_t length, nghttp2_data_source *source,
void *user_data) {
connection *conn = user_data;
uint8_t *p = conn->buf.last;
stream *strm = source->ptr;
/* We never use padding in this program */
assert(frame->data.padlen == 0);
if ((size_t)io_buf_left(&conn->buf) < 9 + frame->hd.length) {
return NGHTTP2_ERR_WOULDBLOCK;
}
memcpy(p, framehd, 9);
p += 9;
while (length) {
ssize_t nread;
while ((nread = read(strm->filefd, p, length)) == -1 && errno == EINTR)
;
if (nread == -1) {
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
length -= nread;
p += nread;
}
conn->buf.last = p;
return 0;
}
static ssize_t fd_read_callback(nghttp2_session *session _U_,
int32_t stream_id _U_, uint8_t *buf,
int32_t stream_id _U_, uint8_t *buf _U_,
size_t length, uint32_t *data_flags,
nghttp2_data_source *source,
void *user_data _U_) {
stream *strm = source->ptr;
ssize_t nread;
ssize_t nread =
(int64_t)length < strm->fileleft ? (int64_t)length : strm->fileleft;
*data_flags |= NGHTTP2_DATA_FLAG_NO_COPY;
while ((nread = read(strm->filefd, buf, length)) == -1 && errno == EINTR)
;
if (nread == -1) {
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
strm->fileleft -= nread;
if (nread == 0 || strm->fileleft == 0) {
if (strm->fileleft != 0) {
@@ -1274,14 +1317,8 @@ int main(int argc, char **argv) {
shared_callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_frame_not_send_callback(
shared_callbacks, on_frame_not_send_callback);
rv = nghttp2_option_new(&shared_option);
if (rv != 0) {
fprintf(stderr, "nghttp2_option_new: %s", nghttp2_strerror(rv));
exit(EXIT_FAILURE);
}
nghttp2_option_set_recv_client_preface(shared_option, 1);
nghttp2_session_callbacks_set_send_data_callback(shared_callbacks,
send_data_callback);
rv = io_loop_add(&loop, serv.fd, EPOLLIN, &serv);
@@ -1299,7 +1336,6 @@ int main(int argc, char **argv) {
io_loop_run(&loop, &serv);
nghttp2_option_del(shared_option);
nghttp2_session_callbacks_del(shared_callbacks);
return 0;

View File

@@ -1,5 +1,7 @@
#!/usr/bin/env python
from gentokenlookup import gentokenlookup
HEADERS = [
':authority',
':method',
@@ -26,6 +28,7 @@ HEADERS = [
"accept-language",
"cache-control",
"user-agent",
"date",
# disallowed h1 headers
'connection',
'keep-alive',
@@ -34,70 +37,5 @@ HEADERS = [
'upgrade'
]
def to_enum_hd(k):
res = 'HD_'
for c in k.upper():
if c == ':' or c == '-':
res += '_'
continue
res += c
return res
def build_header(headers):
res = {}
for k in headers:
size = len(k)
if size not in res:
res[size] = {}
ent = res[size]
c = k[-1]
if c not in ent:
ent[c] = []
ent[c].append(k)
return res
def gen_enum():
print '''\
enum {'''
for k in sorted(HEADERS):
print '''\
{},'''.format(to_enum_hd(k))
print '''\
HD_MAXIDX,
};'''
def gen_index_header():
print '''\
int lookup_token(const uint8_t *name, size_t namelen) {
switch (namelen) {'''
b = build_header(HEADERS)
for size in sorted(b.keys()):
ents = b[size]
print '''\
case {}:'''.format(size)
print '''\
switch (name[{}]) {{'''.format(size - 1)
for c in sorted(ents.keys()):
headers = sorted(ents[c])
print '''\
case '{}':'''.format(c)
for k in headers:
print '''\
if (util::streq_l("{}", name, {})) {{
return {};
}}'''.format(k[:-1], size - 1, to_enum_hd(k))
print '''\
break;'''
print '''\
}
break;'''
print '''\
}
return -1;
}'''
if __name__ == '__main__':
gen_enum()
print ''
gen_index_header()
gentokenlookup(HEADERS, 'HD')

View File

@@ -1,19 +1,72 @@
#!/usr/bin/env python
HEADERS = [
':authority',
':method',
':path',
':scheme',
':status',
"content-length",
"host",
"te",
'connection',
'keep-alive',
'proxy-connection',
'transfer-encoding',
'upgrade'
(':authority', 0),
(':method', 1),
(':method', 2),
(':path', 3),
(':path', 4),
(':scheme', 5),
(':scheme', 6),
(':status', 7),
(':status', 8),
(':status', 9),
(':status', 10),
(':status', 11),
(':status', 12),
(':status', 13),
('accept-charset', 14),
('accept-encoding', 15),
('accept-language', 16),
('accept-ranges', 17),
('accept', 18),
('access-control-allow-origin', 19),
('age', 20),
('allow', 21),
('authorization', 22),
('cache-control', 23),
('content-disposition', 24),
('content-encoding', 25),
('content-language', 26),
('content-length', 27),
('content-location', 28),
('content-range', 29),
('content-type', 30),
('cookie', 31),
('date', 32),
('etag', 33),
('expect', 34),
('expires', 35),
('from', 36),
('host', 37),
('if-match', 38),
('if-modified-since', 39),
('if-none-match', 40),
('if-range', 41),
('if-unmodified-since', 42),
('last-modified', 43),
('link', 44),
('location', 45),
('max-forwards', 46),
('proxy-authenticate', 47),
('proxy-authorization', 48),
('range', 49),
('referer', 50),
('refresh', 51),
('retry-after', 52),
('server', 53),
('set-cookie', 54),
('strict-transport-security', 55),
('transfer-encoding', 56),
('user-agent', 57),
('vary', 58),
('via', 59),
('www-authenticate', 60),
('te', None),
('connection', None),
('keep-alive',None),
('proxy-connection', None),
('upgrade', None),
]
def to_enum_hd(k):
@@ -27,7 +80,7 @@ def to_enum_hd(k):
def build_header(headers):
res = {}
for k in headers:
for k, _ in headers:
size = len(k)
if size not in res:
res[size] = {}
@@ -40,18 +93,20 @@ def build_header(headers):
return res
def gen_enum():
print '''\
typedef enum {'''
for k in sorted(HEADERS):
print '''\
{},'''.format(to_enum_hd(k))
print '''\
NGHTTP2_TOKEN_MAXIDX,
} nghttp2_token;'''
name = ''
print 'typedef enum {'
for k, token in HEADERS:
if token is None:
print ' {},'.format(to_enum_hd(k))
else:
if name != k:
name = k
print ' {} = {},'.format(to_enum_hd(k), token)
print '} nghttp2_token;'
def gen_index_header():
print '''\
static int lookup_token(const uint8_t *name, size_t namelen) {
static inline int lookup_token(const uint8_t *name, size_t namelen) {
switch (namelen) {'''
b = build_header(HEADERS)
for size in sorted(b.keys()):
@@ -66,7 +121,7 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
case '{}':'''.format(c)
for k in headers:
print '''\
if (streq("{}", name, {})) {{
if (lstreq("{}", name, {})) {{
return {};
}}'''.format(k[:-1], size - 1, to_enum_hd(k))
print '''\

53
genmethodfunc.py Executable file
View File

@@ -0,0 +1,53 @@
#!/usr/bin/env python
from __future__ import unicode_literals
from io import StringIO
from gentokenlookup import gentokenlookup
# copied from http-parser/http_parser.h, and stripped trailing spaces
# and backslashes.
SRC = '''
XX(0, DELETE, DELETE)
XX(1, GET, GET)
XX(2, HEAD, HEAD)
XX(3, POST, POST)
XX(4, PUT, PUT)
/* pathological */
XX(5, CONNECT, CONNECT)
XX(6, OPTIONS, OPTIONS)
XX(7, TRACE, TRACE)
/* webdav */
XX(8, COPY, COPY)
XX(9, LOCK, LOCK)
XX(10, MKCOL, MKCOL)
XX(11, MOVE, MOVE)
XX(12, PROPFIND, PROPFIND)
XX(13, PROPPATCH, PROPPATCH)
XX(14, SEARCH, SEARCH)
XX(15, UNLOCK, UNLOCK)
/* subversion */
XX(16, REPORT, REPORT)
XX(17, MKACTIVITY, MKACTIVITY)
XX(18, CHECKOUT, CHECKOUT)
XX(19, MERGE, MERGE)
/* upnp */
XX(20, MSEARCH, M-SEARCH)
XX(21, NOTIFY, NOTIFY)
XX(22, SUBSCRIBE, SUBSCRIBE)
XX(23, UNSUBSCRIBE, UNSUBSCRIBE)
/* RFC-5789 */
XX(24, PATCH, PATCH)
XX(25, PURGE, PURGE)
/* CalDAV */
XX(26, MKCALENDAR, MKCALENDAR)
'''
if __name__ == '__main__':
methods = []
for line in StringIO(SRC):
line = line.strip()
if not line.startswith('XX'):
continue
_, m, _ = line.split(',', 2)
methods.append(m.strip())
gentokenlookup(methods, 'HTTP')

127
gennghttpxfun.py Executable file
View File

@@ -0,0 +1,127 @@
#!/usr/bin/env python
from gentokenlookup import gentokenlookup
OPTIONS = [
"private-key-file",
"private-key-passwd-file",
"certificate-file",
"dh-param-file",
"subcert",
"backend",
"frontend",
"workers",
"http2-max-concurrent-streams",
"log-level",
"daemon",
"http2-proxy",
"http2-bridge",
"client-proxy",
"add-x-forwarded-for",
"strip-incoming-x-forwarded-for",
"no-via",
"frontend-http2-read-timeout",
"frontend-read-timeout",
"frontend-write-timeout",
"backend-read-timeout",
"backend-write-timeout",
"stream-read-timeout",
"stream-write-timeout",
"accesslog-file",
"accesslog-syslog",
"accesslog-format",
"errorlog-file",
"errorlog-syslog",
"backend-keep-alive-timeout",
"frontend-http2-window-bits",
"backend-http2-window-bits",
"frontend-http2-connection-window-bits",
"backend-http2-connection-window-bits",
"frontend-no-tls",
"backend-no-tls",
"backend-tls-sni-field",
"pid-file",
"user",
"syslog-facility",
"backlog",
"ciphers",
"client",
"insecure",
"cacert",
"backend-ipv4",
"backend-ipv6",
"backend-http-proxy-uri",
"read-rate",
"read-burst",
"write-rate",
"write-burst",
"worker-read-rate",
"worker-read-burst",
"worker-write-rate",
"worker-write-burst",
"npn-list",
"tls-proto-list",
"verify-client",
"verify-client-cacert",
"client-private-key-file",
"client-cert-file",
"frontend-http2-dump-request-header",
"frontend-http2-dump-response-header",
"http2-no-cookie-crumbling",
"frontend-frame-debug",
"padding",
"altsvc",
"add-request-header",
"add-response-header",
"worker-frontend-connections",
"no-location-rewrite",
"no-host-rewrite",
"backend-http1-connections-per-host",
"backend-http1-connections-per-frontend",
"listener-disable-timeout",
"tls-ticket-key-file",
"rlimit-nofile",
"backend-request-buffer",
"backend-response-buffer",
"no-server-push",
"backend-http2-connections-per-worker",
"fetch-ocsp-response-file",
"ocsp-update-interval",
"no-ocsp",
"header-field-buffer",
"max-header-fields",
"include",
"tls-ticket-key-cipher",
"host-rewrite",
"tls-session-cache-memcached",
"tls-ticket-key-memcached",
"tls-ticket-key-memcached-interval",
"tls-ticket-key-memcached-max-retry",
"tls-ticket-key-memcached-max-fail",
"request-phase-file",
"response-phase-file",
"accept-proxy-protocol",
"conf",
]
LOGVARS = [
"remote_addr",
"time_local",
"time_iso8601",
"request",
"status",
"body_bytes_sent",
"remote_port",
"server_port",
"request_time",
"pid",
"alpn",
"ssl_cipher",
"ssl_protocol",
"ssl_session_id",
"ssl_session_reused",
]
if __name__ == '__main__':
gentokenlookup(OPTIONS, 'SHRPX_OPTID', value_type='char', comp_fun='util::strieq_l')
gentokenlookup(LOGVARS, 'SHRPX_LOGF', value_type='char', comp_fun='util::strieq_l', return_type='LogFragmentType', fail_value='SHRPX_LOGF_NONE')

69
gentokenlookup.py Normal file
View File

@@ -0,0 +1,69 @@
#!/usr/bin/env python
def to_enum_hd(k, prefix):
res = prefix + '_'
for c in k.upper():
if c == ':' or c == '-':
res += '_'
continue
res += c
return res
def build_header(headers):
res = {}
for k in headers:
size = len(k)
if size not in res:
res[size] = {}
ent = res[size]
c = k[-1]
if c not in ent:
ent[c] = []
ent[c].append(k)
return res
def gen_enum(tokens, prefix):
print '''\
enum {'''
for k in sorted(tokens):
print '''\
{},'''.format(to_enum_hd(k, prefix))
print '''\
{}_MAXIDX,
}};'''.format(prefix)
def gen_index_header(tokens, prefix, value_type, comp_fun, return_type, fail_value):
print '''\
{} lookup_token(const {} *name, size_t namelen) {{
switch (namelen) {{'''.format(return_type, value_type)
b = build_header(tokens)
for size in sorted(b.keys()):
ents = b[size]
print '''\
case {}:'''.format(size)
print '''\
switch (name[{}]) {{'''.format(size - 1)
for c in sorted(ents.keys()):
headers = sorted(ents[c])
print '''\
case '{}':'''.format(c)
for k in headers:
print '''\
if ({}("{}", name, {})) {{
return {};
}}'''.format(comp_fun, k[:-1], size - 1, to_enum_hd(k, prefix))
print '''\
break;'''
print '''\
}
break;'''
print '''\
}}
return {};
}}'''.format(fail_value)
def gentokenlookup(tokens, prefix, value_type='uint8_t', comp_fun='util::streq_l', return_type='int', fail_value='-1'):
gen_enum(tokens, prefix)
print ''
gen_index_header(tokens, prefix, value_type, comp_fun, return_type, fail_value)

View File

@@ -4,6 +4,7 @@
# script to produce rst file from program's help output.
from __future__ import unicode_literals
from __future__ import print_function
import sys
import re
import argparse
@@ -44,8 +45,8 @@ def help2man(infile):
line = infile.readline().strip()
m = re.match(r'^Usage: (.*)', line)
if not m:
print 'usage line is invalid. Expected following lines:'
print 'Usage: cmdname ...'
print('usage line is invalid. Expected following lines:')
print('Usage: cmdname ...')
sys.exit(1)
synopsis = m.group(1).split(' ', 1)
if len(synopsis) == 2:
@@ -60,7 +61,11 @@ def help2man(infile):
break
description.append(line)
print '''
print('''
.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY.
.. program:: {cmdname}
{cmdname}(1)
{cmdnameunderline}
@@ -75,39 +80,48 @@ DESCRIPTION
{description}
'''.format(cmdname=cmdname, args=args,
cmdnameunderline='=' * (len(cmdname) + 3),
synopsis=synopsis, description=format_text('\n'.join(description)))
synopsis=synopsis, description=format_text('\n'.join(description))))
in_arg = False
in_footer = False
for line in infile:
line = line.rstrip()
if not line.strip() and in_arg:
print ''
print()
continue
if line.startswith(' ') and in_arg:
if not line.startswith(arg_indent):
sys.stderr.write('warning: argument description is not indented correctly. We need {} spaces as indentation.\n'.format(len(arg_indent)))
print '{}'.format(format_arg_text(line[len(arg_indent):]))
print('{}'.format(format_arg_text(line[len(arg_indent):])))
continue
if in_arg:
print ''
print()
in_arg = False
if line == '--':
in_footer = True
continue
if in_footer:
print(line.strip())
continue
if line == 'Options:':
print 'OPTIONS'
print '-------'
print ''
print('OPTIONS')
print('-------')
print()
continue
if line.startswith(' <'):
# positional argument
m = re.match(r'^(?:\s+)([a-zA-Z0-9-_<>]+)(.*)', line)
argname, rest = m.group(1), m.group(2)
print '.. describe:: {}'.format(argname)
print ''
print '{}'.format(format_arg_text(rest.strip()))
print('.. describe:: {}'.format(argname))
print()
print('{}'.format(format_arg_text(rest.strip())))
in_arg = True
continue
@@ -115,9 +129,9 @@ DESCRIPTION
# positional argument
m = re.match(r'^(?:\s+)(\([a-zA-Z0-9-_<> ]+\))(.*)', line)
argname, rest = m.group(1), m.group(2)
print '.. describe:: {}'.format(argname)
print ''
print '{}'.format(format_arg_text(rest.strip()))
print('.. describe:: {}'.format(argname))
print()
print('{}'.format(format_arg_text(rest.strip())))
in_arg = True
continue
@@ -127,23 +141,23 @@ DESCRIPTION
r'^(?:\s+)(-\S+?(?:, -\S+?)*)($| .*)',
line)
argname, rest = m.group(1), m.group(2)
print '.. option:: {}'.format(argname)
print ''
print('.. option:: {}'.format(argname))
print()
rest = rest.strip()
if len(rest):
print '{}'.format(format_arg_text(rest))
print('{}'.format(format_arg_text(rest)))
in_arg = True
continue
if not line.startswith(' ') and line.endswith(':'):
# subsection
subsec = line.strip()[:-1]
print '{}'.format(subsec)
print '{}'.format('~' * len(subsec))
print ''
print('{}'.format(subsec))
print('{}'.format('~' * len(subsec)))
print()
continue
print line.strip()
print(line.strip())
def format_text(text):
# escape *
@@ -173,6 +187,6 @@ if __name__ == '__main__':
args = parser.parse_args()
help2man(sys.stdin)
if args.include:
print ''
print()
with open(args.include) as f:
sys.stdout.write(f.read())

2
integration-tests/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
# generated files
config.go

View File

@@ -30,14 +30,16 @@ EXTRA_DIST = \
server.crt \
alt-server.key \
alt-server.crt \
setenv
setenv \
req-set-header.rb \
resp-set-header.rb \
return.rb
.PHONY: itprep it
itprep:
itprep-local:
go get -d -v github.com/bradfitz/http2
go get -d -v github.com/tatsuhiro-t/go-nghttp2
go get -d -v golang.org/x/net/spdy
go get -d -v github.com/tatsuhiro-t/spdy
go get -d -v golang.org/x/net/websocket
it:
it-local:
sh setenv go test -v

View File

@@ -2,8 +2,10 @@ package nghttp2
import (
"bufio"
"bytes"
"fmt"
"github.com/bradfitz/http2/hpack"
"golang.org/x/net/websocket"
"io"
"net/http"
"syscall"
@@ -50,6 +52,27 @@ func TestH1H1PlainGETClose(t *testing.T) {
}
}
// TestH1H1InvalidMethod tests that server rejects invalid method with
// 501 status code
func TestH1H1InvalidMethod(t *testing.T) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
t.Errorf("server should not forward this request")
})
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1H1InvalidMethod",
method: "get",
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 501; got != want {
t.Errorf("status = %v; want %v", got, want)
}
}
// TestH1H1MultipleRequestCL tests that server rejects request which
// contains multiple Content-Length header fields.
func TestH1H1MultipleRequestCL(t *testing.T) {
@@ -141,7 +164,7 @@ func TestH1H1GracefulShutdown(t *testing.T) {
// TestH1H1HostRewrite tests that server rewrites Host header field
func TestH1H1HostRewrite(t *testing.T) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
st := newServerTester([]string{"--host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("request-host", r.Host)
})
defer st.Close()
@@ -189,7 +212,7 @@ func TestH1H1HTTP10(t *testing.T) {
// field using actual backend server even if --no-http-rewrite is
// used.
func TestH1H1HTTP10NoHostRewrite(t *testing.T) {
st := newServerTester([]string{"--no-host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("request-host", r.Host)
})
defer st.Close()
@@ -246,6 +269,206 @@ func TestH1H1RequestTrailer(t *testing.T) {
}
}
// TestH1H1HeaderFieldBufferPath tests that request with request path
// larger than configured buffer size is rejected.
func TestH1H1HeaderFieldBufferPath(t *testing.T) {
// The value 100 is chosen so that sum of header fields bytes
// does not exceed it. We use > 100 bytes URI to exceed this
// limit.
st := newServerTester([]string{"--header-field-buffer=100"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatal("execution path should not be here")
})
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1H1HeaderFieldBufferPath",
path: "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 431; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestH1H1HeaderFieldBuffer tests that request with header fields
// larger than configured buffer size is rejected.
func TestH1H1HeaderFieldBuffer(t *testing.T) {
st := newServerTester([]string{"--header-field-buffer=10"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatal("execution path should not be here")
})
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1H1HeaderFieldBuffer",
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 431; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestH1H1HeaderFields tests that request with header fields more
// than configured number is rejected.
func TestH1H1HeaderFields(t *testing.T) {
st := newServerTester([]string{"--max-header-fields=1"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatal("execution path should not be here")
})
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1H1HeaderFields",
header: []hpack.HeaderField{
// Add extra header field to ensure that
// header field limit exceeds
pair("Connection", "close"),
},
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 431; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestH1H1Websocket tests that HTTP Upgrade to WebSocket works.
func TestH1H1Websocket(t *testing.T) {
st := newServerTesterHandler(nil, t, websocket.Handler(func(ws *websocket.Conn) {
io.Copy(ws, ws)
}))
defer st.Close()
content := []byte("hello world")
res, err := st.websocket(requestParam{
name: "TestH1H1Websocket",
body: content,
})
if err != nil {
t.Fatalf("Error st.websocket() = %v", err)
}
if got, want := res.body, content; !bytes.Equal(got, want) {
t.Errorf("echo: %q; want %q", got, want)
}
}
// TestH1H1ReqPhaseSetHeader tests mruby request phase hook
// modifies request header fields.
func TestH1H1ReqPhaseSetHeader(t *testing.T) {
st := newServerTester([]string{"--request-phase-file=" + testDir + "/req-set-header.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, want := r.Header.Get("User-Agent"), "mruby"; got != want {
t.Errorf("User-Agent = %v; want %v", got, want)
}
})
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1H1ReqPhaseSetHeader",
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("status = %v; want %v", got, want)
}
}
// TestH1H1ReqPhaseReturn tests mruby request phase hook returns
// custom response.
func TestH1H1ReqPhaseReturn(t *testing.T) {
st := newServerTester([]string{"--request-phase-file=" + testDir + "/return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
})
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1H1ReqPhaseReturn",
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("status = %v; want %v", got, want)
}
hdtests := []struct {
k, v string
}{
{"content-length", "11"},
{"from", "mruby"},
}
for _, tt := range hdtests {
if got, want := res.header.Get(tt.k), tt.v; got != want {
t.Errorf("%v = %v; want %v", tt.k, got, want)
}
}
if got, want := string(res.body), "Hello World"; got != want {
t.Errorf("body = %v; want %v", got, want)
}
}
// TestH1H1RespPhaseSetHeader tests mruby response phase hook modifies
// response header fields.
func TestH1H1RespPhaseSetHeader(t *testing.T) {
st := newServerTester([]string{"--response-phase-file=" + testDir + "/resp-set-header.rb"}, t, noopHandler)
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1H1RespPhaseSetHeader",
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("status = %v; want %v", got, want)
}
if got, want := res.header.Get("alpha"), "bravo"; got != want {
t.Errorf("alpha = %v; want %v", got, want)
}
}
// TestH1H1RespPhaseReturn tests mruby response phase hook returns
// custom response.
func TestH1H1RespPhaseReturn(t *testing.T) {
st := newServerTester([]string{"--response-phase-file=" + testDir + "/return.rb"}, t, noopHandler)
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1H1RespPhaseReturn",
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("status = %v; want %v", got, want)
}
hdtests := []struct {
k, v string
}{
{"content-length", "11"},
{"from", "mruby"},
}
for _, tt := range hdtests {
if got, want := res.header.Get(tt.k), tt.v; got != want {
t.Errorf("%v = %v; want %v", tt.k, got, want)
}
}
if got, want := string(res.body), "Hello World"; got != want {
t.Errorf("body = %v; want %v", got, want)
}
}
// TestH1H2ConnectFailure tests that server handles the situation that
// connection attempt to HTTP/2 backend failed.
func TestH1H2ConnectFailure(t *testing.T) {
@@ -320,7 +543,7 @@ func TestH1H2HTTP10(t *testing.T) {
// field using actual backend server even if --no-http-rewrite is
// used.
func TestH1H2HTTP10NoHostRewrite(t *testing.T) {
st := newServerTester([]string{"--http2-bridge", "--no-host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) {
st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("request-host", r.Host)
})
defer st.Close()
@@ -438,3 +661,73 @@ func TestH1H2NoVia(t *testing.T) {
t.Errorf("Via: %v; want %v", got, want)
}
}
// TestH1H2ReqPhaseReturn tests mruby request phase hook returns
// custom response.
func TestH1H2ReqPhaseReturn(t *testing.T) {
st := newServerTester([]string{"--http2-bridge", "--request-phase-file=" + testDir + "/return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
})
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1H2ReqPhaseReturn",
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("status = %v; want %v", got, want)
}
hdtests := []struct {
k, v string
}{
{"content-length", "11"},
{"from", "mruby"},
}
for _, tt := range hdtests {
if got, want := res.header.Get(tt.k), tt.v; got != want {
t.Errorf("%v = %v; want %v", tt.k, got, want)
}
}
if got, want := string(res.body), "Hello World"; got != want {
t.Errorf("body = %v; want %v", got, want)
}
}
// TestH1H2RespPhaseReturn tests mruby response phase hook returns
// custom response.
func TestH1H2RespPhaseReturn(t *testing.T) {
st := newServerTester([]string{"--http2-bridge", "--response-phase-file=" + testDir + "/return.rb"}, t, noopHandler)
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1H2RespPhaseReturn",
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("status = %v; want %v", got, want)
}
hdtests := []struct {
k, v string
}{
{"content-length", "11"},
{"from", "mruby"},
}
for _, tt := range hdtests {
if got, want := res.header.Get(tt.k), tt.v; got != want {
t.Errorf("%v = %v; want %v", tt.k, got, want)
}
}
if got, want := string(res.body), "Hello World"; got != want {
t.Errorf("body = %v; want %v", got, want)
}
}

View File

@@ -8,6 +8,7 @@ import (
"io"
"io/ioutil"
"net/http"
"strings"
"syscall"
"testing"
)
@@ -194,7 +195,7 @@ func TestH2H1NoVia(t *testing.T) {
// TestH2H1HostRewrite tests that server rewrites host header field
func TestH2H1HostRewrite(t *testing.T) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
st := newServerTester([]string{"--host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("request-host", r.Host)
})
defer st.Close()
@@ -216,7 +217,7 @@ func TestH2H1HostRewrite(t *testing.T) {
// TestH2H1NoHostRewrite tests that server does not rewrite host
// header field
func TestH2H1NoHostRewrite(t *testing.T) {
st := newServerTester([]string{"--no-host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("request-host", r.Host)
})
defer st.Close()
@@ -403,6 +404,26 @@ func TestH2H1ConnectFailure(t *testing.T) {
}
}
// TestH2H1InvalidMethod tests that server rejects invalid method with
// 501.
func TestH2H1InvalidMethod(t *testing.T) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
t.Errorf("server should not forward this request")
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1InvalidMethod",
method: "get",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 501; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestH2H1AssembleCookies tests that crumbled cookies in HTTP/2
// request is assembled into 1 when forwarding to HTTP/1 backend link.
func TestH2H1AssembleCookies(t *testing.T) {
@@ -489,12 +510,36 @@ func TestH2H1SNI(t *testing.T) {
}
}
// TestH2H1TLSXfp tests nghttpx sends x-forwarded-proto header field
// with http value since :scheme is http, even if the frontend
// connection is encrypted.
func TestH2H1TLSXfp(t *testing.T) {
st := newServerTesterTLS(nil, t, func(w http.ResponseWriter, r *http.Request) {
if got, want := r.Header.Get("x-forwarded-proto"), "http"; got != want {
t.Errorf("x-forwarded-proto: want %v; got %v", want, got)
}
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1TLSXfp",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
}
// TestH2H1ServerPush tests server push using Link header field from
// backend server.
func TestH2H1ServerPush(t *testing.T) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
// only resources marked as rel=preload are pushed
w.Header().Add("Link", "</css/main.css>; rel=preload, </foo>, </css/theme.css>; rel=preload")
if !strings.HasPrefix(r.URL.Path, "/css/") {
w.Header().Add("Link", "</css/main.css>; rel=preload, </foo>, </css/theme.css>; rel=preload")
}
})
defer st.Close()
@@ -555,6 +600,549 @@ func TestH2H1RequestTrailer(t *testing.T) {
}
}
// TestH2H1HeaderFieldBuffer tests that request with header fields
// larger than configured buffer size is rejected.
func TestH2H1HeaderFieldBuffer(t *testing.T) {
st := newServerTester([]string{"--header-field-buffer=10"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatal("execution path should not be here")
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1HeaderFieldBuffer",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 431; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestH2H1HeaderFields tests that request with header fields more
// than configured number is rejected.
func TestH2H1HeaderFields(t *testing.T) {
st := newServerTester([]string{"--max-header-fields=1"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatal("execution path should not be here")
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1HeaderFields",
// we have at least 4 pseudo-header fields sent, and
// that ensures that buffer limit exceeds.
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 431; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestH2H1ReqPhaseSetHeader tests mruby request phase hook
// modifies request header fields.
func TestH2H1ReqPhaseSetHeader(t *testing.T) {
st := newServerTester([]string{"--request-phase-file=" + testDir + "/req-set-header.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, want := r.Header.Get("User-Agent"), "mruby"; got != want {
t.Errorf("User-Agent = %v; want %v", got, want)
}
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1ReqPhaseSetHeader",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("status = %v; want %v", got, want)
}
}
// TestH2H1ReqPhaseReturn tests mruby request phase hook returns
// custom response.
func TestH2H1ReqPhaseReturn(t *testing.T) {
st := newServerTester([]string{"--request-phase-file=" + testDir + "/return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1ReqPhaseReturn",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("status = %v; want %v", got, want)
}
hdtests := []struct {
k, v string
}{
{"content-length", "11"},
{"from", "mruby"},
}
for _, tt := range hdtests {
if got, want := res.header.Get(tt.k), tt.v; got != want {
t.Errorf("%v = %v; want %v", tt.k, got, want)
}
}
if got, want := string(res.body), "Hello World"; got != want {
t.Errorf("body = %v; want %v", got, want)
}
}
// TestH2H1RespPhaseSetHeader tests mruby response phase hook modifies
// response header fields.
func TestH2H1RespPhaseSetHeader(t *testing.T) {
st := newServerTester([]string{"--response-phase-file=" + testDir + "/resp-set-header.rb"}, t, noopHandler)
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1RespPhaseSetHeader",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("status = %v; want %v", got, want)
}
if got, want := res.header.Get("alpha"), "bravo"; got != want {
t.Errorf("alpha = %v; want %v", got, want)
}
}
// TestH2H1RespPhaseReturn tests mruby response phase hook returns
// custom response.
func TestH2H1RespPhaseReturn(t *testing.T) {
st := newServerTester([]string{"--response-phase-file=" + testDir + "/return.rb"}, t, noopHandler)
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1RespPhaseReturn",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("status = %v; want %v", got, want)
}
hdtests := []struct {
k, v string
}{
{"content-length", "11"},
{"from", "mruby"},
}
for _, tt := range hdtests {
if got, want := res.header.Get(tt.k), tt.v; got != want {
t.Errorf("%v = %v; want %v", tt.k, got, want)
}
}
if got, want := string(res.body), "Hello World"; got != want {
t.Errorf("body = %v; want %v", got, want)
}
}
// TestH2H1Upgrade tests HTTP Upgrade to HTTP/2
func TestH2H1Upgrade(t *testing.T) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {})
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH2H1Upgrade",
header: []hpack.HeaderField{
pair("Connection", "Upgrade, HTTP2-Settings"),
pair("Upgrade", "h2c"),
pair("HTTP2-Settings", "AAMAAABkAAQAAP__"),
},
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 101; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
res, err = st.http2(requestParam{
httpUpgrade: true,
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
}
// TestH2H1ProxyProtocolV1TCP4 tests PROXY protocol version 1
// containing TCP4 entry is accepted and X-Forwarded-For contains
// advertised src address.
func TestH2H1ProxyProtocolV1TCP4(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
}
})
defer st.Close()
st.conn.Write([]byte("PROXY TCP4 192.168.0.2 192.168.0.100 12345 8080\r\n"))
res, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1TCP4",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
}
// TestH2H1ProxyProtocolV1TCP6 tests PROXY protocol version 1
// containing TCP6 entry is accepted and X-Forwarded-For contains
// advertised src address.
func TestH2H1ProxyProtocolV1TCP6(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, want := r.Header.Get("X-Forwarded-For"), "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; got != want {
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
}
})
defer st.Close()
st.conn.Write([]byte("PROXY TCP6 2001:0db8:85a3:0000:0000:8a2e:0370:7334 ::1 12345 8080\r\n"))
res, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1TCP6",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
}
// TestH2H1ProxyProtocolV1Unknown tests PROXY protocol version 1
// containing UNKNOWN entry is accepted.
func TestH2H1ProxyProtocolV1Unknown(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, notWant := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got == notWant {
t.Errorf("X-Forwarded-For: %v")
}
})
defer st.Close()
st.conn.Write([]byte("PROXY UNKNOWN 192.168.0.2 192.168.0.100 12345 8080\r\n"))
res, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1Unknown",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
}
// TestH2H1ProxyProtocolV1JustUnknown tests PROXY protocol version 1
// containing only "PROXY UNKNOWN" is accepted.
func TestH2H1ProxyProtocolV1JustUnknown(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, noopHandler)
defer st.Close()
st.conn.Write([]byte("PROXY UNKNOWN\r\n"))
res, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1JustUnknown",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
}
// TestH2H1ProxyProtocolV1TooLongLine tests PROXY protocol version 1
// line longer than 107 bytes must be rejected
func TestH2H1ProxyProtocolV1TooLongLine(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, noopHandler)
defer st.Close()
st.conn.Write([]byte("PROXY UNKNOWN ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 655350\r\n"))
_, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1TooLongLine",
})
if err == nil {
t.Fatalf("connection was not terminated")
}
}
// TestH2H1ProxyProtocolV1BadLineEnd tests that PROXY protocol version
// 1 line ending without \r\n should be rejected.
func TestH2H1ProxyProtocolV1BadLineEnd(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
defer st.Close()
st.conn.Write([]byte("PROXY TCP6 ::1 ::1 12345 8080\r \n"))
_, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1BadLineEnd",
})
if err == nil {
t.Fatalf("connection was not terminated")
}
}
// TestH2H1ProxyProtocolV1NoEnd tests that PROXY protocol version 1
// line containing no \r\n should be rejected.
func TestH2H1ProxyProtocolV1NoEnd(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
defer st.Close()
st.conn.Write([]byte("PROXY TCP6 ::1 ::1 12345 8080"))
_, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1NoEnd",
})
if err == nil {
t.Fatalf("connection was not terminated")
}
}
// TestH2H1ProxyProtocolV1EmbeddedNULL tests that PROXY protocol
// version 1 line containing NULL character should be rejected.
func TestH2H1ProxyProtocolV1EmbeddedNULL(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
defer st.Close()
b := []byte("PROXY TCP6 ::1*foo ::1 12345 8080\r\n")
b[14] = 0
st.conn.Write(b)
_, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1EmbeddedNULL",
})
if err == nil {
t.Fatalf("connection was not terminated")
}
}
// TestH2H1ProxyProtocolV1MissingSrcPort tests that PROXY protocol
// version 1 line without src port should be rejected.
func TestH2H1ProxyProtocolV1MissingSrcPort(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
defer st.Close()
st.conn.Write([]byte("PROXY TCP6 ::1 ::1 8080\r\n"))
_, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1MissingSrcPort",
})
if err == nil {
t.Fatalf("connection was not terminated")
}
}
// TestH2H1ProxyProtocolV1MissingDstPort tests that PROXY protocol
// version 1 line without dst port should be rejected.
func TestH2H1ProxyProtocolV1MissingDstPort(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
defer st.Close()
st.conn.Write([]byte("PROXY TCP6 ::1 ::1 12345 \r\n"))
_, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1MissingDstPort",
})
if err == nil {
t.Fatalf("connection was not terminated")
}
}
// TestH2H1ProxyProtocolV1InvalidSrcPort tests that PROXY protocol
// containing invalid src port should be rejected.
func TestH2H1ProxyProtocolV1InvalidSrcPort(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
defer st.Close()
st.conn.Write([]byte("PROXY TCP6 ::1 ::1 123x 8080\r\n"))
_, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1InvalidSrcPort",
})
if err == nil {
t.Fatalf("connection was not terminated")
}
}
// TestH2H1ProxyProtocolV1InvalidDstPort tests that PROXY protocol
// containing invalid dst port should be rejected.
func TestH2H1ProxyProtocolV1InvalidDstPort(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
defer st.Close()
st.conn.Write([]byte("PROXY TCP6 ::1 ::1 123456 80x\r\n"))
_, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1InvalidDstPort",
})
if err == nil {
t.Fatalf("connection was not terminated")
}
}
// TestH2H1ProxyProtocolV1LeadingZeroPort tests that PROXY protocol
// version 1 line with non zero port with leading zero should be
// rejected.
func TestH2H1ProxyProtocolV1LeadingZeroPort(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
defer st.Close()
st.conn.Write([]byte("PROXY TCP6 ::1 ::1 03000 8080\r\n"))
_, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1LeadingZeroPort",
})
if err == nil {
t.Fatalf("connection was not terminated")
}
}
// TestH2H1ProxyProtocolV1TooLargeSrcPort tests that PROXY protocol
// containing too large src port should be rejected.
func TestH2H1ProxyProtocolV1TooLargeSrcPort(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
defer st.Close()
st.conn.Write([]byte("PROXY TCP6 ::1 ::1 65536 8080\r\n"))
_, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1TooLargeSrcPort",
})
if err == nil {
t.Fatalf("connection was not terminated")
}
}
// TestH2H1ProxyProtocolV1TooLargeDstPort tests that PROXY protocol
// containing too large dst port should be rejected.
func TestH2H1ProxyProtocolV1TooLargeDstPort(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
defer st.Close()
st.conn.Write([]byte("PROXY TCP6 ::1 ::1 12345 65536\r\n"))
_, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1TooLargeDstPort",
})
if err == nil {
t.Fatalf("connection was not terminated")
}
}
// TestH2H1ProxyProtocolV1InvalidSrcAddr tests that PROXY protocol
// containing invalid src addr should be rejected.
func TestH2H1ProxyProtocolV1InvalidSrcAddr(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
defer st.Close()
st.conn.Write([]byte("PROXY TCP6 192.168.0.1 ::1 12345 8080\r\n"))
_, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1InvalidSrcAddr",
})
if err == nil {
t.Fatalf("connection was not terminated")
}
}
// TestH2H1ProxyProtocolV1InvalidDstAddr tests that PROXY protocol
// containing invalid dst addr should be rejected.
func TestH2H1ProxyProtocolV1InvalidDstAddr(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
defer st.Close()
st.conn.Write([]byte("PROXY TCP6 ::1 192.168.0.1 12345 8080\r\n"))
_, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1InvalidDstAddr",
})
if err == nil {
t.Fatalf("connection was not terminated")
}
}
// TestH2H1ProxyProtocolV1InvalidProtoFamily tests that PROXY protocol
// containing invalid protocol family should be rejected.
func TestH2H1ProxyProtocolV1InvalidProtoFamily(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
defer st.Close()
st.conn.Write([]byte("PROXY UNIX ::1 ::1 12345 8080\r\n"))
_, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1InvalidProtoFamily",
})
if err == nil {
t.Fatalf("connection was not terminated")
}
}
// TestH2H1ProxyProtocolV1InvalidID tests that PROXY protocol
// containing invalid PROXY protocol version 1 ID should be rejected.
func TestH2H1ProxyProtocolV1InvalidID(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
defer st.Close()
st.conn.Write([]byte("PR0XY TCP6 ::1 ::1 12345 8080\r\n"))
_, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1InvalidID",
})
if err == nil {
t.Fatalf("connection was not terminated")
}
}
// TestH2H1GracefulShutdown tests graceful shutdown.
func TestH2H1GracefulShutdown(t *testing.T) {
st := newServerTester(nil, t, noopHandler)
@@ -695,7 +1283,7 @@ func TestH2H2ConnectFailure(t *testing.T) {
// TestH2H2HostRewrite tests that server rewrites host header field
func TestH2H2HostRewrite(t *testing.T) {
st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
st := newServerTester([]string{"--http2-bridge", "--host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("request-host", r.Host)
})
defer st.Close()
@@ -717,7 +1305,7 @@ func TestH2H2HostRewrite(t *testing.T) {
// TestH2H2NoHostRewrite tests that server does not rewrite host
// header field
func TestH2H2NoHostRewrite(t *testing.T) {
st := newServerTester([]string{"--http2-bridge", "--no-host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) {
st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("request-host", r.Host)
})
defer st.Close()
@@ -735,3 +1323,95 @@ func TestH2H2NoHostRewrite(t *testing.T) {
t.Errorf("request-host: %v; want %v", got, want)
}
}
// TestH2H2TLSXfp tests nghttpx sends x-forwarded-proto header field
// with http value since :scheme is http, even if the frontend
// connection is encrypted.
func TestH2H2TLSXfp(t *testing.T) {
st := newServerTesterTLS([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, want := r.Header.Get("x-forwarded-proto"), "http"; got != want {
t.Errorf("x-forwarded-proto: want %v; got %v", want, got)
}
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H2TLSXfp",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
}
// TestH2H2ReqPhaseReturn tests mruby request phase hook returns
// custom response.
func TestH2H2ReqPhaseReturn(t *testing.T) {
st := newServerTester([]string{"--http2-bridge", "--request-phase-file=" + testDir + "/return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H2ReqPhaseReturn",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("status = %v; want %v", got, want)
}
hdtests := []struct {
k, v string
}{
{"content-length", "11"},
{"from", "mruby"},
}
for _, tt := range hdtests {
if got, want := res.header.Get(tt.k), tt.v; got != want {
t.Errorf("%v = %v; want %v", tt.k, got, want)
}
}
if got, want := string(res.body), "Hello World"; got != want {
t.Errorf("body = %v; want %v", got, want)
}
}
// TestH2H2RespPhaseReturn tests mruby response phase hook returns
// custom response.
func TestH2H2RespPhaseReturn(t *testing.T) {
st := newServerTester([]string{"--http2-bridge", "--response-phase-file=" + testDir + "/return.rb"}, t, noopHandler)
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H2RespPhaseReturn",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("status = %v; want %v", got, want)
}
hdtests := []struct {
k, v string
}{
{"content-length", "11"},
{"from", "mruby"},
}
for _, tt := range hdtests {
if got, want := res.header.Get(tt.k), tt.v; got != want {
t.Errorf("%v = %v; want %v", tt.k, got, want)
}
}
if got, want := string(res.body), "Hello World"; got != want {
t.Errorf("body = %v; want %v", got, want)
}
}

View File

@@ -2,7 +2,7 @@ package nghttp2
import (
"github.com/bradfitz/http2/hpack"
"golang.org/x/net/spdy"
"github.com/tatsuhiro-t/spdy"
"net/http"
"testing"
)
@@ -170,6 +170,180 @@ func TestS3H1NoVia(t *testing.T) {
}
}
// TestS3H1HeaderFieldBuffer tests that request with header fields
// larger than configured buffer size is rejected.
func TestS3H1HeaderFieldBuffer(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--header-field-buffer=10"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatal("execution path should not be here")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1HeaderFieldBuffer",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.spdyRstErrCode, spdy.InternalError; got != want {
t.Errorf("res.spdyRstErrCode: %v; want %v", got, want)
}
}
// TestS3H1HeaderFields tests that request with header fields more
// than configured number is rejected.
func TestS3H1HeaderFields(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--max-header-fields=1"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatal("execution path should not be here")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1HeaderFields",
// we have at least 5 pseudo-header fields sent, and
// that ensures that buffer limit exceeds.
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.spdyRstErrCode, spdy.InternalError; got != want {
t.Errorf("res.spdyRstErrCode: %v; want %v", got, want)
}
}
// TestS3H1InvalidMethod tests that server rejects invalid method with
// 501.
func TestS3H1InvalidMethod(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Errorf("server should not forward this request")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1InvalidMethod",
method: "get",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 501; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestS3H1ReqPhaseSetHeader tests mruby request phase hook
// modifies request header fields.
func TestS3H1ReqPhaseSetHeader(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--request-phase-file=" + testDir + "/req-set-header.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, want := r.Header.Get("User-Agent"), "mruby"; got != want {
t.Errorf("User-Agent = %v; want %v", got, want)
}
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1ReqPhaseSetHeader",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("status = %v; want %v", got, want)
}
}
// TestS3H1ReqPhaseReturn tests mruby request phase hook returns
// custom response.
func TestS3H1ReqPhaseReturn(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--request-phase-file=" + testDir + "/return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1ReqPhaseReturn",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("status = %v; want %v", got, want)
}
hdtests := []struct {
k, v string
}{
{"content-length", "11"},
{"from", "mruby"},
}
for _, tt := range hdtests {
if got, want := res.header.Get(tt.k), tt.v; got != want {
t.Errorf("%v = %v; want %v", tt.k, got, want)
}
}
if got, want := string(res.body), "Hello World"; got != want {
t.Errorf("body = %v; want %v", got, want)
}
}
// TestS3H1RespPhaseSetHeader tests mruby response phase hook modifies
// response header fields.
func TestS3H1RespPhaseSetHeader(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--response-phase-file=" + testDir + "/resp-set-header.rb"}, t, noopHandler)
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1RespPhaseSetHeader",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("status = %v; want %v", got, want)
}
if got, want := res.header.Get("alpha"), "bravo"; got != want {
t.Errorf("alpha = %v; want %v", got, want)
}
}
// TestS3H1RespPhaseReturn tests mruby response phase hook returns
// custom response.
func TestS3H1RespPhaseReturn(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--response-phase-file=" + testDir + "/return.rb"}, t, noopHandler)
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1RespPhaseReturn",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("status = %v; want %v", got, want)
}
hdtests := []struct {
k, v string
}{
{"content-length", "11"},
{"from", "mruby"},
}
for _, tt := range hdtests {
if got, want := res.header.Get(tt.k), tt.v; got != want {
t.Errorf("%v = %v; want %v", tt.k, got, want)
}
}
if got, want := string(res.body), "Hello World"; got != want {
t.Errorf("body = %v; want %v", got, want)
}
}
// TestS3H2ConnectFailure tests that server handles the situation that
// connection attempt to HTTP/2 backend failed.
func TestS3H2ConnectFailure(t *testing.T) {
@@ -190,3 +364,73 @@ func TestS3H2ConnectFailure(t *testing.T) {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestS3H2ReqPhaseReturn tests mruby request phase hook returns
// custom response.
func TestS3H2ReqPhaseReturn(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--http2-bridge", "--request-phase-file=" + testDir + "/return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H2ReqPhaseReturn",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("status = %v; want %v", got, want)
}
hdtests := []struct {
k, v string
}{
{"content-length", "11"},
{"from", "mruby"},
}
for _, tt := range hdtests {
if got, want := res.header.Get(tt.k), tt.v; got != want {
t.Errorf("%v = %v; want %v", tt.k, got, want)
}
}
if got, want := string(res.body), "Hello World"; got != want {
t.Errorf("body = %v; want %v", got, want)
}
}
// TestS3H2RespPhaseReturn tests mruby response phase hook returns
// custom response.
func TestS3H2RespPhaseReturn(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--http2-bridge", "--response-phase-file=" + testDir + "/return.rb"}, t, noopHandler)
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H2RespPhaseReturn",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("status = %v; want %v", got, want)
}
hdtests := []struct {
k, v string
}{
{"content-length", "11"},
{"from", "mruby"},
}
for _, tt := range hdtests {
if got, want := res.header.Get(tt.k), tt.v; got != want {
t.Errorf("%v = %v; want %v", tt.k, got, want)
}
}
if got, want := string(res.body), "Hello World"; got != want {
t.Errorf("body = %v; want %v", got, want)
}
}

View File

@@ -0,0 +1,3 @@
Nghttpx.run do |env|
env.req.set_header "User-Agent", "mruby"
end

View File

@@ -0,0 +1,3 @@
Nghttpx.run do |env|
env.resp.set_header "Alpha", "bravo"
end

View File

@@ -0,0 +1,8 @@
Nghttpx.run do |env|
resp = env.resp
resp.clear_headers
resp.status = 404
resp.add_header "from", "mruby"
resp.return "Hello World"
end

View File

@@ -9,7 +9,8 @@ import (
"github.com/bradfitz/http2"
"github.com/bradfitz/http2/hpack"
"github.com/tatsuhiro-t/go-nghttp2"
"golang.org/x/net/spdy"
"github.com/tatsuhiro-t/spdy"
"golang.org/x/net/websocket"
"io"
"io/ioutil"
"net"
@@ -66,6 +67,10 @@ func newServerTester(args []string, t *testing.T, handler http.HandlerFunc) *ser
return newServerTesterInternal(args, t, handler, false, nil)
}
func newServerTesterHandler(args []string, t *testing.T, handler http.Handler) *serverTester {
return newServerTesterInternal(args, t, handler, false, nil)
}
// newServerTester creates test context for TLS frontend connection.
func newServerTesterTLS(args []string, t *testing.T, handler http.HandlerFunc) *serverTester {
return newServerTesterInternal(args, t, handler, true, nil)
@@ -79,7 +84,7 @@ func newServerTesterTLSConfig(args []string, t *testing.T, handler http.HandlerF
// newServerTesterInternal creates test context. If frontendTLS is
// true, set up TLS frontend connection.
func newServerTesterInternal(args []string, t *testing.T, handler http.HandlerFunc, frontendTLS bool, clientConfig *tls.Config) *serverTester {
func newServerTesterInternal(args []string, t *testing.T, handler http.Handler, frontendTLS bool, clientConfig *tls.Config) *serverTester {
ts := httptest.NewUnstartedServer(handler)
backendTLS := false
@@ -247,15 +252,16 @@ func (st *serverTester) readSpdyFrame() (spdy.Frame, error) {
}
type requestParam struct {
name string // name for this request to identify the request in log easily
streamID uint32 // stream ID, automatically assigned if 0
method string // method, defaults to GET
scheme string // scheme, defaults to http
authority string // authority, defaults to backend server address
path string // path, defaults to /
header []hpack.HeaderField // additional request header fields
body []byte // request body
trailer []hpack.HeaderField // trailer part
name string // name for this request to identify the request in log easily
streamID uint32 // stream ID, automatically assigned if 0
method string // method, defaults to GET
scheme string // scheme, defaults to http
authority string // authority, defaults to backend server address
path string // path, defaults to /
header []hpack.HeaderField // additional request header fields
body []byte // request body
trailer []hpack.HeaderField // trailer part
httpUpgrade bool // true if upgraded to HTTP/2 through HTTP Upgrade
}
// wrapper for request body to set trailer part
@@ -278,6 +284,41 @@ func (cbr *chunkedBodyReader) Read(p []byte) (n int, err error) {
return cbr.body.Read(p)
}
func (st *serverTester) websocket(rp requestParam) (*serverResponse, error) {
urlstring := st.url + "/echo"
config, err := websocket.NewConfig(urlstring, st.url)
if err != nil {
st.t.Fatalf("websocket.NewConfig(%q, %q) returned error: %v", urlstring, st.url, err)
}
config.Header.Add("Test-Case", rp.name)
for _, h := range rp.header {
config.Header.Add(h.Name, h.Value)
}
ws, err := websocket.NewClient(config, st.conn)
if err != nil {
st.t.Fatalf("Error creating websocket client: %v", err)
}
if _, err := ws.Write(rp.body); err != nil {
st.t.Fatalf("ws.Write() returned error: %v", err)
}
msg := make([]byte, 1024)
var n int
if n, err = ws.Read(msg); err != nil {
st.t.Fatalf("ws.Read() returned error: %v", err)
}
res := &serverResponse{
body: msg[:n],
}
return res, nil
}
func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
method := "GET"
if rp.method != "" {
@@ -296,7 +337,19 @@ func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
body = cbr
}
}
req, err := http.NewRequest(method, st.url, body)
reqURL := st.url
if rp.path != "" {
u, err := url.Parse(st.url)
if err != nil {
st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err)
}
u.Path = rp.path
reqURL = u.String()
}
req, err := http.NewRequest(method, reqURL, body)
if err != nil {
return nil, err
}
@@ -478,69 +531,70 @@ func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
streams := make(map[uint32]*serverResponse)
streams[id] = res
method := "GET"
if rp.method != "" {
method = rp.method
}
_ = st.enc.WriteField(pair(":method", method))
scheme := "http"
if rp.scheme != "" {
scheme = rp.scheme
}
_ = st.enc.WriteField(pair(":scheme", scheme))
authority := st.authority
if rp.authority != "" {
authority = rp.authority
}
_ = st.enc.WriteField(pair(":authority", authority))
path := "/"
if rp.path != "" {
path = rp.path
}
_ = st.enc.WriteField(pair(":path", path))
_ = st.enc.WriteField(pair("test-case", rp.name))
for _, h := range rp.header {
_ = st.enc.WriteField(h)
}
err := st.fr.WriteHeaders(http2.HeadersFrameParam{
StreamID: id,
EndStream: len(rp.body) == 0 && len(rp.trailer) == 0,
EndHeaders: true,
BlockFragment: st.headerBlkBuf.Bytes(),
})
if err != nil {
return nil, err
}
if len(rp.body) != 0 {
// TODO we assume rp.body fits in 1 frame
if err := st.fr.WriteData(id, len(rp.trailer) == 0, rp.body); err != nil {
return nil, err
if !rp.httpUpgrade {
method := "GET"
if rp.method != "" {
method = rp.method
}
}
_ = st.enc.WriteField(pair(":method", method))
if len(rp.trailer) != 0 {
st.headerBlkBuf.Reset()
for _, h := range rp.trailer {
scheme := "http"
if rp.scheme != "" {
scheme = rp.scheme
}
_ = st.enc.WriteField(pair(":scheme", scheme))
authority := st.authority
if rp.authority != "" {
authority = rp.authority
}
_ = st.enc.WriteField(pair(":authority", authority))
path := "/"
if rp.path != "" {
path = rp.path
}
_ = st.enc.WriteField(pair(":path", path))
_ = st.enc.WriteField(pair("test-case", rp.name))
for _, h := range rp.header {
_ = st.enc.WriteField(h)
}
err := st.fr.WriteHeaders(http2.HeadersFrameParam{
StreamID: id,
EndStream: true,
EndStream: len(rp.body) == 0 && len(rp.trailer) == 0,
EndHeaders: true,
BlockFragment: st.headerBlkBuf.Bytes(),
})
if err != nil {
return nil, err
}
}
if len(rp.body) != 0 {
// TODO we assume rp.body fits in 1 frame
if err := st.fr.WriteData(id, len(rp.trailer) == 0, rp.body); err != nil {
return nil, err
}
}
if len(rp.trailer) != 0 {
st.headerBlkBuf.Reset()
for _, h := range rp.trailer {
_ = st.enc.WriteField(h)
}
err := st.fr.WriteHeaders(http2.HeadersFrameParam{
StreamID: id,
EndStream: true,
EndHeaders: true,
BlockFragment: st.headerBlkBuf.Bytes(),
})
if err != nil {
return nil, err
}
}
}
loop:
for {
fr, err := st.readFrame()

3
lib/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
# generated files
includes/nghttp2/nghttp2ver.h
libnghttp2.pc

View File

@@ -25,7 +25,8 @@ SUBDIRS = includes
EXTRA_DIST = Makefile.msvc
AM_CFLAGS = $(WARNCFLAGS)
AM_CPPFLAGS = -I$(srcdir)/includes -I$(builddir)/includes @DEFS@
AM_CPPFLAGS = -I$(srcdir)/includes -I$(builddir)/includes -DBUILDING_NGHTTP2 \
@DEFS@
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libnghttp2.pc

View File

@@ -2,81 +2,106 @@
# GNU Makefile for nghttp2 / MSVC.
#
# By G. Vanem <gvanem@yahoo.no> 2013
# Updated 3/2015 by Remo Eichenberger @remoe
# The MIT License apply.
#
#
# Choose your weapons:
# Set 'ZLIB_ROOT' to the root of zlib.
# Set 'USE_CYTHON=1' to build and install the 'nghttp2.pyd' Python extension.
#
ZLIB_ROOT = g:/MingW32/src/Compression/zlib-1.2.8
USE_CYTHON = 1
THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST))
_VERSION := $(shell grep AC_INIT ../configure.ac | cut -d'[' -f3 | sed -e 's/-DEV], //g')
_VERSION := $(subst ., ,$(_VERSION))
VER_MAJOR = $(word 1,$(_VERSION))
VER_MINOR = $(word 2,$(_VERSION))
VER_MICRO = $(word 3,$(_VERSION))
VERSION = $(VER_MAJOR).$(VER_MINOR).$(VER_MICRO)
VERSION_NUM = ($(VER_MAJOR) << 16) + ($(VER_MINOR) << 8) + $(VER_MICRO)
USE_CYTHON := 1
#USE_CYTHON := 0
GENERATED = 'Generated by $(realpath Makefile.MSVC)'
_VERSION := $(shell grep AC_INIT ../configure.ac | cut -d'[' -f3 | sed -e 's/-DEV], //g')
_VERSION := $(subst ., ,$(_VERSION))
VER_MAJOR := $(word 1,$(_VERSION))
VER_MINOR := $(word 2,$(_VERSION))
VER_MICRO := $(word 3,$(_VERSION))
VERSION := $(VER_MAJOR).$(VER_MINOR).$(VER_MICRO)
VERSION_NUM := ($(VER_MAJOR) << 16) + ($(VER_MINOR) << 8) + $(VER_MICRO)
GENERATED := 'Generated by $(realpath Makefile.MSVC)'
OBJ_DIR := MSVC_obj
#SUFFIX :=-vc90-mt-x86
#
# Where to copy nghttp2.dll + lib + headers to.
# Note: 'make install' is not in default targets. Do it explicitly.
#
VC_ROOT = $(realpath $(VCINSTALLDIR))
INSTALL_BIN = $(VC_ROOT)/bin
INSTALL_LIB = $(VC_ROOT)/lib
INSTALL_HDR = $(VC_ROOT)/include
TARGET_DIR ?= ../_VC_ROOT
VC_ROOT := $(abspath $(TARGET_DIR))
INSTALL_BIN := $(VC_ROOT)/bin
INSTALL_LIB := $(VC_ROOT)/lib
INSTALL_HDR := $(VC_ROOT)/include
DLL_R := $(OBJ_DIR)/nghttp2$(SUFFIX).dll
DLL_D := $(OBJ_DIR)/nghttp2d$(SUFFIX).dll
LIB_R := $(OBJ_DIR)/nghttp2-static.lib
LIB_D := $(OBJ_DIR)/nghttp2d-static.lib
IMP_R := $(OBJ_DIR)/nghttp2.lib
IMP_D := $(OBJ_DIR)/nghttp2d.lib
#
# Build for DEBUG-model and RELEASE at the same time.
#
TARGETS = nghttp2.lib nghttp2.dll nghttp2_imp.lib \
nghttp2d.lib nghttp2d.dll nghttp2d_imp.lib
TARGETS := $(LIB_R) $(DLL_R) $(IMP_R) \
$(LIB_D) $(DLL_D) $(IMP_D)
EXT_LIBS = $(ZLIB_ROOT)/zlib.lib ws2_32.lib
EXT_LIBS =
OBJ_DIR = MSVC_obj
NGHTTP2_PDB_R = $(OBJ_DIR)/nghttp2.pdb
NGHTTP2_PDB_D = $(OBJ_DIR)/nghttp2d.pdb
NGHTTP2_PDB_R := $(OBJ_DIR)/nghttp2.pdb
NGHTTP2_PDB_D := $(OBJ_DIR)/nghttp2d.pdb
CC = cl
CFLAGS = -I./includes -I$(ZLIB_ROOT) -DHAVE_WINSOCK2_H -Dssize_t=long
LD := link
AR := lib
#CC := icl
#LD := xilink
#AR := xilib
RC := rc
CFLAGS := -I./includes -Dssize_t=long -D_U_=""
CFLAGS_R = -nologo -MD -W3 -Zi -Fd./$(NGHTTP2_PDB_R)
CFLAGS_D = -nologo -MDd -W3 -Zi -Fd./$(NGHTTP2_PDB_D) \
CFLAGS_R := -nologo -MD -W3 -Z7 -DBUILDING_NGHTTP2
CFLAGS_D := -nologo -MDd -W3 -Z7 -DBUILDING_NGHTTP2 \
-Ot -D_DEBUG -GF -RTCs -RTCu # -RTCc -GS
LDFLAGS = -nologo -machine:i386 -map -debug -incremental:no # -verbose
LDFLAGS := -nologo -MAP -debug -incremental:no -opt:ref,icf -MANIFEST # -verbose
NGHTTP2_SRC = nghttp2_buf.c \
nghttp2_callbacks.c \
nghttp2_frame.c \
nghttp2_helper.c \
nghttp2_hd.c \
nghttp2_hd_huffman.c \
nghttp2_hd_huffman_data.c \
nghttp2_map.c \
nghttp2_npn.c \
nghttp2_option.c \
nghttp2_outbound_item.c \
nghttp2_priority_spec.c \
nghttp2_pq.c \
nghttp2_queue.c \
nghttp2_session.c \
nghttp2_stream.c \
nghttp2_submit.c \
nghttp2_version.c
NGHTTP2_OBJ_R = $(addprefix $(OBJ_DIR)/r_, $(notdir $(NGHTTP2_SRC:.c=.obj)))
NGHTTP2_OBJ_D = $(addprefix $(OBJ_DIR)/d_, $(notdir $(NGHTTP2_SRC:.c=.obj)))
NGHTTP2_SRC := nghttp2_pq.c \
nghttp2_map.c \
nghttp2_queue.c \
nghttp2_frame.c \
nghttp2_buf.c \
nghttp2_stream.c \
nghttp2_outbound_item.c \
nghttp2_session.c \
nghttp2_submit.c \
nghttp2_helper.c \
nghttp2_npn.c \
nghttp2_hd.c \
nghttp2_hd_huffman.c \
nghttp2_hd_huffman_data.c \
nghttp2_version.c \
nghttp2_priority_spec.c \
nghttp2_option.c \
nghttp2_callbacks.c \
nghttp2_mem.c \
nghttp2_http.c
all: intro $(OBJ_DIR) $(TARGETS)
NGHTTP2_OBJ_R := $(addprefix $(OBJ_DIR)/r_, $(notdir $(NGHTTP2_SRC:.c=.obj)))
NGHTTP2_OBJ_D := $(addprefix $(OBJ_DIR)/d_, $(notdir $(NGHTTP2_SRC:.c=.obj)))
.PHONY: all intro test_ver install copy_headers_and_libs \
install_nghttp2_pyd_0 install_nghttp2_pyd_1 \
build_nghttp2_pyd_0 build_nghttp2_pyd_1 \
clean_nghttp2_pyd_0 clean_nghttp2_pyd_1
all: intro $(OBJ_DIR) $(TARGETS) build_nghttp2_pyd_$(USE_CYTHON)
@echo 'Welcome to NgHTTP2 (release + debug).'
@echo 'Do a "make -f Makefile.MSVC install" at own risk!'
@@ -94,73 +119,88 @@ $(OBJ_DIR):
- mkdir $(OBJ_DIR)
install: includes/nghttp2/nghttp2.h includes/nghttp2/nghttp2ver.h \
nghttp2.dll nghttp2.lib nghttp2_imp.lib \
nghttp2d.dll nghttp2d.lib nghttp2d_imp.lib \
copy_headers_and_libs install_nghttp2_pyd_$(USE_CYTHON)
$(TARGETS) \
copy_headers_and_libs install_nghttp2_pyd_$(USE_CYTHON)
#
# This MUST be done before using the 'install_nghttp2_pyd_1' rule.
#
copy_headers_and_libs:
- mkdir $(INSTALL_HDR)/nghttp2
- mkdir -p $(INSTALL_HDR)/nghttp2 $(INSTALL_BIN) $(INSTALL_LIB)
cp --update $(addprefix includes/nghttp2/, nghttp2.h nghttp2ver.h) $(INSTALL_HDR)/nghttp2
cp --update nghttp2.dll nghttp2d.dll $(NGHTTP2_PDB_R) $(NGHTTP2_PDB_D) $(INSTALL_BIN)
cp --update nghttp2.lib nghttp2d.lib nghttp2_imp.lib nghttp2d_imp.lib $(INSTALL_LIB)
cp --update $(DLL_R) $(DLL_D) $(NGHTTP2_PDB_R) $(NGHTTP2_PDB_D) $(INSTALL_BIN)
cp --update $(IMP_R) $(IMP_D) $(LIB_R) $(LIB_D) $(INSTALL_LIB)
@echo
nghttp2.lib: $(NGHTTP2_OBJ_R)
lib -nologo -out:$@ $^
$(LIB_R): $(NGHTTP2_OBJ_R)
$(AR) -nologo -out:$@ $^
@echo
nghttp2d.lib: $(NGHTTP2_OBJ_D)
lib -nologo -out:$@ $^
$(LIB_D): $(NGHTTP2_OBJ_D)
$(AR) -nologo -out:$@ $^
@echo
nghttp2.dll nghttp2_imp.lib: $(NGHTTP2_OBJ_R) $(OBJ_DIR)/r_nghttp2.res $(OBJ_DIR)/r_nghttp2.def
link $(LDFLAGS) -dll -out:nghttp2.dll -implib:nghttp2_imp.lib -def:$(OBJ_DIR)/r_nghttp2.def \
$(NGHTTP2_OBJ_R) $(OBJ_DIR)/r_nghttp2.res $(EXT_LIBS)
$(IMP_R): $(DLL_R)
$(DLL_R): $(NGHTTP2_OBJ_R) $(OBJ_DIR)/r_nghttp2.res
$(LD) $(LDFLAGS) -dll -out:$@ -implib:$(IMP_R) $(NGHTTP2_OBJ_R) -PDB:$(NGHTTP2_PDB_R) $(OBJ_DIR)/r_nghttp2.res $(EXT_LIBS)
mt -nologo -manifest $@.manifest -outputresource:$@\;2
@echo
nghttp2d.dll nghttp2d_imp.lib: $(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res $(OBJ_DIR)/d_nghttp2.def
link $(LDFLAGS) -dll -out:nghttp2d.dll -implib:nghttp2d_imp.lib -def:$(OBJ_DIR)/d_nghttp2.def \
$(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res $(EXT_LIBS)
$(IMP_D): $(DLL_D)
$(DLL_D): $(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res
$(LD) $(LDFLAGS) -dll -out:$@ -implib:$(IMP_D) $(NGHTTP2_OBJ_D) -PDB:$(NGHTTP2_PDB_D) $(OBJ_DIR)/d_nghttp2.res $(EXT_LIBS)
mt -nologo -manifest $@.manifest -outputresource:$@\;2
@echo
install_nghttp2_pyd_0: ;
install_nghttp2_pyd_1: $(addprefix ../python/, setup.py.in nghttp2.pyx)
WIN_OBJDIR:=$(shell cygpath -w $(abspath $(OBJ_DIR)))
WIN_OBJDIR:=$(subst \,/,$(WIN_OBJDIR))
../python/setup.py: ../python/setup.py.in $(THIS_MAKEFILE)
cd ../python ; \
echo '# $(GENERATED). DO NOT EDIT.' > setup.py ; \
sed -e 's/@top_srcdir@/../' \
-e 's/@top_builddir@/../' \
-e 's/@PACKAGE_VERSION@/$(VERSION)/' setup.py.in >> setup.py ; \
cython -v nghttp2.pyx ; \
python setup.py install
-e 's%@top_builddir@%$(WIN_OBJDIR)%' \
-e 's/@PACKAGE_VERSION@/$(VERSION)/' setup.py.in >> setup.py ;
build_nghttp2_pyd_0: ;
build_nghttp2_pyd_1: $(addprefix ../python/, setup.py nghttp2.pyx)
cd ../python ; \
python setup.py build_ext -i -f bdist_wininst
install_nghttp2_pyd_0: ;
install_nghttp2_pyd_1: $(addprefix ../python/, setup.py nghttp2.pyx)
cd ../python ; \
pip install .
clean_nghttp2_pyd_0: ;
clean_nghttp2_pyd_1:
cd ../python ; \
rm -f setup.py nghttp2.c ; \
rm -fR build/*
rm -fR build dist
$(OBJ_DIR)/r_%.obj: %.c
$(OBJ_DIR)/r_%.obj: %.c $(THIS_MAKEFILE)
$(CC) $(CFLAGS_R) $(CFLAGS) -Fo$@ -c $<
@echo
$(OBJ_DIR)/d_%.obj: %.c
$(OBJ_DIR)/d_%.obj: %.c $(THIS_MAKEFILE)
$(CC) $(CFLAGS_D) $(CFLAGS) -Fo$@ -c $<
@echo
$(OBJ_DIR)/r_nghttp2.res: nghttp2.rc
rc -nologo -D_RELEASE -Fo $@ $<
$(OBJ_DIR)/r_nghttp2.res: $(OBJ_DIR)/nghttp2.rc $(THIS_MAKEFILE)
$(RC) -nologo -D_RELEASE -Fo $@ $<
@echo
$(OBJ_DIR)/d_nghttp2.res: nghttp2.rc
rc -nologo -D_DEBUG -Fo $@ $<
$(OBJ_DIR)/d_nghttp2.res: $(OBJ_DIR)/nghttp2.rc $(THIS_MAKEFILE)
$(RC) -nologo -D_DEBUG -Fo $@ $<
@echo
includes/nghttp2/nghttp2ver.h: includes/nghttp2/nghttp2ver.h.in
includes/nghttp2/nghttp2ver.h: includes/nghttp2/nghttp2ver.h.in $(THIS_MAKEFILE)
sed < includes/nghttp2/nghttp2ver.h.in \
-e 's/@PACKAGE_VERSION@/$(VERSION)/g' \
-e 's/@PACKAGE_VERSION_NUM@/($(VERSION_NUM))/g' > $@
@@ -200,8 +240,6 @@ define RES_FILE
VALUE "OriginalFilename", "nghttp2" DBG ".dll"
VALUE "ProductName", "NGHTTP2."
VALUE "ProductVersion", VER_STR
VALUE "PrivateBuild", "The privat build of <gvanem@yahoo.no>."
VALUE "SpecialBuild", ""
END
END
BLOCK "VarFileInfo"
@@ -213,38 +251,19 @@ endef
export RES_FILE
nghttp2.rc: Makefile.MSVC
$(OBJ_DIR)/nghttp2.rc: Makefile.MSVC
@echo 'Generating $@...'
@echo ' /* $(GENERATED). DO NOT EDIT.' > $@
@echo ' */' >> $@
@echo "$$RES_FILE" >> $@
$(OBJ_DIR)/r_nghttp2.def: Makefile.MSVC
@echo 'Generating $@...'
@echo '; $(GENERATED). DO NOT EDIT.' > $@
@echo ';' >> $@
@echo 'LIBRARY nghttp2.dll' >> $@
@echo 'EXPORTS' >> $@
nm $(NGHTTP2_OBJ_R) | grep ' T .*_nghttp2' | sed 's/^.* _/ /' >> $@
@echo 'NGHTTP2_STATIC_TABLE_LENGTH DATA' >> $@
$(OBJ_DIR)/d_nghttp2.def: Makefile.MSVC
@echo 'Generating $@...'
@echo '; $(GENERATED). DO NOT EDIT.' > $@
@echo ';' >> $@
@echo 'LIBRARY nghttp2d.dll' >> $@
@echo 'EXPORTS' >> $@
nm $(NGHTTP2_OBJ_D) | grep ' T .*_nghttp2' | sed 's/^.* _/ /' >> $@
@echo 'NGHTTP2_STATIC_TABLE_LENGTH DATA' >> $@
clean:
rm -f $(OBJ_DIR)/* nghttp2_imp.exp nghttp2_imp.exp \
nghttp2.map nghttp2d.map nghttp2.rc includes/nghttp2/nghttp2ver.h
rm -f $(OBJ_DIR)/* includes/nghttp2/nghttp2ver.h
@echo
vclean realclean: clean clean_nghttp2_pyd_$(USE_CYTHON)
rm -f $(TARGETS) nghttp2.pdb nghttp2d.pdb nghttp2_imp.exp nghttp2d_imp.exp .depend.MSVC
- rmdir $(OBJ_DIR)
- rm -rf $(OBJ_DIR)
- rm -f .depend.MSVC
#
# Use gcc to generated the dependencies. No MSVC specific args please!
@@ -263,4 +282,4 @@ depend: includes/nghttp2/nghttp2ver.h
sed -e $(REPLACE_D) .depend.tmp >> .depend.MSVC
rm -f .depend.tmp
-include .depend.MSVC
-include .depend.MSVC

File diff suppressed because it is too large Load Diff

View File

@@ -320,7 +320,7 @@ int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len) {
}
buf->last = nghttp2_cpymem(buf->last, p, nwrite);
p += len;
p += nwrite;
len -= nwrite;
}
@@ -432,6 +432,24 @@ ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
return (ssize_t)len;
}
size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out) {
size_t len;
nghttp2_buf_chain *chain;
nghttp2_buf *buf;
nghttp2_buf resbuf;
len = nghttp2_bufs_len(bufs);
nghttp2_buf_wrap_init(&resbuf, out, len);
for (chain = bufs->head; chain; chain = chain->next) {
buf = &chain->buf;
resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
}
return len;
}
void nghttp2_bufs_reset(nghttp2_bufs *bufs) {
nghttp2_buf_chain *chain, *ci;
size_t k;

View File

@@ -324,6 +324,17 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
*/
ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out);
/*
* Copies all data stored in |bufs| to |out|. This function assumes
* that the buffer space pointed by |out| has at least
* nghttp2_bufs(bufs) bytes.
*
* The contents of |bufs| is left unchanged.
*
* This function returns the length of copied data.
*/
size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out);
/*
* Resets |bufs| and makes the buffers empty.
*/

View File

@@ -121,3 +121,9 @@ void nghttp2_session_callbacks_set_on_begin_frame_callback(
nghttp2_on_begin_frame_callback on_begin_frame_callback) {
cbs->on_begin_frame_callback = on_begin_frame_callback;
}
void nghttp2_session_callbacks_set_send_data_callback(
nghttp2_session_callbacks *cbs,
nghttp2_send_data_callback send_data_callback) {
cbs->send_data_callback = send_data_callback;
}

View File

@@ -106,6 +106,7 @@ struct nghttp2_session_callbacks {
* Sets callback function invoked when a frame header is received.
*/
nghttp2_on_begin_frame_callback on_begin_frame_callback;
nghttp2_send_data_callback send_data_callback;
};
#endif /* NGHTTP2_CALLBACKS_H */

View File

@@ -784,9 +784,6 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv) {
for (i = 0; i < niv; ++i) {
switch (iv[i].settings_id) {
case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
if (iv[i].value > NGHTTP2_MAX_HEADER_TABLE_SIZE) {
return 0;
}
break;
case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
break;
@@ -813,7 +810,7 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv) {
return 1;
}
static void frame_set_pad(nghttp2_buf *buf, size_t padlen) {
static void frame_set_pad(nghttp2_buf *buf, size_t padlen, int framehd_only) {
size_t trail_padlen;
size_t newlen;
@@ -828,6 +825,10 @@ static void frame_set_pad(nghttp2_buf *buf, size_t padlen) {
newlen = (nghttp2_get_uint32(buf->pos) >> 8) + padlen;
nghttp2_put_uint32be(buf->pos, (uint32_t)((newlen << 8) + buf->pos[3]));
if (framehd_only) {
return;
}
trail_padlen = padlen - 1;
buf->pos[NGHTTP2_FRAME_HDLEN] = trail_padlen;
@@ -836,12 +837,10 @@ static void frame_set_pad(nghttp2_buf *buf, size_t padlen) {
/* extend buffers trail_padlen bytes, since we ate previous padlen -
trail_padlen byte(s) */
buf->last += trail_padlen;
return;
}
int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
size_t padlen) {
size_t padlen, int framehd_only) {
nghttp2_buf *buf;
if (padlen == 0) {
@@ -874,7 +873,7 @@ int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
assert(nghttp2_buf_avail(buf) >= (ssize_t)padlen - 1);
frame_set_pad(buf, padlen);
frame_set_pad(buf, padlen, framehd_only);
hd->length += padlen;
hd->flags |= NGHTTP2_FLAG_PADDED;

View File

@@ -65,9 +65,6 @@
/* The number of bytes for each SETTINGS entry */
#define NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH 6
/* The maximum header table size in SETTINGS_HEADER_TABLE_SIZE */
#define NGHTTP2_MAX_HEADER_TABLE_SIZE ((1u << 31) - 1)
/* Length of priority related fields in HEADERS/PRIORITY frames */
#define NGHTTP2_PRIORITY_SPECLEN 5
@@ -75,7 +72,7 @@
#define NGHTTP2_MAX_PADLEN 256
/* Union of extension frame payload */
typedef union { nghttp2_ext_altsvc altsvc; } nghttp2_ext_frame_payload;
typedef union { int dummy; } nghttp2_ext_frame_payload;
void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd);
@@ -510,7 +507,8 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
* Sets Pad Length field and flags and adjusts frame header position
* of each buffers in |bufs|. The number of padding is given in the
* |padlen| including Pad Length field. The |hd| is the frame header
* for the serialized data.
* for the serialized data. This function fills zeros padding region
* unless framehd_only is nonzero.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
@@ -521,6 +519,6 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
* The length of the resulting frame is too large.
*/
int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
size_t padlen);
size_t padlen, int framehd_only);
#endif /* NGHTTP2_FRAME_H */

File diff suppressed because it is too large Load Diff

View File

@@ -49,7 +49,68 @@
#define NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE (1 << 12)
/* Exported for unit test */
extern const size_t NGHTTP2_STATIC_TABLE_LENGTH;
#define NGHTTP2_STATIC_TABLE_LENGTH 61
/* Generated by genlibtokenlookup.py */
typedef enum {
NGHTTP2_TOKEN__AUTHORITY = 0,
NGHTTP2_TOKEN__METHOD = 1,
NGHTTP2_TOKEN__PATH = 3,
NGHTTP2_TOKEN__SCHEME = 5,
NGHTTP2_TOKEN__STATUS = 7,
NGHTTP2_TOKEN_ACCEPT_CHARSET = 14,
NGHTTP2_TOKEN_ACCEPT_ENCODING = 15,
NGHTTP2_TOKEN_ACCEPT_LANGUAGE = 16,
NGHTTP2_TOKEN_ACCEPT_RANGES = 17,
NGHTTP2_TOKEN_ACCEPT = 18,
NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN = 19,
NGHTTP2_TOKEN_AGE = 20,
NGHTTP2_TOKEN_ALLOW = 21,
NGHTTP2_TOKEN_AUTHORIZATION = 22,
NGHTTP2_TOKEN_CACHE_CONTROL = 23,
NGHTTP2_TOKEN_CONTENT_DISPOSITION = 24,
NGHTTP2_TOKEN_CONTENT_ENCODING = 25,
NGHTTP2_TOKEN_CONTENT_LANGUAGE = 26,
NGHTTP2_TOKEN_CONTENT_LENGTH = 27,
NGHTTP2_TOKEN_CONTENT_LOCATION = 28,
NGHTTP2_TOKEN_CONTENT_RANGE = 29,
NGHTTP2_TOKEN_CONTENT_TYPE = 30,
NGHTTP2_TOKEN_COOKIE = 31,
NGHTTP2_TOKEN_DATE = 32,
NGHTTP2_TOKEN_ETAG = 33,
NGHTTP2_TOKEN_EXPECT = 34,
NGHTTP2_TOKEN_EXPIRES = 35,
NGHTTP2_TOKEN_FROM = 36,
NGHTTP2_TOKEN_HOST = 37,
NGHTTP2_TOKEN_IF_MATCH = 38,
NGHTTP2_TOKEN_IF_MODIFIED_SINCE = 39,
NGHTTP2_TOKEN_IF_NONE_MATCH = 40,
NGHTTP2_TOKEN_IF_RANGE = 41,
NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE = 42,
NGHTTP2_TOKEN_LAST_MODIFIED = 43,
NGHTTP2_TOKEN_LINK = 44,
NGHTTP2_TOKEN_LOCATION = 45,
NGHTTP2_TOKEN_MAX_FORWARDS = 46,
NGHTTP2_TOKEN_PROXY_AUTHENTICATE = 47,
NGHTTP2_TOKEN_PROXY_AUTHORIZATION = 48,
NGHTTP2_TOKEN_RANGE = 49,
NGHTTP2_TOKEN_REFERER = 50,
NGHTTP2_TOKEN_REFRESH = 51,
NGHTTP2_TOKEN_RETRY_AFTER = 52,
NGHTTP2_TOKEN_SERVER = 53,
NGHTTP2_TOKEN_SET_COOKIE = 54,
NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY = 55,
NGHTTP2_TOKEN_TRANSFER_ENCODING = 56,
NGHTTP2_TOKEN_USER_AGENT = 57,
NGHTTP2_TOKEN_VARY = 58,
NGHTTP2_TOKEN_VIA = 59,
NGHTTP2_TOKEN_WWW_AUTHENTICATE = 60,
NGHTTP2_TOKEN_TE,
NGHTTP2_TOKEN_CONNECTION,
NGHTTP2_TOKEN_KEEP_ALIVE,
NGHTTP2_TOKEN_PROXY_CONNECTION,
NGHTTP2_TOKEN_UPGRADE
} nghttp2_token;
typedef enum {
NGHTTP2_HD_FLAG_NONE = 0,
@@ -67,18 +128,14 @@ typedef enum {
typedef struct {
nghttp2_nv nv;
uint32_t name_hash;
uint32_t value_hash;
/* nghttp2_token value for nv.name. It could be -1 if we have no
token for that header field name. */
int token;
/* Reference count */
uint8_t ref;
uint8_t flags;
} nghttp2_hd_entry;
typedef struct {
nghttp2_hd_entry ent;
size_t index;
} nghttp2_hd_static_entry;
typedef struct {
nghttp2_hd_entry **buffer;
size_t mask;
@@ -94,6 +151,8 @@ typedef enum {
} nghttp2_hd_opcode;
typedef enum {
NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE,
NGHTTP2_HD_STATE_INFLATE_START,
NGHTTP2_HD_STATE_OPCODE,
NGHTTP2_HD_STATE_READ_TABLE_SIZE,
NGHTTP2_HD_STATE_READ_INDEX,
@@ -107,6 +166,12 @@ typedef enum {
NGHTTP2_HD_STATE_READ_VALUE
} nghttp2_hd_inflate_state;
typedef enum {
NGHTTP2_HD_WITH_INDEXING,
NGHTTP2_HD_WITHOUT_INDEXING,
NGHTTP2_HD_NEVER_INDEXING
} nghttp2_hd_indexing_mode;
typedef struct {
/* dynamic header table */
nghttp2_hd_ringbuf hd_table;
@@ -176,9 +241,8 @@ struct nghttp2_hd_inflater {
* set in the |flags|, the content pointed by the |name| with length
* |namelen| is copied. Likewise, if NGHTTP2_HD_FLAG_VALUE_ALLOC bit
* set in the |flags|, the content pointed by the |value| with length
* |valuelen| is copied. The |name_hash| and |value_hash| are hash
* value for |name| and |value| respectively. The hash function is
* defined in nghttp2_hd.c.
* |valuelen| is copied. The |token| is enum number looked up by
* |name|. It could be -1 if we don't have that enum value.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
@@ -188,8 +252,7 @@ struct nghttp2_hd_inflater {
*/
int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name,
size_t namelen, uint8_t *value, size_t valuelen,
uint32_t name_hash, uint32_t value_hash,
nghttp2_mem *mem);
int token, nghttp2_mem *mem);
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent, nghttp2_mem *mem);
@@ -271,20 +334,32 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem);
*/
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater);
/*
* Similar to nghttp2_hd_inflate_hd(), but this takes additional
* output parameter |token|. On successful header emission, it
* contains nghttp2_token value for nv_out->name. It could be -1 if
* we don't have enum value for the name. Other than that return
* values and semantics are the same as nghttp2_hd_inflate_hd().
*/
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
nghttp2_nv *nv_out, int *inflate_flags,
int *token, uint8_t *in, size_t inlen,
int in_final);
/* For unittesting purpose */
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,
nghttp2_nv *nv, int inc_indexing);
nghttp2_nv *nv, int indexing_mode);
/* For unittesting purpose */
int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
int inc_indexing);
int indexing_mode);
/* For unittesting purpose */
int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size);
/* For unittesting purpose */
nghttp2_hd_entry *nghttp2_hd_table_get(nghttp2_hd_context *context,
size_t index);
NGHTTP2_EXTERN nghttp2_hd_entry *
nghttp2_hd_table_get(nghttp2_hd_context *context, size_t index);
/* For unittesting purpose */
ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *final,

View File

@@ -168,10 +168,27 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
ctx->accept = 1;
}
/* Use macro to make the code simpler..., but error case is tricky.
We spent most of the CPU in decoding, so we are doing this
thing. */
#define hd_huff_decode_sym_emit(bufs, sym, avail) \
do { \
if ((avail)) { \
nghttp2_bufs_fast_addb((bufs), (sym)); \
--(avail); \
} else { \
rv = nghttp2_bufs_addb((bufs), (sym)); \
if (rv != 0) { \
return rv; \
} \
(avail) = nghttp2_bufs_cur_avail((bufs)); \
} \
} while (0)
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
nghttp2_bufs *bufs, const uint8_t *src,
size_t srclen, int final) {
size_t i, j;
size_t i;
int rv;
size_t avail;
@@ -180,30 +197,28 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
/* We use the decoding algorithm described in
http://graphics.ics.uci.edu/pub/Prefix.pdf */
for (i = 0; i < srclen; ++i) {
uint8_t in = src[i] >> 4;
for (j = 0; j < 2; ++j) {
const nghttp2_huff_decode *t;
const nghttp2_huff_decode *t;
t = &huff_decode_table[ctx->state][in];
if (t->flags & NGHTTP2_HUFF_FAIL) {
return NGHTTP2_ERR_HEADER_COMP;
}
if (t->flags & NGHTTP2_HUFF_SYM) {
if (avail) {
nghttp2_bufs_fast_addb(bufs, t->sym);
--avail;
} else {
rv = nghttp2_bufs_addb(bufs, t->sym);
if (rv != 0) {
return rv;
}
avail = nghttp2_bufs_cur_avail(bufs);
}
}
ctx->state = t->state;
ctx->accept = (t->flags & NGHTTP2_HUFF_ACCEPTED) != 0;
in = src[i] & 0xf;
t = &huff_decode_table[ctx->state][src[i] >> 4];
if (t->flags & NGHTTP2_HUFF_FAIL) {
return NGHTTP2_ERR_HEADER_COMP;
}
if (t->flags & NGHTTP2_HUFF_SYM) {
/* this is macro, and may return from this function on error */
hd_huff_decode_sym_emit(bufs, t->sym, avail);
}
t = &huff_decode_table[t->state][src[i] & 0xf];
if (t->flags & NGHTTP2_HUFF_FAIL) {
return NGHTTP2_ERR_HEADER_COMP;
}
if (t->flags & NGHTTP2_HUFF_SYM) {
/* this is macro, and may return from this function on error */
hd_huff_decode_sym_emit(bufs, t->sym, avail);
}
ctx->state = t->state;
ctx->accept = (t->flags & NGHTTP2_HUFF_ACCEPTED) != 0;
}
if (final && !ctx->accept) {
return NGHTTP2_ERR_HEADER_COMP;

View File

@@ -292,17 +292,23 @@ const char *nghttp2_strerror(int error_code) {
case NGHTTP2_ERR_PUSH_DISABLED:
return "Server push is disabled by peer";
case NGHTTP2_ERR_DATA_EXIST:
return "DATA frame already exists";
return "DATA or HEADERS frame has already been submitted for the stream";
case NGHTTP2_ERR_SESSION_CLOSING:
return "The current session is closing";
case NGHTTP2_ERR_HTTP_HEADER:
return "Invalid HTTP header field was received";
case NGHTTP2_ERR_HTTP_MESSAGING:
return "Violation in HTTP messaging rule";
case NGHTTP2_ERR_REFUSED_STREAM:
return "Stream was refused";
case NGHTTP2_ERR_INTERNAL:
return "Internal error";
case NGHTTP2_ERR_NOMEM:
return "Out of memory";
case NGHTTP2_ERR_CALLBACK_FAILURE:
return "The user callback function failed";
case NGHTTP2_ERR_BAD_PREFACE:
return "Received bad connection preface";
case NGHTTP2_ERR_BAD_CLIENT_MAGIC:
return "Received bad client magic byte string";
default:
return "Unknown error code";
}

Some files were not shown because too many files have changed in this diff Show More