transfer: don't close connections in transfer

This commit is contained in:
Michał Matczuk 2017-11-15 00:07:10 +01:00
parent 8cf9ce23ec
commit 496df4d34f
3 changed files with 25 additions and 34 deletions

View file

@ -465,16 +465,16 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusBadGateway)
return
}
defer resp.Body.Close()
copyHeader(w.Header(), resp.Header)
w.WriteHeader(resp.StatusCode)
if resp.Body != nil {
transfer(w, resp.Body, log.NewContext(s.logger).With(
"dir", "client to user",
"dst", r.RemoteAddr,
"src", r.Host,
))
}
transfer(w, resp.Body, log.NewContext(s.logger).With(
"dir", "client to user",
"dst", r.RemoteAddr,
"src", r.Host,
))
}
// RoundTrip is http.RoundTriper implementation.
@ -504,7 +504,7 @@ func (s *Server) RoundTrip(r *http.Request) (*http.Response, error) {
func (s *Server) proxyConn(identifier id.ID, conn net.Conn, msg *proto.ControlMessage) error {
s.logger.Log(
"level", 2,
"action", "proxy",
"action", "proxy conn",
"identifier", identifier,
"ctrlMsg", msg,
)
@ -520,6 +520,9 @@ func (s *Server) proxyConn(identifier id.ID, conn net.Conn, msg *proto.ControlMe
return err
}
ctx, cancel := context.WithCancel(context.Background())
req = req.WithContext(ctx)
done := make(chan struct{})
go func() {
transfer(pw, conn, log.NewContext(s.logger).With(
@ -527,6 +530,7 @@ func (s *Server) proxyConn(identifier id.ID, conn net.Conn, msg *proto.ControlMe
"dst", identifier,
"src", conn.RemoteAddr(),
))
cancel()
close(done)
}()
@ -534,6 +538,7 @@ func (s *Server) proxyConn(identifier id.ID, conn net.Conn, msg *proto.ControlMe
if err != nil {
return fmt.Errorf("io error: %s", err)
}
defer resp.Body.Close()
transfer(conn, resp.Body, log.NewContext(s.logger).With(
"dir", "client to user",
@ -545,7 +550,7 @@ func (s *Server) proxyConn(identifier id.ID, conn net.Conn, msg *proto.ControlMe
s.logger.Log(
"level", 2,
"action", "proxy done",
"action", "proxy conn done",
"identifier", identifier,
"ctrlMsg", msg,
)
@ -556,7 +561,7 @@ func (s *Server) proxyConn(identifier id.ID, conn net.Conn, msg *proto.ControlMe
func (s *Server) proxyHTTP(identifier id.ID, r *http.Request, msg *proto.ControlMessage) (*http.Response, error) {
s.logger.Log(
"level", 2,
"action", "proxy",
"action", "proxy HTTP",
"identifier", identifier,
"ctrlMsg", msg,
)
@ -605,7 +610,7 @@ func (s *Server) proxyHTTP(identifier id.ID, r *http.Request, msg *proto.Control
s.logger.Log(
"level", 2,
"action", "proxy done",
"action", "proxy HTTP done",
"identifier", identifier,
"ctrlMsg", msg,
"status code", resp.StatusCode,

View file

@ -97,6 +97,7 @@ func (p *TCPProxy) Proxy(w io.Writer, r io.ReadCloser, msg *proto.ControlMessage
)
return
}
defer local.Close()
done := make(chan struct{})
go func() {

View file

@ -7,36 +7,21 @@ package tunnel
import (
"io"
"net/http"
"strings"
"github.com/mmatczuk/go-http-tunnel/log"
)
type closeWriter interface {
CloseWrite() error
}
type closeReader interface {
CloseRead() error
}
func transfer(dst io.Writer, src io.ReadCloser, logger log.Logger) {
n, err := io.Copy(dst, src)
if err != nil {
logger.Log(
"level", 2,
"msg", "copy error",
"err", err,
)
}
if d, ok := dst.(closeWriter); ok {
d.CloseWrite()
}
if s, ok := src.(closeReader); ok {
s.CloseRead()
} else {
src.Close()
if !strings.Contains(err.Error(), "context canceled") && !strings.Contains(err.Error(), "CANCEL") {
logger.Log(
"level", 2,
"msg", "copy error",
"err", err,
)
}
}
logger.Log(