Search code examples
c++httphttp2nghttp2

How can I solve the "empty response" error using nghttp2?


I'm using nghttp2_asio. I compiled it using ./configure --enable-asio-lib. Then, I added /usr/local/lib to /etc/ld.so.conf file. The code is as follows:

#include "bits/stdc++.h"
#include "nghttp2/asio_http2_server.h"

using namespace std;
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;

int main(int argc, char **argv) {
  http2 srv;
  srv.num_threads(4);
  srv.handle("/", [](const request &req, const response &res) {
    cout << req.uri().path << endl;
    header_map headers;
    headers.emplace("content-type", header_value{ "text/html", false });
    res.write_head(200, headers);
    res.end(file_generator("index.html"));
  });
  boost::system::error_code ec;
  if (srv.listen_and_serve(ec, "localhost", "8080")) cerr << ec.message() << endl;
  return 0;
}

When I try to open the browser (Chrome or Firefox) on http://localhost:8080, it give me the following error:

This page isn't working

localhost didn't send any data.

ERR_EMPTY_RESPONSE

Even if I try with curl, it gives me the error:

curl: (52) Empty reply from server

The only thing that works is curl http://localhost:8080 --http2-prior-knowledge.

Is there a solution for this?


Solution

  • It looks like your browser refuses to do HTTP/2 over an unencrypted connection. The Wikipedia page has the following to say:

    Although the standard itself does not require usage of encryption,[51] all major client implementations (Firefox,[52] Chrome, Safari, Opera, IE, Edge) have stated that they will only support HTTP/2 over TLS, which makes encryption de facto mandatory.[53]

    cURL has a different problem: it defaults to HTTP/1 which your HTTP/2 server does not understand. Adding the flag makes it use the HTTP/2 binary protocol directly. Alternatively, connecting to an HTTPS endpoint will automatically turn on HTTP/2.

    See the libnghttp2_asio documentation for an example on how to serve with encryption:

    int main(int argc, char *argv[]) {
      boost::system::error_code ec;
      boost::asio::ssl::context tls(boost::asio::ssl::context::sslv23);
    
      tls.use_private_key_file("server.key", boost::asio::ssl::context::pem);
      tls.use_certificate_chain_file("server.crt");
    
      configure_tls_context_easy(ec, tls);
    
      http2 server;
    
      // add server handlers here
    
      if (server.listen_and_serve(ec, tls, "localhost", "3000")) {
        std::cerr << "error: " << ec.message() << std::endl;
      }
    }