mirror of
https://github.com/fosrl/newt.git
synced 2026-05-20 23:29:56 +00:00
Merge pull request #345 from LaurenceJJones/investigate/https-permanent-redirect-loop
fix(http): populate Request.TLS for private HTTPS via httpConnCtx
This commit is contained in:
@@ -139,6 +139,21 @@ type httpConnCtx struct {
|
|||||||
rule *SubnetRule
|
rule *SubnetRule
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConnectionState allows net/http.Server to populate Request.TLS when the
|
||||||
|
// underlying connection is TLS (e.g. *tls.Conn from tls.Server). Without this,
|
||||||
|
// the connection is not *tls.Conn and does not expose ConnectionState through
|
||||||
|
// the net.Conn interface field, so tlsState stays nil and the HTTPS redirect
|
||||||
|
// in handleRequest runs on every request.
|
||||||
|
func (c *httpConnCtx) ConnectionState() tls.ConnectionState {
|
||||||
|
type tlsConn interface {
|
||||||
|
ConnectionState() tls.ConnectionState
|
||||||
|
}
|
||||||
|
if tc, ok := c.Conn.(tlsConn); ok {
|
||||||
|
return tc.ConnectionState()
|
||||||
|
}
|
||||||
|
return tls.ConnectionState{}
|
||||||
|
}
|
||||||
|
|
||||||
// connCtxKey is the unexported context key used to store a *SubnetRule on the
|
// connCtxKey is the unexported context key used to store a *SubnetRule on the
|
||||||
// per-connection context created by http.Server.ConnContext.
|
// per-connection context created by http.Server.ConnContext.
|
||||||
type connCtxKey struct{}
|
type connCtxKey struct{}
|
||||||
|
|||||||
48
netstack2/http_handler_tls_test.go
Normal file
48
netstack2/http_handler_tls_test.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package netstack2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// tlsConnStub is a minimal net.Conn that also exposes TLS state, matching
|
||||||
|
// *tls.Conn's ConnectionState used by net/http.Server.
|
||||||
|
type tlsConnStub struct {
|
||||||
|
net.Conn
|
||||||
|
state tls.ConnectionState
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tlsConnStub) ConnectionState() tls.ConnectionState {
|
||||||
|
return t.state
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHTTPConnCtxForwardsConnectionState(t *testing.T) {
|
||||||
|
c1, c2 := net.Pipe()
|
||||||
|
defer c1.Close()
|
||||||
|
defer c2.Close()
|
||||||
|
|
||||||
|
inner := &tlsConnStub{
|
||||||
|
Conn: c1,
|
||||||
|
state: tls.ConnectionState{Version: tls.VersionTLS12, HandshakeComplete: true},
|
||||||
|
}
|
||||||
|
wrapped := &httpConnCtx{Conn: inner, rule: nil}
|
||||||
|
|
||||||
|
got := wrapped.ConnectionState()
|
||||||
|
if got.Version != tls.VersionTLS12 || !got.HandshakeComplete {
|
||||||
|
t.Fatalf("ConnectionState = %+v, want TLS 1.2 and HandshakeComplete", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHTTPConnCtxConnectionStatePlainTCP(t *testing.T) {
|
||||||
|
c1, c2 := net.Pipe()
|
||||||
|
defer c1.Close()
|
||||||
|
defer c2.Close()
|
||||||
|
|
||||||
|
wrapped := &httpConnCtx{Conn: c1, rule: nil}
|
||||||
|
got := wrapped.ConnectionState()
|
||||||
|
if got.Version != 0 {
|
||||||
|
t.Fatalf("expected zero ConnectionState for plain conn, got %+v", got)
|
||||||
|
}
|
||||||
|
_ = c2
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user