From e996e7c35bf2fe7c633798f5646ecc26af8e8db3 Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Thu, 20 Jun 2019 15:19:42 +0800 Subject: [PATCH] add user-agent option for http/http2 --- chain.go | 5 +++-- client.go | 16 ++++++++++++---- cmd/gost/route.go | 4 ++++ http.go | 6 +++++- http2.go | 7 +++++-- node.go | 6 ++++-- 6 files changed, 33 insertions(+), 11 deletions(-) diff --git a/chain.go b/chain.go index a3d81d1..5b0cd45 100644 --- a/chain.go +++ b/chain.go @@ -150,7 +150,8 @@ func (c *Chain) dialWithOptions(addr string, options *ChainOptions) (net.Conn, e return nil, err } - cc, err := route.LastNode().Client.Connect(conn, ipAddr, AddrConnectOption(addr)) + cOpts := append([]ConnectOption{AddrConnectOption(addr)}, route.LastNode().ConnectOptions...) + cc, err := route.LastNode().Client.Connect(conn, ipAddr, cOpts...) if err != nil { conn.Close() return nil, err @@ -233,7 +234,7 @@ func (c *Chain) getConn() (conn net.Conn, err error) { preNode := node for _, node := range nodes[1:] { var cc net.Conn - cc, err = preNode.Client.Connect(cn, node.Addr) + cc, err = preNode.Client.Connect(cn, node.Addr, preNode.ConnectOptions...) if err != nil { cn.Close() node.MarkDead() diff --git a/client.go b/client.go index 60fc327..7382686 100644 --- a/client.go +++ b/client.go @@ -238,10 +238,11 @@ func QUICConfigHandshakeOption(config *QUICConfig) HandshakeOption { // ConnectOptions describes the options for Connector.Connect. type ConnectOptions struct { - Addr string - Timeout time.Duration - User *url.Userinfo - Selector gosocks5.Selector + Addr string + Timeout time.Duration + User *url.Userinfo + Selector gosocks5.Selector + UserAgent string } // ConnectOption allows a common way to set ConnectOptions. @@ -274,3 +275,10 @@ func SelectorConnectOption(s gosocks5.Selector) ConnectOption { opts.Selector = s } } + +// UserAgentConnectOption specifies the HTTP user-agent header. +func UserAgentConnectOption(ua string) ConnectOption { + return func(opts *ConnectOptions) { + opts.UserAgent = ua + } +} diff --git a/cmd/gost/route.go b/cmd/gost/route.go index b4e358a..ee77d65 100644 --- a/cmd/gost/route.go +++ b/cmd/gost/route.go @@ -209,6 +209,10 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) { gost.TimeoutDialOption(time.Duration(timeout)*time.Second), ) + node.ConnectOptions = []gost.ConnectOption{ + gost.UserAgentConnectOption(node.Get("agent")), + } + if host == "" { host = node.Host } diff --git a/http.go b/http.go index a9de1f5..d307689 100644 --- a/http.go +++ b/http.go @@ -37,6 +37,10 @@ func (c *httpConnector) Connect(conn net.Conn, addr string, options ...ConnectOp if timeout <= 0 { timeout = ConnectTimeout } + ua := opts.UserAgent + if ua == "" { + ua = DefaultUserAgent + } conn.SetDeadline(time.Now().Add(timeout)) defer conn.SetDeadline(time.Time{}) @@ -49,7 +53,7 @@ func (c *httpConnector) Connect(conn net.Conn, addr string, options ...ConnectOp ProtoMinor: 1, Header: make(http.Header), } - req.Header.Set("User-Agent", DefaultUserAgent) + req.Header.Set("User-Agent", ua) req.Header.Set("Proxy-Connection", "keep-alive") user := opts.User diff --git a/http2.go b/http2.go index fd40832..5027d00 100644 --- a/http2.go +++ b/http2.go @@ -38,6 +38,10 @@ func (c *http2Connector) Connect(conn net.Conn, addr string, options ...ConnectO for _, option := range options { option(opts) } + ua := opts.UserAgent + if ua == "" { + ua = DefaultUserAgent + } cc, ok := conn.(*http2ClientConn) if !ok { @@ -56,8 +60,7 @@ func (c *http2Connector) Connect(conn net.Conn, addr string, options ...ConnectO Host: addr, ContentLength: -1, } - // DEPRECATED - //req.Header.Set("Gost-Target", addr) + req.Header.Set("User-Agent", ua) user := opts.User if user == nil { diff --git a/node.go b/node.go index 7d063f3..dc012a1 100644 --- a/node.go +++ b/node.go @@ -28,6 +28,7 @@ type Node struct { Values url.Values DialOptions []DialOption HandshakeOptions []HandshakeOption + ConnectOptions []ConnectOption Client *Client marker *failMarker Bypass *Bypass @@ -129,18 +130,19 @@ func (node *Node) Get(key string) string { return node.Values.Get(key) } -// GetBool likes Get, but convert parameter value to bool. +// GetBool converts node parameter value to bool. func (node *Node) GetBool(key string) bool { b, _ := strconv.ParseBool(node.Values.Get(key)) return b } -// GetInt likes Get, but convert parameter value to int. +// GetInt converts node parameter value to int. func (node *Node) GetInt(key string) int { n, _ := strconv.Atoi(node.Values.Get(key)) return n } +// GetDuration converts node parameter value to time.Duration. func (node *Node) GetDuration(key string) time.Duration { d, _ := time.ParseDuration(node.Values.Get(key)) return d