8

When using Cro with HTTP1.1 I can access the requested Host via both the host method request.uri.host in Cro::Uri as well as the Host or :authority header sent by the browser via the request.header method in Cro::HTTP::Request.

However, when I use HTTP/2, none of these work. The Uri object only contains the schema and the path.

I'm using an official certificate with a wildcard for subdomains and running this locally by adding these subdomains to my hosts file. Chrome DevTools says it has sent the :authority request header under HTTP/2 and Firefox Developer Tools says it has sent the Host request header under HTTP/2. However if I write the headers to a log like below, I see several headers, but not the Host or :authority header.

sub routes() is export {
  route {
    get -> {
      my $log = "/data/myapp/logs/cro.log";
      my $fh = open $log, :w;
      my $host = request.uri.host;
      $fh.say( "Host with host method: " ~ $host );
      $host = request.header('Host');
      $fh.say( "Host: " ~ $host );
      $host = request.header(':authority');
      $fh.say(":authority: " ~ $host );
      $fh.say( "Request headers:" );
      for request.headers {
        $fh.say( "{.name}: {.value}" );
      }
      $fh.close;
      content 'text/html', "<h1> MyApp </h1><p>Running";
    }
  }
}

I'm aware that HTTP/2 uses Server Name Indication and that the host name is sent as part of the TLS negotiation. On the other hand this is also part of the Cro modules (Cro::TLS) and the headers are sent by the browser nonetheless.

So how to get the host under HTTP/2?

acw
  • 447
  • 2
  • 9

1 Answers1

8

This appears to be a plain bug (unrelated to ones named by Raiph).

I wrote a patch and sent a PR (https://github.com/croservices/cro-http/pull/104), with it merged you can update your Cro::HTTP distribution and both ways you specified (request.uri construction or asking for header('Host')) will work.

Takao
  • 1,016
  • 6
  • 11
  • 1
    Hi @Takao. It's great to see Cro steadily mature as it passes thru the beta 0.8... series on its way to an eventual 1.0 (in a year or two at a guess). I'm curious what debugging approach you took (insert some `say` statements?) and if you essentially guessed the problem because you know the relevant protocols and the Cro source code? Is there a good single link that gives an overview of debugging Cro issues in general, and http ones in particular? (And if not, any quick comments you might have would be great.) – raiph Jun 10 '20 at 19:05
  • 3
    My way was: 1)run `http2.t` test with `note $request.uri` added to the `/` route block with both HTTP versions; 2)It differs. Run with `CRO_TRACE=1` as env var; 3)In `CRO_TRACE` output the request has the header, but when it is parsed by the server, not anymore; 4)Go to part of the HTTP/2 parser which sets headers; 5)There are 5 pseudo-headers in HTTP/2, but we only handled 3 of them; 6)Add a missing one; 7)Fixed, add a test, PR. There is no debugging manual, but setting `CRO_TRACE` and running helps a lot to understand what module has a problem and go there. – Takao Jun 10 '20 at 19:28
  • 2
    Cro is very modular and it helps debugging, but HTTP by itself is tricky, so the code in some places is hard to get. There are some concurrency problems known, as well as related to error reporting in various cases. But when it is about protocol data processing parts (like this one), those bugs are usually good to debug. – Takao Jun 10 '20 at 19:35
  • 1
    @Takoa Thank you diagnosing and fixing. More on [github](https://github.com/croservices/cro-http/pull/104#issuecomment-642928932) – acw Jun 11 '20 at 21:11