HTTP/2 C library and tools

Nghttp2 v1.5.0

We released nghttp2 v1.5.0.

This release introduces new APIs, and fixes several bugs, and adds new features to bundled applications.

First, let’s talk about new APIs.

The new API nghttp2_session_change_stream_priority() changes the priority of given stream without sending PRIORITY frame. This is very useful for server to change priority of streams, especially for pushed streams. By default, pushed streams depend on the associated stream, but if we are pushing resources included in critical rendering path, it would be better to at least interleave them with the associated stream. In this case, using this new API is very handy.

The new API nghttp2_session_check_server_session() is very simple function, and returns nonzero if given HTTP/2 session is configured as server side.

The new API nghttp2_session_check_request_allowed() is for client to check that it can send request at this time. There are several reasons that request can no longer be issued (e.g., all available stream IDs have been spent; or GOAWAY has been received).

The new API nghttp2_session_upgrade2() deprecates existing nghttp2_session_upgrade(). nghttp2_session_upgrade() is called in both client and server when connection was upgraded to HTTP/2 from HTTP/1.1 via HTTP Upgrade mechanism. Originally reported in curl issue #521, we discovered that it has a design flaw. That is it does not tell the library the request method upgraded request used. By default, nghttp2 library checks HTTP messaging rules. One of them is that the length of response body matches the length included in content-length. In particular, when method is HEAD, in client side library checks that response body is really 0, no matter what the content-length header field contains. Suppose the first request with HTTP Upgrade has HEAD method, and it is upgraded. Since nghttp2_session_upgrade() cannot tell the library what method is, library attempts to check the response body length matches content-length header field. But this will fail since server returns 0 length body, and non-zero length header field most likely exists. This results in sending RST_STREAM from client side. The new nghttp2_session_upgrade2() has additional parameter to tell library the method is HEAD or not, and it solves this issue. All programs using nghttp2_session_upgrade() are advised to migrate to nghttp2_session_upgrade2() as soon as possible. To workaround the above problem in nghttp2_session_upgrade(), it now does not check response body length against content-length for the upgraded request, but this is just a gas stop measure.

The new flags NGHTTP2_NV_FLAG_NO_COPY_NAME and NGHTTP2_NV_FLAG_NO_COPY_VALUE have been introduced in this release. They are used to specify flags field of nghttp2_nv. Previously, when application passed header fields to functions like nghttp2_submit_request() or nghttp2_submit_response(), they are all copied. This is very convenient and quite safe, since caller does not have to worry about the memory leak or dangling pointers. But obviously this memory copy could add overhead especially if header fileds are long or many. The new flags can tell the library that it does not have to copy header name or value, thereby eliminates the overhead of copying. It is a responsibility of applications to retain the header fields until the library finished using them. For server application, usually response headers are retained until streams are closed, due to logging variables, so there is a good chance for them to optimize a bit and squeeze the more speed.

OK, that is all for new stuff for library API. Let’s see the bug fix in library. The documentation of nghttp2_session_find_stream() said that it returns root stream (stream ID is 0) if 0 is passed as stream ID, but previously it returned always NULL. Now it is corrected, and it returns root stream.

Kamil Dudka fixed borken linage with --disable-static in unit tests.

We added ALPN support for asio library.

For h2load, we made some bug fixes, and added new features. We fixed the bug which caused crash when dealing with “connection: close” from HTTP/1.1 server. Kit Chan fixed the bug that h2load goes into infinite loop when timing script file starts with 0.0 in first line. Previously, user cannot override user-agent header field with -H option, but now they can do that. We now show “space savings” to measure header compression efficiency. This is only useful for HTTP/2 or SPDY. We fixed bug that application protocol is not shown with OpenSSL < 1.0.2. We introduced --h1 option which is a short hand of --npn-list=http/1.1 and --no-tls-proto=http/1.1, and effectively forces http/1.1 usage for both http and https URI.

For nghttpx, we finally support server push from HTTP/2 backend. PUSH_PROMISE frame from backend is forwarded to frontend session, and delivered to client. We fixed the bug that causes connection failure with backend proxy URI. We now use the host name given in --backend-tls-sni-field to verify certificate host name. We now log :authority header field value as $http_host if available. This is useful since HTTP/2 request might not contain host header field.

For nghttpd, we fixed crash with CONNECT request. Previously, nghttpd does not set content-type header fields. In this release, nghttpd reads /etc/mime.types and set content-type header field depending on the extension of the requested resource.

For nghttp, request method is now record in har correctly. The HTTP method in HTTP Upgrade is now configurable using -H with :method.

Finally, we upgraded clang-format-3.6. We also upgraded mruby to 1.2.0.