title: Count sent and received bytes in Go in an http.Handler ServeHTTP function?
body: <p>How can sent and received bytes be counted from within a <code>ServeHTTP</code> function in Go?</p>
  
  <p>The count needs to be relatively accurate. Skipping connection establishment is not ideal, but acceptable. But headers must be included.</p>
  
  <p>It also needs to be fast. Iterating is generally too slow.</p>
  
  <p>The counting itself doesn't need to occur within <code>ServeHTTP</code>, as long the count for a given connection can be made available to <code>ServeHTTP</code>.</p>
  
  <p>This must also not break HTTPS or HTTP/2.</p>
  
  <p><strong>Things I've Tried</strong></p>
  
  <p>It's possible to get a rough, slow estimate of received bytes by iterating over the <code>Request</code> headers. This is far too slow, and the Go standard library removes and combines headers, so it's not accurate either.</p>
  
  <p>I tried writing an intercepting <code>Listener</code>, which created an internal <code>tls.Listen</code> or <code>net.Listen</code> Listener, and whose <code>Accept()</code> function got a <code>net.Conn</code> from the internal Listener's <code>Accept()</code>, and then wrapped that in an intercepting <code>net.Conn</code> whose <code>Read</code> and <code>Write</code> functions call the real <code>net.Conn</code> and count their reads and writes. It's then possible to make those counts available to the <code>ServeHTTP</code> function via mutexed shared variables.</p>
  
  <p>The problem is, the intercepting <code>Conn</code> breaks HTTP/2, because Go's internal libraries cast the <code>net.Conn</code> as a <code>*tls.Conn</code> (e.g. <a href="https://golang.org/src/net/http/server.go#L1730" rel="nofollow noreferrer">https://golang.org/src/net/http/server.go#L1730</a>), and it doesn't appear possible in Go to wrap the object while still making that cast succeed (if it is, it would solve this problem).</p>
  
  <p>Counting sent bytes can be done relatively accurately by counting what is written to the <code>ResponseWriter</code>. Counting received bytes in the HTTP body is also achievable, via <code>Request.Body</code>. The critical issue here appears to be quickly and accurately counting request header bytes. Though again, also counting connection establishment bytes would be ideal.</p>
  
  <p>Is this possible? How?</p>