title: When should an http.RoundTripper close its connection?
body: <p>I'm using <a href="https://golang.org/pkg/net/http/httputil/#ReverseProxy" rel="nofollow noreferrer">httputil.ReverseProxy</a> with an <a href="https://golang.org/pkg/net/http/#RoundTripper" rel="nofollow noreferrer">http.RoundTripper</a> of my own implementation that uses an <a href="https://godoc.org/golang.org/x/crypto/ssh#Channel" rel="nofollow noreferrer">ssh.Channel</a> as a transport. My RoundTrip method looks approximately like this:</p>
  
  <pre><code>func (c SSHConnection) RoundTrip(req *http.Request) (*http.Response, error) {
      ch, err := c.GetChannel()
      if err != nil {
          return nil, errors.New("couldn't open forwarded-tcpip channel: " + err.Error())
      }
      // defer ch.Close()
      err = req.Write(ch)
      if err != nil {
          return nil, errors.New("couldn't send request: " + err.Error())
      }
  
      return http.ReadResponse(bufio.NewReader(ch), req)
  }
  
  func (c SSHConnection) GetChannel() (ssh.Channel, error) {
      ch, req, err := c.Conn.OpenChannel("forwarded-tcpip", msg)
      if err != nil {
          return nil, err
      }
      go ssh.DiscardRequests(req)
      return ch, nil
  }
  </code></pre>
  
  <p>Notice the commented-out defer ch.Close(). Initially I naively closed the connection here, but the response body would sometimes be empty, due to a race between the HTTP proxy's reading of the body and this closing of the SSH channel.</p>
  
  <p>Assuming, for now, that I don't care to do keep-alive, when can I close the ssh.Channel? If I don't, every request starts a new goroutine (because of go ssh.DiscardRequests(req)), so I leak a goroutine on every HTTP requests until the underlying SSH connection is closed.</p>