title: How to ask the client to downgrade a HTTP2 connection to HTTP1.1
body: <p>This is mostly out of curiosity; say I have a HTTP1.1 compatible server.  I don't have the resources / it's not possible to add full HTTP2 support to that server.</p>
  <p>Still I want to be able to serve <a href="https://http2.github.io/http2-spec/#known-http" rel="nofollow noreferrer">clients which open a connection with a HTTP2 connection preface</a> (<code>PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n</code>) by telling them to use HTTP1.1 instead.  Note that this is about clients which <strong>don't</strong> start the connection with a HTTP1.1 request with an <code>Upgrade</code> header.</p>
  <p>This is the behavior I'd like to achieve:</p>
  <pre><code>CLIENT                 SERVER
    | ------ http2 GET --&gt; |
    | &lt;----need http1 ---- |
    | ------ http1 GET --&gt; |
    ... (normal http1 processing)
  </code></pre>
  <p>The specification contains an error code <code>HTTP_1_1_REQUIRED (0xd)</code> which sounds just about what I need.  Moreover, from reading around it seems that this error code is used to downgrade connections when necessary (TLS re-negotiation apparently?).  Yet I just don't seem to be able to get this to work...</p>
  <pre class="lang-c prettyprint-override"><code>char const Http2EmptySettingsFrame[] =
    {
     // Frame Header
     0, 0, 0,
     0x4,
     0,
     0 &amp; 0x7F, 0, 0, 0
    };
  
  char const Http2RstStreamFrame[] =
    {
     // Frame Header
     0, 0, 4, // Length of frame content
     0x3, // Type: RST_STREAM
     0, // Flags
     0 &amp; 0x7F, 0, 0, 1, // Stream identifier 1 ; also tried with 0
  
     // Frame content
     0, 0, 0, 0xD // Error code (RST_STREAM frame)
    };
  
  char const Http2GoAwayFrame[] =
    {
     // Frame Header
     0, 0, 8,
     0x7,
     0,
     0 &amp; 0x7F, 0, 0, 0,
  
     0 &amp; 0x7F, 0, 0, 0, // GO_AWAY stream id
     0, 0, 0, 0xD // GO_AWAY error code: HTTP_1_1_REQUIRED
    };
  
  </code></pre>
  <p>Using the above and <code>fwrite(frame, sizeof(frame), 1, stdout)</code> in a small test program, I create frames to send to a client to (<code>./a.out &gt; frame.bin</code>).  I then start my &quot;server&quot;:</p>
  <pre class="lang-sh prettyprint-override"><code>cat emptysettings.bin rststream.bin goaway.bin - | netcat -l -p 8888 -s 127.0.0.1
  </code></pre>
  <p>Using a http2 client I then get ...</p>
  <pre class="lang-sh prettyprint-override"><code># this was when just sending empty SETTINGS and RST_STREAM frame
  nghttp -v http://127.0.0.1:8888
  [  0.000] Connected
  [  0.000] recv SETTINGS frame &lt;length=0, flags=0x00, stream_id=0&gt;
            (niv=0)
  [  0.000] [INVALID; error=Protocol error] recv RST_STREAM frame &lt;length=4, flags=0x00, stream_id=1&gt;
            (error_code=HTTP_1_1_REQUIRED(0x0d))
  [  0.000] send SETTINGS frame &lt;length=12, flags=0x00, stream_id=0&gt;
            (niv=2)
            [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
            [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
  [  0.000] send GOAWAY frame &lt;length=34, flags=0x00, stream_id=0&gt;
            (last_stream_id=0, error_code=PROTOCOL_ERROR(0x01), opaque_data(26)=[RST_STREAM: stream in idle])
  [ERROR] request http://127.0.0.1:8888 failed: request HEADERS is not allowed
  Some requests were not processed. total=1, processed=0
  </code></pre>
  <p>... or using curl ...</p>
  <pre class="lang-sh prettyprint-override"><code>curl -v --http2-prior-knowledge http://127.0.0.1:8888
  *   Trying 127.0.0.1:8888...
  * TCP_NODELAY set
  * Connected to 127.0.0.1 (127.0.0.1) port 8888 (#0)
  * Using HTTP2, server supports multi-use
  * Connection state changed (HTTP/2 confirmed)
  * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
  * Using Stream ID: 1 (easy handle 0x16887f0)
  &gt; GET / HTTP/2
  &gt; Host: 127.0.0.1:8888
  &gt; User-Agent: curl/7.66.0
  &gt; Accept: */*
  &gt; 
  * Connection state changed (MAX_CONCURRENT_STREAMS == 4294967295)!
  * stopped the pause stream!
  * Connection #0 to host 127.0.0.1 left intact
  curl: (16) Error in the HTTP2 framing layer
  </code></pre>
  <p>... thus: <strong>What response do I need to send to a client initiating a http2 connection for them to downgrade the connection to HTTP1.1?</strong></p>
  <p>Sending <code>HTTP/1.1 505 hmmm\n\n</code> (505 = <a href="https://www.rfc-editor.org/rfc/rfc2616#section-10.5.6" rel="nofollow noreferrer">HTTP Version not supported</a>) doesn't help either...</p>