1 libnghttp2_asio: High level HTTP/2 C++ library
2 ==============================================
4 libnghttp2_asio is C++ library built on top of libnghttp2 and provides
5 high level abstraction API to build HTTP/2 applications. It depends
6 on Boost::ASIO library and OpenSSL. Currently libnghttp2_asio
7 provides server and client side API.
9 libnghttp2_asio is not built by default. Use ``--enable-asio-lib``
10 configure flag to build libnghttp2_asio. The required Boost libraries
17 We have 3 header files for this library:
19 * :doc:`asio_http2_server.h`
20 * :doc:`asio_http2_client.h`
23 asio_http2.h is included from the other two files.
25 To build a program with libnghttp2_asio, link to the following
28 -lnghttp2_asio -lboost_system
30 If ``boost::asio::ssl`` is used in application code, OpenSSL is also
31 required in link line::
33 -lnghttp2_asio -lboost_system -lssl -lcrypto
38 To use server API, first include following header file:
42 #include <nghttp2/asio_http2_server.h>
44 Also take a look at that header file :doc:`asio_http2_server.h`.
46 Server API is designed to build HTTP/2 server very easily to utilize
47 C++11 anonymous function and closure. The bare minimum example of
48 HTTP/2 server looks like this:
52 using namespace nghttp2::asio_http2;
53 using namespace nghttp2::asio_http2::server;
55 int main(int argc, char *argv[]) {
56 boost::system::error_code ec;
59 server.handle("/", [](const request &req, const response &res) {
61 res.end("hello, world\n");
64 if (server.listen_and_serve(ec, "localhost", "3000")) {
65 std::cerr << "error: " << ec.message() << std::endl;
69 First we instantiate ``nghttp2::asio_http2::server::http2`` object.
70 ``nghttp2::asio_http2::server::http2::handle`` function registers
71 pattern and its handler function. In this example, we register "/" as
72 pattern, which matches all requests. Then call
73 ``nghttp2::asio_http2::server::http2::listen_and_serve`` function with
74 address and port to listen to.
76 The ``req`` and ``res`` represent HTTP request and response
77 respectively. ``nghttp2::asio_http2_::server::response::write_head``
78 constructs HTTP response header fields. The first argument is HTTP
79 status code, in the above example, which is 200. The second argument,
80 which is omitted in the above example, is additional header fields to
83 ``nghttp2::asio_http2::server::response::end`` sends response body.
84 In the above example, we send string "hello, world".
86 The life time of req and res object ends after the callback set by
87 ``nghttp2::asio_http2::server::response::on_close`` function.
88 Application must not use those objects after this call.
90 Serving static files and enabling SSL/TLS
91 +++++++++++++++++++++++++++++++++++++++++
93 In this example, we serve a couple of static files and also enable
98 #include <nghttp2/asio_http2_server.h>
100 using namespace nghttp2::asio_http2;
101 using namespace nghttp2::asio_http2::server;
103 int main(int argc, char *argv[]) {
104 boost::system::error_code ec;
105 boost::asio::ssl::context tls(boost::asio::ssl::context::sslv23);
107 tls.use_private_key_file("server.key", boost::asio::ssl::context::pem);
108 tls.use_certificate_chain_file("server.crt");
110 configure_tls_context_easy(ec, tls);
114 server.handle("/index.html", [](const request &req, const response &res) {
116 res.end(file_generator("index.html"));
119 if (server.listen_and_serve(ec, tls, "localhost", "3000")) {
120 std::cerr << "error: " << ec.message() << std::endl;
124 We first create ``boost::asio::ssl::context`` object and set path to
125 private key file and certificate file.
126 ``nghttp2::asio_http2::server::configure_tls_context_easy`` function
127 configures SSL/TLS context object for HTTP/2 server use, including NPN
130 In the above example, if request path is "/index.html", we serve
131 index.html file in the current working directory.
132 ``nghttp2::asio_http2::server::response::end`` has overload to take
133 function of type ``nghttp2::asio_http2::generator_cb`` and application
134 pass its implementation to generate response body. For the
135 convenience, libnghttp2_asio library provides
136 ``nghttp2::asio_http2::file_generator`` function to generate function
137 to server static file. If other resource is requested, server
138 automatically responds with 404 status code.
143 Server push is also supported.
147 #include <nghttp2/asio_http2_server.h>
149 using namespace nghttp2::asio_http2;
150 using namespace nghttp2::asio_http2::server;
152 int main(int argc, char *argv[]) {
153 boost::system::error_code ec;
154 boost::asio::ssl::context tls(boost::asio::ssl::context::sslv23);
156 tls.use_private_key_file("server.key", boost::asio::ssl::context::pem);
157 tls.use_certificate_chain_file("server.crt");
159 configure_tls_context_easy(ec, tls);
163 std::string style_css = "h1 { color: green; }";
165 server.handle("/", [&style_css](const request &req, const response &res) {
166 boost::system::error_code ec;
167 auto push = res.push(ec, "GET", "/style.css");
168 push->write_head(200);
169 push->end(style_css);
173 <!DOCTYPE html><html lang="en">
174 <title>HTTP/2 FTW</title><body>
175 <link href="/style.css" rel="stylesheet" type="text/css">
176 <h1>This should be green</h1>
181 server.handle("/style.css",
182 [&style_css](const request &req, const response &res) {
187 if (server.listen_and_serve(ec, tls, "localhost", "3000")) {
188 std::cerr << "error: " << ec.message() << std::endl;
192 When client requested any resource other than "/style.css", we push
193 "/style.css". To push resource, call
194 ``nghttp2::asio_http2::server::response::push`` function with desired
195 method and path. It returns another response object and use its
196 functions to send push response.
198 Enable multi-threading
199 ++++++++++++++++++++++
201 Enabling multi-threading is very easy. Just call
202 ``nghttp2::asio_http2::server::http2::num_threads`` function with the
203 desired number of threads:
209 // Use 4 native threads
210 server.num_threads(4);
215 To use client API, first include following header file:
219 #include <nghttp2/asio_http2_client.h>
221 Also take a look at that header file :doc:`asio_http2_client.h`.
223 Here is the sample client code to access HTTP/2 server and print out
224 response header fields and response body to the console screen:
230 #include <nghttp2/asio_http2_client.h>
232 using boost::asio::ip::tcp;
234 using namespace nghttp2::asio_http2;
235 using namespace nghttp2::asio_http2::client;
237 int main(int argc, char *argv[]) {
238 boost::system::error_code ec;
239 boost::asio::io_service io_service;
241 // connect to localhost:3000
242 session sess(io_service, "localhost", "3000");
244 sess.on_connect([&sess](tcp::resolver::iterator endpoint_it) {
245 boost::system::error_code ec;
247 auto req = sess.submit(ec, "GET", "http://localhost:3000/");
249 req->on_response([](const response &res) {
250 // print status code and response header fields.
251 std::cerr << "HTTP/2 " << res.status_code() << std::endl;
252 for (auto &kv : res.header()) {
253 std::cerr << kv.first << ": " << kv.second.value << "\n";
255 std::cerr << std::endl;
257 res.on_data([](const uint8_t *data, std::size_t len) {
258 std::cerr.write(reinterpret_cast<const char *>(data), len);
259 std::cerr << std::endl;
263 req->on_close([&sess](uint32_t error_code) {
264 // shutdown session after first request was done.
269 sess.on_error([](const boost::system::error_code &ec) {
270 std::cerr << "error: " << ec.message() << std::endl;
276 ``nghttp2::asio_http2::client::session`` object takes
277 ``boost::asio::io_service`` object and remote server address. When
278 connection is made, the callback function passed to
279 ``nghttp2::asio_http2::client::on_connect`` is invoked with connected
280 address as its parameter. After this callback call, use
281 ``nghttp2::asio_http2::session::submit`` to send request to the
282 server. You can submit multiple requests at once without waiting for
283 the completion of previous request.
285 The life time of req and res object ends after the callback set by
286 ``nghttp2::asio_http2::server::request::on_close`` function.
287 Application must not use those objects after this call.
289 Normally, client does not stop even after all requests are done unless
290 connection is lost. To stop client, call
291 ``nghttp2::asio_http2::server::session::shutdown()``.
293 Recieve server push and enable SSL/TLS
294 ++++++++++++++++++++++++++++++++++++++
300 #include <nghttp2/asio_http2_client.h>
302 using boost::asio::ip::tcp;
304 using namespace nghttp2::asio_http2;
305 using namespace nghttp2::asio_http2::client;
307 int main(int argc, char *argv[]) {
308 boost::system::error_code ec;
309 boost::asio::io_service io_service;
311 boost::asio::ssl::context tls(boost::asio::ssl::context::sslv23);
312 tls.set_default_verify_paths();
313 // disabled to make development easier...
314 // tls_ctx.set_verify_mode(boost::asio::ssl::verify_peer);
315 configure_tls_context(ec, tls);
317 // connect to localhost:3000
318 session sess(io_service, tls, "localhost", "3000");
320 sess.on_connect([&sess](tcp::resolver::iterator endpoint_it) {
321 boost::system::error_code ec;
323 auto req = sess.submit(ec, "GET", "http://localhost:3000/");
325 req->on_response([&sess](const response &res) {
326 std::cerr << "response received!" << std::endl;
327 res.on_data([&sess](const uint8_t *data, std::size_t len) {
328 std::cerr.write(reinterpret_cast<const char *>(data), len);
329 std::cerr << std::endl;
333 req->on_push([](const request &push) {
334 std::cerr << "push request received!" << std::endl;
335 push.on_response([](const response &res) {
336 std::cerr << "push response received!" << std::endl;
337 res.on_data([](const uint8_t *data, std::size_t len) {
338 std::cerr.write(reinterpret_cast<const char *>(data), len);
339 std::cerr << std::endl;
345 sess.on_error([](const boost::system::error_code &ec) {
346 std::cerr << "error: " << ec.message() << std::endl;
352 The above sample code demonstrates how to enable SSL/TLS and receive
353 server push. Currently,
354 ``nghttp2::asio_http2::client::configure_tls_context`` function setups
355 NPN callbacks for SSL/TLS context for HTTP/2 use.
357 To receive server push, use
358 ``nghttp2::asio_http2::client::request::on_push`` function to set
359 callback function which is invoked when server push request is
360 arrived. The callback function takes
361 ``nghttp2::asio_http2::client::request`` object, which contains the
362 pushed request. To get server push response, set callback using
363 ``nghttp2::asio_http2::client::request::on_response``.
365 As stated in the previous section, client does not stop automatically
366 as long as HTTP/2 session is fine and connection is alive. We don't
367 call ``nghttp2::asio_http2::client::session::shutdown`` in this
368 example, so the program does not terminate after all responses are
369 received. Hit Ctrl-C to terminate the program.
371 Multiple concurrent requests
372 ++++++++++++++++++++++++++++
378 #include <nghttp2/asio_http2_client.h>
380 using boost::asio::ip::tcp;
382 using namespace nghttp2::asio_http2;
383 using namespace nghttp2::asio_http2::client;
385 int main(int argc, char *argv[]) {
386 boost::system::error_code ec;
387 boost::asio::io_service io_service;
389 // connect to localhost:3000
390 session sess(io_service, "localhost", "3000");
392 sess.on_connect([&sess](tcp::resolver::iterator endpoint_it) {
393 boost::system::error_code ec;
395 auto printer = [](const response &res) {
396 res.on_data([](const uint8_t *data, std::size_t len) {
397 std::cerr.write(reinterpret_cast<const char *>(data), len);
398 std::cerr << std::endl;
403 auto count = std::make_shared<int>(num);
405 for (std::size_t i = 0; i < num; ++i) {
406 auto req = sess.submit(ec, "GET",
407 "http://localhost:3000/" + std::to_string(i + 1));
409 req->on_response(printer);
410 req->on_close([&sess, count](uint32_t error_code) {
412 // shutdown session after |num| requests were done.
419 sess.on_error([](const boost::system::error_code &ec) {
420 std::cerr << "error: " << ec.message() << std::endl;
426 Here is the sample to send 3 requests at once. Depending on the
427 server settings, these requests are processed out-of-order. In this
428 example, we have a trick to shutdown session after all requests were
429 done. We made ``count`` object which is shared pointer to int and is
430 initialized to 3. On each request closure (the invocation of the
431 callback set by ``nghttp2::asio_http2::client::request::on_close``),
432 we decrement the count. If count becomes 0, we are sure that all
433 requests have been done and initiate shutdown.