- 分离 Request 的配置态与执行态,修复二次 Do、raw 模式网络配置失效和 body 来源互斥问题 - 新增 starnet trace 抽象,补齐 DNS/连接/TLS/重试事件,并优化动态 transport 缓存与代理解析路径 - 收紧非法代理为 fail-fast,多目标目标回退仅限幂等请求,修复 Host/TLS/SNI 等语义边界 - 补充防御性拷贝、专项回归测试、本地代理/TLS 用例与 README 行为说明
111 lines
2.7 KiB
Go
111 lines
2.7 KiB
Go
package starnet
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
"testing"
|
|
)
|
|
|
|
func TestRequestProxyWithCustomIPTargetsOriginWithoutRewritingProxyDial(t *testing.T) {
|
|
tlsReqInfo := make(chan struct {
|
|
host string
|
|
sni string
|
|
}, 1)
|
|
tlsServer := newIPv4TLSServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
tlsReqInfo <- struct {
|
|
host string
|
|
sni string
|
|
}{
|
|
host: r.Host,
|
|
sni: r.TLS.ServerName,
|
|
}
|
|
_, _ = w.Write([]byte("ok"))
|
|
}))
|
|
defer tlsServer.Close()
|
|
|
|
_, port, err := net.SplitHostPort(tlsServer.Listener.Addr().String())
|
|
if err != nil {
|
|
t.Fatalf("split tls server addr: %v", err)
|
|
}
|
|
|
|
proxyServer := newIPv4ConnectProxyServer(t, nil)
|
|
defer proxyServer.Close()
|
|
|
|
targetHost := "proxy-custom-ip.test"
|
|
reqURL := fmt.Sprintf("https://%s:%s", targetHost, port)
|
|
req := NewSimpleRequest(reqURL, http.MethodGet).
|
|
SetProxy(proxyServer.URL).
|
|
SetCustomIP([]string{"127.0.0.1"}).
|
|
SetSkipTLSVerify(true)
|
|
|
|
resp, err := req.Do()
|
|
if err != nil {
|
|
t.Fatalf("Do error: %v", err)
|
|
}
|
|
defer resp.Close()
|
|
|
|
targets := proxyServer.Targets()
|
|
if len(targets) != 1 {
|
|
t.Fatalf("connect targets=%v; want 1 target", targets)
|
|
}
|
|
gotConnectTarget := targets[0]
|
|
wantConnectTarget := net.JoinHostPort("127.0.0.1", port)
|
|
if gotConnectTarget != wantConnectTarget {
|
|
t.Fatalf("CONNECT target = %q; want %q", gotConnectTarget, wantConnectTarget)
|
|
}
|
|
|
|
gotTLS := <-tlsReqInfo
|
|
wantHost := net.JoinHostPort(targetHost, port)
|
|
if gotTLS.host != wantHost {
|
|
t.Fatalf("request host = %q; want %q", gotTLS.host, wantHost)
|
|
}
|
|
if gotTLS.sni != targetHost {
|
|
t.Fatalf("tls sni = %q; want %q", gotTLS.sni, targetHost)
|
|
}
|
|
}
|
|
|
|
func TestRequestCustomIPPreservesOriginalHostAndSNI(t *testing.T) {
|
|
tlsReqInfo := make(chan struct {
|
|
host string
|
|
sni string
|
|
}, 1)
|
|
tlsServer := newIPv4TLSServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
tlsReqInfo <- struct {
|
|
host string
|
|
sni string
|
|
}{
|
|
host: r.Host,
|
|
sni: r.TLS.ServerName,
|
|
}
|
|
_, _ = w.Write([]byte("ok"))
|
|
}))
|
|
defer tlsServer.Close()
|
|
|
|
_, port, err := net.SplitHostPort(tlsServer.Listener.Addr().String())
|
|
if err != nil {
|
|
t.Fatalf("split tls server addr: %v", err)
|
|
}
|
|
|
|
targetHost := "custom-ip-direct.test"
|
|
reqURL := fmt.Sprintf("https://%s:%s", targetHost, port)
|
|
req := NewSimpleRequest(reqURL, http.MethodGet).
|
|
SetCustomIP([]string{"127.0.0.1"}).
|
|
SetSkipTLSVerify(true)
|
|
|
|
resp, err := req.Do()
|
|
if err != nil {
|
|
t.Fatalf("Do error: %v", err)
|
|
}
|
|
defer resp.Close()
|
|
|
|
gotTLS := <-tlsReqInfo
|
|
wantHost := net.JoinHostPort(targetHost, port)
|
|
if gotTLS.host != wantHost {
|
|
t.Fatalf("request host = %q; want %q", gotTLS.host, wantHost)
|
|
}
|
|
if gotTLS.sni != targetHost {
|
|
t.Fatalf("tls sni = %q; want %q", gotTLS.sni, targetHost)
|
|
}
|
|
}
|