srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/internal/proxy/proxy.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/proxy/proxy.go')
-rw-r--r--internal/proxy/proxy.go14
1 files changed, 13 insertions, 1 deletions
diff --git a/internal/proxy/proxy.go b/internal/proxy/proxy.go
index fcf8c14..014c601 100644
--- a/internal/proxy/proxy.go
+++ b/internal/proxy/proxy.go
@@ -38,6 +38,10 @@ import (
"mitmux/internal/store"
)
+// upstreamTimeout bounds the write-request/read-response phase of an
+// upstream exchange, once dialing has already succeeded.
+const upstreamTimeout = 60 * time.Second
+
// hopByHopHeaders are stripped before forwarding a request or response,
// per RFC 7230 6.1 - they are meaningful only between a client and its
// immediate next hop, not end-to-end.
@@ -259,6 +263,14 @@ func (s *Server) forward(dial dialer, scheme, hostname string, w http.ResponseWr
return
}
defer conn.Close()
+ // The dial itself is bounded (net.Dialer.Timeout / HandshakeContext);
+ // without this, a server that accepts the connection and then never
+ // writes or never finishes writing would hang the request forever -
+ // there's no other timeout covering the write-request/read-response
+ // phase. Bounds the whole exchange, so a legitimately slow multi-
+ // minute transfer would also get cut off; a fixed default is enough
+ // for now, not worth a config surface yet.
+ conn.SetDeadline(time.Now().Add(upstreamTimeout))
var resp *http.Response
var upstreamTee *teeConn
@@ -299,7 +311,7 @@ func (s *Server) forward(dial dialer, scheme, hostname string, w http.ResponseWr
if upstreamTee != nil {
respRaw, respExact = upstreamTee.Take(), true
} else {
- respRaw, respExact = captureResponse(resp, nil, respBodyCap)
+ respRaw, respExact = captureResponse(resp, respBodyCap)
}
s.record(started, duration, scheme, hostname, r, reqRaw, reqExact, respRaw, respExact, resp.StatusCode, "")