mirror of https://github.com/ginuerzh/gost
8 changed files with 249 additions and 41 deletions
@ -0,0 +1,127 @@ |
|||
package gost |
|||
|
|||
import ( |
|||
"bufio" |
|||
"bytes" |
|||
"crypto/rand" |
|||
"io" |
|||
"io/ioutil" |
|||
"net/http" |
|||
"net/http/httptest" |
|||
"net/url" |
|||
"testing" |
|||
) |
|||
|
|||
var httpTestHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|||
io.Copy(w, r.Body) |
|||
}) |
|||
|
|||
func httpProxyRoundtrip(urlStr string, cliUser *url.Userinfo, srvUsers []*url.Userinfo, body io.Reader) (statusCode int, recv []byte, err error) { |
|||
ln, err := TCPListener("") |
|||
if err != nil { |
|||
return |
|||
} |
|||
h := HTTPHandler(UsersHandlerOption(srvUsers...)) |
|||
server := &Server{Listener: ln} |
|||
go server.Serve(h) |
|||
|
|||
exitChan := make(chan struct{}) |
|||
defer close(exitChan) |
|||
go func() { |
|||
defer server.Close() |
|||
<-exitChan |
|||
}() |
|||
|
|||
client := &Client{ |
|||
Connector: HTTPConnector(cliUser), |
|||
Transporter: TCPTransporter(), |
|||
} |
|||
conn, err := client.Dial(ln.Addr().String()) |
|||
if err != nil { |
|||
return |
|||
} |
|||
defer conn.Close() |
|||
conn, err = client.Handshake(conn) |
|||
if err != nil { |
|||
return |
|||
} |
|||
url, err := url.Parse(urlStr) |
|||
if err != nil { |
|||
return |
|||
} |
|||
conn, err = client.Connect(conn, url.Host) |
|||
if err != nil { |
|||
return |
|||
} |
|||
req, err := http.NewRequest(http.MethodGet, urlStr, body) |
|||
if err != nil { |
|||
return |
|||
} |
|||
if err = req.Write(conn); err != nil { |
|||
return |
|||
} |
|||
resp, err := http.ReadResponse(bufio.NewReader(conn), req) |
|||
if err != nil { |
|||
return |
|||
} |
|||
defer resp.Body.Close() |
|||
statusCode = resp.StatusCode |
|||
recv, err = ioutil.ReadAll(resp.Body) |
|||
return |
|||
} |
|||
|
|||
var httpProxyTests = []struct { |
|||
url string |
|||
cliUser *url.Userinfo |
|||
srvUsers []*url.Userinfo |
|||
errStr string |
|||
}{ |
|||
{"", nil, nil, ""}, |
|||
{"", nil, []*url.Userinfo{url.User("admin")}, "407 Proxy Authentication Required"}, |
|||
{"", nil, []*url.Userinfo{url.UserPassword("", "123456")}, "407 Proxy Authentication Required"}, |
|||
{"", url.User("admin"), []*url.Userinfo{url.User("test")}, "407 Proxy Authentication Required"}, |
|||
{"", url.User("admin"), []*url.Userinfo{url.UserPassword("admin", "123456")}, "407 Proxy Authentication Required"}, |
|||
{"", url.User("admin"), []*url.Userinfo{url.User("admin")}, ""}, |
|||
{"", url.User("admin"), []*url.Userinfo{url.UserPassword("admin", "")}, ""}, |
|||
{"", url.UserPassword("admin", "123456"), nil, ""}, |
|||
{"", url.UserPassword("admin", "123456"), []*url.Userinfo{url.User("admin")}, ""}, |
|||
{"", url.UserPassword("admin", "123456"), []*url.Userinfo{url.UserPassword("", "123456")}, ""}, |
|||
{"", url.UserPassword("", "123456"), []*url.Userinfo{url.UserPassword("", "123456")}, ""}, |
|||
{"", url.UserPassword("admin", "123456"), []*url.Userinfo{url.UserPassword("admin", "123456")}, ""}, |
|||
{"", url.UserPassword("admin", "123456"), []*url.Userinfo{url.UserPassword("user", "pass"), url.UserPassword("admin", "123456")}, ""}, |
|||
{"http://:0", nil, nil, "503 Service unavailable"}, |
|||
} |
|||
|
|||
func TestHTTPProxy(t *testing.T) { |
|||
Debug = true |
|||
httpSrv := httptest.NewServer(httpTestHandler) |
|||
defer httpSrv.Close() |
|||
|
|||
for _, test := range httpProxyTests { |
|||
send := make([]byte, 16) |
|||
rand.Read(send) |
|||
urlStr := test.url |
|||
if urlStr == "" { |
|||
urlStr = httpSrv.URL |
|||
} |
|||
_, recv, err := httpProxyRoundtrip(urlStr, test.cliUser, test.srvUsers, bytes.NewReader(send)) |
|||
if err == nil { |
|||
if test.errStr != "" { |
|||
t.Errorf("HTTP proxy response should failed with error %s", test.errStr) |
|||
continue |
|||
} |
|||
} else { |
|||
if test.errStr == "" { |
|||
t.Errorf("HTTP proxy got error %v", err) |
|||
} |
|||
if err.Error() != test.errStr { |
|||
t.Errorf("HTTP proxy got error %v, want %v", err, test.errStr) |
|||
} |
|||
continue |
|||
} |
|||
if !bytes.Equal(send, recv) { |
|||
t.Errorf("got %v, want %v", recv, send) |
|||
continue |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
package gost |
|||
|
|||
import "testing" |
|||
import "net/url" |
|||
|
|||
var nodeTests = []struct { |
|||
in string |
|||
out Node |
|||
hasError bool |
|||
}{ |
|||
{"", Node{}, false}, |
|||
{"://", Node{}, true}, |
|||
{"localhost", Node{Addr: "localhost", Transport: "tcp"}, false}, |
|||
{":", Node{Addr: ":", Transport: "tcp"}, false}, |
|||
{":8080", Node{Addr: ":8080", Transport: "tcp"}, false}, |
|||
{"http://:8080", Node{Addr: ":8080", Protocol: "http", Transport: "tcp"}, false}, |
|||
{"http://localhost:8080", Node{Addr: "localhost:8080", Protocol: "http", Transport: "tcp"}, false}, |
|||
{"http://admin:123456@:8080", Node{Addr: ":8080", Protocol: "http", Transport: "tcp", User: url.UserPassword("admin", "123456")}, false}, |
|||
{"http://admin@localhost:8080", Node{Addr: "localhost:8080", Protocol: "http", Transport: "tcp", User: url.User("admin")}, false}, |
|||
{"http://:123456@localhost:8080", Node{Addr: "localhost:8080", Protocol: "http", Transport: "tcp", User: url.UserPassword("", "123456")}, false}, |
|||
{"http://@localhost:8080", Node{Addr: "localhost:8080", Protocol: "http", Transport: "tcp", User: url.User("")}, false}, |
|||
{"http://:@localhost:8080", Node{Addr: "localhost:8080", Protocol: "http", Transport: "tcp", User: url.UserPassword("", "")}, false}, |
|||
{"https://:8080", Node{Addr: ":8080", Protocol: "http", Transport: "tls"}, false}, |
|||
{"socks+tls://:8080", Node{Addr: ":8080", Protocol: "socks5", Transport: "tls"}, false}, |
|||
{"tls://:8080", Node{Addr: ":8080", Transport: "tls"}, false}, |
|||
{"tcp://:8080/:8081", Node{Addr: ":8080", Remote: ":8081", Protocol: "tcp", Transport: "tcp"}, false}, |
|||
{"udp://:8080/:8081", Node{Addr: ":8080", Remote: ":8081", Protocol: "udp", Transport: "udp"}, false}, |
|||
{"rtcp://:8080/:8081", Node{Addr: ":8080", Remote: ":8081", Protocol: "rtcp", Transport: "rtcp"}, false}, |
|||
{"rudp://:8080/:8081", Node{Addr: ":8080", Remote: ":8081", Protocol: "rudp", Transport: "rudp"}, false}, |
|||
{"redirect://:8080", Node{Addr: ":8080", Protocol: "redirect", Transport: "tcp"}, false}, |
|||
} |
|||
|
|||
func TestParseNode(t *testing.T) { |
|||
for _, test := range nodeTests { |
|||
actual, err := ParseNode(test.in) |
|||
if err != nil { |
|||
if test.hasError { |
|||
t.Logf("ParseNode(%q) got expected error: %v", test.in, err) |
|||
continue |
|||
} |
|||
t.Errorf("ParseNode(%q) got error: %v", test.in, err) |
|||
} else { |
|||
if test.hasError { |
|||
t.Errorf("ParseNode(%q) got %v, but should return error", test.in, actual) |
|||
continue |
|||
} |
|||
if actual.Addr != test.out.Addr || actual.Protocol != test.out.Protocol || |
|||
actual.Transport != test.out.Transport || actual.Remote != test.out.Remote { |
|||
t.Errorf("ParseNode(%q) got %v, want %v", test.in, actual, test.out) |
|||
} |
|||
if actual.User == nil { |
|||
if test.out.User != nil { |
|||
t.Errorf("ParseNode(%q) got %v, want %v", test.in, actual, test.out) |
|||
} |
|||
continue |
|||
} |
|||
if actual.User != nil { |
|||
if test.out.User == nil { |
|||
t.Errorf("ParseNode(%q) got %v, want %v", test.in, actual, test.out) |
|||
continue |
|||
} |
|||
if *actual.User != *test.out.User { |
|||
t.Errorf("ParseNode(%q) got %v, want %v", test.in, actual, test.out) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue