mirror of https://github.com/fatedier/frp
fatedier
3 years ago
committed by
GitHub
45 changed files with 1734 additions and 1951 deletions
@ -0,0 +1,65 @@
|
||||
package basic |
||||
|
||||
import ( |
||||
"fmt" |
||||
"time" |
||||
|
||||
"github.com/fatedier/frp/test/e2e/framework" |
||||
|
||||
. "github.com/onsi/ginkgo" |
||||
) |
||||
|
||||
var _ = Describe("[Feature: Chaos]", func() { |
||||
f := framework.NewDefaultFramework() |
||||
|
||||
It("reconnect after frps restart", func() { |
||||
serverPort := f.AllocPort() |
||||
serverConfigPath := f.GenerateConfigFile(fmt.Sprintf(` |
||||
[common] |
||||
bind_addr = 0.0.0.0 |
||||
bind_port = %d |
||||
`, serverPort)) |
||||
|
||||
remotePort := f.AllocPort() |
||||
clientConfigPath := f.GenerateConfigFile(fmt.Sprintf(` |
||||
[common] |
||||
server_port = %d |
||||
log_level = trace |
||||
|
||||
[tcp] |
||||
type = tcp |
||||
local_port = %d |
||||
remote_port = %d |
||||
`, serverPort, f.PortByName(framework.TCPEchoServerPort), remotePort)) |
||||
|
||||
// 1. start frps and frpc, expect request success
|
||||
ps, _, err := f.RunFrps("-c", serverConfigPath) |
||||
framework.ExpectNoError(err) |
||||
|
||||
pc, _, err := f.RunFrpc("-c", clientConfigPath) |
||||
framework.ExpectNoError(err) |
||||
framework.NewRequestExpect(f).Port(remotePort).Ensure() |
||||
|
||||
// 2. stop frps, expect request failed
|
||||
ps.Stop() |
||||
time.Sleep(200 * time.Millisecond) |
||||
framework.NewRequestExpect(f).Port(remotePort).ExpectError(true).Ensure() |
||||
|
||||
// 3. restart frps, expect request success
|
||||
_, _, err = f.RunFrps("-c", serverConfigPath) |
||||
framework.ExpectNoError(err) |
||||
time.Sleep(2 * time.Second) |
||||
framework.NewRequestExpect(f).Port(remotePort).Ensure() |
||||
|
||||
// 4. stop frpc, expect request failed
|
||||
pc.Stop() |
||||
time.Sleep(200 * time.Millisecond) |
||||
framework.NewRequestExpect(f).Port(remotePort).ExpectError(true).Ensure() |
||||
|
||||
// 5. restart frpc, expect request success
|
||||
_, _, err = f.RunFrpc("-c", clientConfigPath) |
||||
framework.ExpectNoError(err) |
||||
time.Sleep(time.Second) |
||||
framework.NewRequestExpect(f).Port(remotePort).Ensure() |
||||
}) |
||||
}) |
@ -0,0 +1,78 @@
|
||||
package basic |
||||
|
||||
import ( |
||||
"fmt" |
||||
"strconv" |
||||
"strings" |
||||
"time" |
||||
|
||||
"github.com/fatedier/frp/test/e2e/framework" |
||||
"github.com/fatedier/frp/test/e2e/framework/consts" |
||||
clientsdk "github.com/fatedier/frp/test/e2e/pkg/sdk/client" |
||||
|
||||
. "github.com/onsi/ginkgo" |
||||
) |
||||
|
||||
var _ = Describe("[Feature: ClientManage]", func() { |
||||
f := framework.NewDefaultFramework() |
||||
|
||||
It("Update && Reload API", func() { |
||||
serverConf := consts.DefaultServerConfig |
||||
|
||||
adminPort := f.AllocPort() |
||||
|
||||
p1Port := f.AllocPort() |
||||
p2Port := f.AllocPort() |
||||
p3Port := f.AllocPort() |
||||
|
||||
clientConf := consts.DefaultClientConfig + fmt.Sprintf(` |
||||
admin_port = %d |
||||
|
||||
[p1] |
||||
type = tcp |
||||
local_port = {{ .%s }} |
||||
remote_port = %d |
||||
|
||||
[p2] |
||||
type = tcp |
||||
local_port = {{ .%s }} |
||||
remote_port = %d |
||||
|
||||
[p3] |
||||
type = tcp |
||||
local_port = {{ .%s }} |
||||
remote_port = %d |
||||
`, adminPort, |
||||
framework.TCPEchoServerPort, p1Port, |
||||
framework.TCPEchoServerPort, p2Port, |
||||
framework.TCPEchoServerPort, p3Port) |
||||
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf}) |
||||
|
||||
framework.NewRequestExpect(f).Port(p1Port).Ensure() |
||||
framework.NewRequestExpect(f).Port(p2Port).Ensure() |
||||
framework.NewRequestExpect(f).Port(p3Port).Ensure() |
||||
|
||||
client := clientsdk.New("127.0.0.1", adminPort) |
||||
conf, err := client.GetConfig() |
||||
framework.ExpectNoError(err) |
||||
|
||||
newP2Port := f.AllocPort() |
||||
// change p2 port and remove p3 proxy
|
||||
newClientConf := strings.ReplaceAll(conf, strconv.Itoa(p2Port), strconv.Itoa(newP2Port)) |
||||
p3Index := strings.Index(newClientConf, "[p3]") |
||||
newClientConf = newClientConf[:p3Index] |
||||
|
||||
err = client.UpdateConfig(newClientConf) |
||||
framework.ExpectNoError(err) |
||||
|
||||
err = client.Reload() |
||||
framework.ExpectNoError(err) |
||||
time.Sleep(time.Second) |
||||
|
||||
framework.NewRequestExpect(f).Port(p1Port).Explain("p1 port").Ensure() |
||||
framework.NewRequestExpect(f).Port(p2Port).Explain("original p2 port").ExpectError(true).Ensure() |
||||
framework.NewRequestExpect(f).Port(newP2Port).Explain("new p2 port").Ensure() |
||||
framework.NewRequestExpect(f).Port(p3Port).Explain("p3 port").ExpectError(true).Ensure() |
||||
}) |
||||
}) |
@ -0,0 +1,113 @@
|
||||
package basic |
||||
|
||||
import ( |
||||
"fmt" |
||||
"strconv" |
||||
"strings" |
||||
|
||||
"github.com/fatedier/frp/test/e2e/framework" |
||||
"github.com/fatedier/frp/test/e2e/pkg/request" |
||||
|
||||
. "github.com/onsi/ginkgo" |
||||
) |
||||
|
||||
const ( |
||||
ConfigValidStr = "syntax is ok" |
||||
) |
||||
|
||||
var _ = Describe("[Feature: Cmd]", func() { |
||||
f := framework.NewDefaultFramework() |
||||
|
||||
Describe("Verify", func() { |
||||
It("frps valid", func() { |
||||
path := f.GenerateConfigFile(` |
||||
[common] |
||||
bind_addr = 0.0.0.0 |
||||
bind_port = 7000 |
||||
`) |
||||
_, output, err := f.RunFrps("verify", "-c", path) |
||||
framework.ExpectNoError(err) |
||||
framework.ExpectTrue(strings.Contains(output, ConfigValidStr), "output: %s", output) |
||||
}) |
||||
It("frps invalid", func() { |
||||
path := f.GenerateConfigFile(` |
||||
[common] |
||||
bind_addr = 0.0.0.0 |
||||
bind_port = 70000 |
||||
`) |
||||
_, output, err := f.RunFrps("verify", "-c", path) |
||||
framework.ExpectNoError(err) |
||||
framework.ExpectTrue(!strings.Contains(output, ConfigValidStr), "output: %s", output) |
||||
}) |
||||
It("frpc valid", func() { |
||||
path := f.GenerateConfigFile(` |
||||
[common] |
||||
server_addr = 0.0.0.0 |
||||
server_port = 7000 |
||||
`) |
||||
_, output, err := f.RunFrpc("verify", "-c", path) |
||||
framework.ExpectNoError(err) |
||||
framework.ExpectTrue(strings.Contains(output, ConfigValidStr), "output: %s", output) |
||||
}) |
||||
It("frpc invalid", func() { |
||||
path := f.GenerateConfigFile(` |
||||
[common] |
||||
server_addr = 0.0.0.0 |
||||
server_port = 7000 |
||||
protocol = invalid |
||||
`) |
||||
_, output, err := f.RunFrpc("verify", "-c", path) |
||||
framework.ExpectNoError(err) |
||||
framework.ExpectTrue(!strings.Contains(output, ConfigValidStr), "output: %s", output) |
||||
}) |
||||
}) |
||||
|
||||
Describe("Single proxy", func() { |
||||
It("TCP", func() { |
||||
serverPort := f.AllocPort() |
||||
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort)) |
||||
framework.ExpectNoError(err) |
||||
|
||||
localPort := f.PortByName(framework.TCPEchoServerPort) |
||||
remotePort := f.AllocPort() |
||||
_, _, err = f.RunFrpc("tcp", "-s", fmt.Sprintf("127.0.0.1:%d", serverPort), "-t", "123", "-u", "test", |
||||
"-l", strconv.Itoa(localPort), "-r", strconv.Itoa(remotePort), "-n", "tcp_test") |
||||
framework.ExpectNoError(err) |
||||
|
||||
framework.NewRequestExpect(f).Port(remotePort).Ensure() |
||||
}) |
||||
|
||||
It("UDP", func() { |
||||
serverPort := f.AllocPort() |
||||
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort)) |
||||
framework.ExpectNoError(err) |
||||
|
||||
localPort := f.PortByName(framework.UDPEchoServerPort) |
||||
remotePort := f.AllocPort() |
||||
_, _, err = f.RunFrpc("udp", "-s", fmt.Sprintf("127.0.0.1:%d", serverPort), "-t", "123", "-u", "test", |
||||
"-l", strconv.Itoa(localPort), "-r", strconv.Itoa(remotePort), "-n", "udp_test") |
||||
framework.ExpectNoError(err) |
||||
|
||||
framework.NewRequestExpect(f).Protocol("udp"). |
||||
Port(remotePort).Ensure() |
||||
}) |
||||
|
||||
It("HTTP", func() { |
||||
serverPort := f.AllocPort() |
||||
vhostHTTPPort := f.AllocPort() |
||||
_, _, err := f.RunFrps("-t", "123", "-p", strconv.Itoa(serverPort), "--vhost_http_port", strconv.Itoa(vhostHTTPPort)) |
||||
framework.ExpectNoError(err) |
||||
|
||||
_, _, err = f.RunFrpc("http", "-s", "127.0.0.1:"+strconv.Itoa(serverPort), "-t", "123", "-u", "test", |
||||
"-n", "udp_test", "-l", strconv.Itoa(f.PortByName(framework.HTTPSimpleServerPort)), |
||||
"--custom_domain", "test.example.com") |
||||
framework.ExpectNoError(err) |
||||
|
||||
framework.NewRequestExpect(f).Port(vhostHTTPPort). |
||||
RequestModify(func(r *request.Request) { |
||||
r.HTTP().HTTPHost("test.example.com") |
||||
}). |
||||
Ensure() |
||||
}) |
||||
}) |
||||
}) |
@ -0,0 +1,83 @@
|
||||
package basic |
||||
|
||||
import ( |
||||
"fmt" |
||||
|
||||
"github.com/fatedier/frp/test/e2e/framework" |
||||
"github.com/fatedier/frp/test/e2e/framework/consts" |
||||
"github.com/fatedier/frp/test/e2e/pkg/port" |
||||
|
||||
. "github.com/onsi/ginkgo" |
||||
) |
||||
|
||||
var _ = Describe("[Feature: Config]", func() { |
||||
f := framework.NewDefaultFramework() |
||||
|
||||
Describe("Template", func() { |
||||
It("render by env", func() { |
||||
serverConf := consts.DefaultServerConfig |
||||
clientConf := consts.DefaultClientConfig |
||||
|
||||
portName := port.GenName("TCP") |
||||
serverConf += fmt.Sprintf(` |
||||
token = {{ %s{{ .Envs.FRP_TOKEN }}%s }} |
||||
`, "`", "`") |
||||
|
||||
clientConf += fmt.Sprintf(` |
||||
token = {{ %s{{ .Envs.FRP_TOKEN }}%s }} |
||||
|
||||
[tcp] |
||||
type = tcp |
||||
local_port = {{ .%s }} |
||||
remote_port = {{ .%s }} |
||||
`, "`", "`", framework.TCPEchoServerPort, portName) |
||||
|
||||
f.SetEnvs([]string{"FRP_TOKEN=123"}) |
||||
f.RunProcesses([]string{serverConf}, []string{clientConf}) |
||||
|
||||
framework.NewRequestExpect(f).PortName(portName).Ensure() |
||||
}) |
||||
}) |
||||
|
||||
Describe("Includes", func() { |
||||
It("split tcp proxies into different files", func() { |
||||
serverPort := f.AllocPort() |
||||
serverConfigPath := f.GenerateConfigFile(fmt.Sprintf(` |
||||
[common] |
||||
bind_addr = 0.0.0.0 |
||||
bind_port = %d |
||||
`, serverPort)) |
||||
|
||||
remotePort := f.AllocPort() |
||||
proxyConfigPath := f.GenerateConfigFile(fmt.Sprintf(` |
||||
[tcp] |
||||
type = tcp |
||||
local_port = %d |
||||
remote_port = %d |
||||
`, f.PortByName(framework.TCPEchoServerPort), remotePort)) |
||||
|
||||
remotePort2 := f.AllocPort() |
||||
proxyConfigPath2 := f.GenerateConfigFile(fmt.Sprintf(` |
||||
[tcp2] |
||||
type = tcp |
||||
local_port = %d |
||||
remote_port = %d |
||||
`, f.PortByName(framework.TCPEchoServerPort), remotePort2)) |
||||
|
||||
clientConfigPath := f.GenerateConfigFile(fmt.Sprintf(` |
||||
[common] |
||||
server_port = %d |
||||
includes = %s,%s |
||||
`, serverPort, proxyConfigPath, proxyConfigPath2)) |
||||
|
||||
_, _, err := f.RunFrps("-c", serverConfigPath) |
||||
framework.ExpectNoError(err) |
||||
|
||||
_, _, err = f.RunFrpc("-c", clientConfigPath) |
||||
framework.ExpectNoError(err) |
||||
|
||||
framework.NewRequestExpect(f).Port(remotePort).Ensure() |
||||
framework.NewRequestExpect(f).Port(remotePort2).Ensure() |
||||
}) |
||||
}) |
||||
}) |
@ -0,0 +1,238 @@
|
||||
package basic |
||||
|
||||
import ( |
||||
"fmt" |
||||
"strconv" |
||||
"sync" |
||||
"time" |
||||
|
||||
"github.com/fatedier/frp/test/e2e/framework" |
||||
"github.com/fatedier/frp/test/e2e/framework/consts" |
||||
"github.com/fatedier/frp/test/e2e/mock/server/httpserver" |
||||
"github.com/fatedier/frp/test/e2e/mock/server/streamserver" |
||||
"github.com/fatedier/frp/test/e2e/pkg/request" |
||||
|
||||
. "github.com/onsi/ginkgo" |
||||
) |
||||
|
||||
var _ = Describe("[Feature: Group]", func() { |
||||
f := framework.NewDefaultFramework() |
||||
|
||||
newHTTPServer := func(port int, respContent string) *httpserver.Server { |
||||
return httpserver.New( |
||||
httpserver.WithBindPort(port), |
||||
httpserver.WithHandler(framework.SpecifiedHTTPBodyHandler([]byte(respContent))), |
||||
) |
||||
} |
||||
|
||||
validateFooBarResponse := func(resp *request.Response) bool { |
||||
if string(resp.Content) == "foo" || string(resp.Content) == "bar" { |
||||
return true |
||||
} |
||||
return false |
||||
} |
||||
|
||||
doFooBarHTTPRequest := func(vhostPort int, host string) []string { |
||||
results := []string{} |
||||
var wait sync.WaitGroup |
||||
var mu sync.Mutex |
||||
expectFn := func() { |
||||
framework.NewRequestExpect(f).Port(vhostPort). |
||||
RequestModify(func(r *request.Request) { |
||||
r.HTTP().HTTPHost(host) |
||||
}). |
||||
Ensure(validateFooBarResponse, func(resp *request.Response) bool { |
||||
mu.Lock() |
||||
defer mu.Unlock() |
||||
results = append(results, string(resp.Content)) |
||||
return true |
||||
}) |
||||
} |
||||
for i := 0; i < 10; i++ { |
||||
wait.Add(1) |
||||
go func() { |
||||
defer wait.Done() |
||||
expectFn() |
||||
}() |
||||
} |
||||
|
||||
wait.Wait() |
||||
return results |
||||
} |
||||
|
||||
Describe("Load Balancing", func() { |
||||
It("TCP", func() { |
||||
serverConf := consts.DefaultServerConfig |
||||
clientConf := consts.DefaultClientConfig |
||||
|
||||
fooPort := f.AllocPort() |
||||
fooServer := streamserver.New(streamserver.TCP, streamserver.WithBindPort(fooPort), streamserver.WithRespContent([]byte("foo"))) |
||||
f.RunServer("", fooServer) |
||||
|
||||
barPort := f.AllocPort() |
||||
barServer := streamserver.New(streamserver.TCP, streamserver.WithBindPort(barPort), streamserver.WithRespContent([]byte("bar"))) |
||||
f.RunServer("", barServer) |
||||
|
||||
remotePort := f.AllocPort() |
||||
clientConf += fmt.Sprintf(` |
||||
[foo] |
||||
type = tcp |
||||
local_port = %d |
||||
remote_port = %d |
||||
group = test |
||||
group_key = 123 |
||||
|
||||
[bar] |
||||
type = tcp |
||||
local_port = %d |
||||
remote_port = %d |
||||
group = test |
||||
group_key = 123 |
||||
`, fooPort, remotePort, barPort, remotePort) |
||||
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf}) |
||||
|
||||
fooCount := 0 |
||||
barCount := 0 |
||||
for i := 0; i < 10; i++ { |
||||
framework.NewRequestExpect(f).Explain("times " + strconv.Itoa(i)).Port(remotePort).Ensure(func(resp *request.Response) bool { |
||||
switch string(resp.Content) { |
||||
case "foo": |
||||
fooCount++ |
||||
case "bar": |
||||
barCount++ |
||||
default: |
||||
return false |
||||
} |
||||
return true |
||||
}) |
||||
} |
||||
|
||||
framework.ExpectTrue(fooCount > 1 && barCount > 1, "fooCount: %d, barCount: %d", fooCount, barCount) |
||||
}) |
||||
}) |
||||
|
||||
Describe("Health Check", func() { |
||||
It("TCP", func() { |
||||
serverConf := consts.DefaultServerConfig |
||||
clientConf := consts.DefaultClientConfig |
||||
|
||||
fooPort := f.AllocPort() |
||||
fooServer := streamserver.New(streamserver.TCP, streamserver.WithBindPort(fooPort), streamserver.WithRespContent([]byte("foo"))) |
||||
f.RunServer("", fooServer) |
||||
|
||||
barPort := f.AllocPort() |
||||
barServer := streamserver.New(streamserver.TCP, streamserver.WithBindPort(barPort), streamserver.WithRespContent([]byte("bar"))) |
||||
f.RunServer("", barServer) |
||||
|
||||
remotePort := f.AllocPort() |
||||
clientConf += fmt.Sprintf(` |
||||
[foo] |
||||
type = tcp |
||||
local_port = %d |
||||
remote_port = %d |
||||
group = test |
||||
group_key = 123 |
||||
health_check_type = tcp |
||||
health_check_interval_s = 1 |
||||
|
||||
[bar] |
||||
type = tcp |
||||
local_port = %d |
||||
remote_port = %d |
||||
group = test |
||||
group_key = 123 |
||||
health_check_type = tcp |
||||
health_check_interval_s = 1 |
||||
`, fooPort, remotePort, barPort, remotePort) |
||||
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf}) |
||||
|
||||
// check foo and bar is ok
|
||||
results := []string{} |
||||
for i := 0; i < 10; i++ { |
||||
framework.NewRequestExpect(f).Port(remotePort).Ensure(validateFooBarResponse, func(resp *request.Response) bool { |
||||
results = append(results, string(resp.Content)) |
||||
return true |
||||
}) |
||||
} |
||||
framework.ExpectContainElements(results, []string{"foo", "bar"}) |
||||
|
||||
// close bar server, check foo is ok
|
||||
barServer.Close() |
||||
time.Sleep(2 * time.Second) |
||||
for i := 0; i < 10; i++ { |
||||
framework.NewRequestExpect(f).Port(remotePort).ExpectResp([]byte("foo")).Ensure() |
||||
} |
||||
|
||||
// resume bar server, check foo and bar is ok
|
||||
f.RunServer("", barServer) |
||||
time.Sleep(2 * time.Second) |
||||
results = []string{} |
||||
for i := 0; i < 10; i++ { |
||||
framework.NewRequestExpect(f).Port(remotePort).Ensure(validateFooBarResponse, func(resp *request.Response) bool { |
||||
results = append(results, string(resp.Content)) |
||||
return true |
||||
}) |
||||
} |
||||
framework.ExpectContainElements(results, []string{"foo", "bar"}) |
||||
}) |
||||
|
||||
It("HTTP", func() { |
||||
vhostPort := f.AllocPort() |
||||
serverConf := consts.DefaultServerConfig + fmt.Sprintf(` |
||||
vhost_http_port = %d |
||||
`, vhostPort) |
||||
clientConf := consts.DefaultClientConfig |
||||
|
||||
fooPort := f.AllocPort() |
||||
fooServer := newHTTPServer(fooPort, "foo") |
||||
f.RunServer("", fooServer) |
||||
|
||||
barPort := f.AllocPort() |
||||
barServer := newHTTPServer(barPort, "bar") |
||||
f.RunServer("", barServer) |
||||
|
||||
clientConf += fmt.Sprintf(` |
||||
[foo] |
||||
type = http |
||||
local_port = %d |
||||
custom_domains = example.com |
||||
group = test |
||||
group_key = 123 |
||||
health_check_type = http |
||||
health_check_interval_s = 1 |
||||
health_check_url = /healthz |
||||
|
||||
[bar] |
||||
type = http |
||||
local_port = %d |
||||
custom_domains = example.com |
||||
group = test |
||||
group_key = 123 |
||||
health_check_type = http |
||||
health_check_interval_s = 1 |
||||
health_check_url = /healthz |
||||
`, fooPort, barPort) |
||||
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf}) |
||||
|
||||
// check foo and bar is ok
|
||||
results := doFooBarHTTPRequest(vhostPort, "example.com") |
||||
framework.ExpectContainElements(results, []string{"foo", "bar"}) |
||||
|
||||
// close bar server, check foo is ok
|
||||
barServer.Close() |
||||
time.Sleep(2 * time.Second) |
||||
results = doFooBarHTTPRequest(vhostPort, "example.com") |
||||
framework.ExpectContainElements(results, []string{"foo"}) |
||||
framework.ExpectNotContainElements(results, []string{"bar"}) |
||||
|
||||
// resume bar server, check foo and bar is ok
|
||||
f.RunServer("", barServer) |
||||
time.Sleep(2 * time.Second) |
||||
results = doFooBarHTTPRequest(vhostPort, "example.com") |
||||
framework.ExpectContainElements(results, []string{"foo", "bar"}) |
||||
}) |
||||
}) |
||||
}) |
@ -0,0 +1,326 @@
|
||||
package basic |
||||
|
||||
import ( |
||||
"fmt" |
||||
"net/http" |
||||
"net/url" |
||||
"strconv" |
||||
|
||||
"github.com/fatedier/frp/test/e2e/framework" |
||||
"github.com/fatedier/frp/test/e2e/framework/consts" |
||||
"github.com/fatedier/frp/test/e2e/mock/server/httpserver" |
||||
"github.com/fatedier/frp/test/e2e/pkg/request" |
||||
"github.com/fatedier/frp/test/e2e/pkg/utils" |
||||
|
||||
"github.com/gorilla/websocket" |
||||
. "github.com/onsi/ginkgo" |
||||
) |
||||
|
||||
var _ = Describe("[Feature: HTTP]", func() { |
||||
f := framework.NewDefaultFramework() |
||||
|
||||
getDefaultServerConf := func(vhostHTTPPort int) string { |
||||
conf := consts.DefaultServerConfig + ` |
||||
vhost_http_port = %d |
||||
` |
||||
return fmt.Sprintf(conf, vhostHTTPPort) |
||||
} |
||||
newHTTPServer := func(port int, respContent string) *httpserver.Server { |
||||
return httpserver.New( |
||||
httpserver.WithBindPort(port), |
||||
httpserver.WithHandler(framework.SpecifiedHTTPBodyHandler([]byte(respContent))), |
||||
) |
||||
} |
||||
|
||||
It("HTTP route by locations", func() { |
||||
vhostHTTPPort := f.AllocPort() |
||||
serverConf := getDefaultServerConf(vhostHTTPPort) |
||||
|
||||
fooPort := f.AllocPort() |
||||
f.RunServer("", newHTTPServer(fooPort, "foo")) |
||||
|
||||
barPort := f.AllocPort() |
||||
f.RunServer("", newHTTPServer(barPort, "bar")) |
||||
|
||||
clientConf := consts.DefaultClientConfig |
||||
clientConf += fmt.Sprintf(` |
||||
[foo] |
||||
type = http |
||||
local_port = %d |
||||
custom_domains = normal.example.com |
||||
locations = /,/foo |
||||
|
||||
[bar] |
||||
type = http |
||||
local_port = %d |
||||
custom_domains = normal.example.com |
||||
locations = /bar |
||||
`, fooPort, barPort) |
||||
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf}) |
||||
|
||||
// foo path
|
||||
framework.NewRequestExpect(f).Explain("foo path").Port(vhostHTTPPort). |
||||
RequestModify(func(r *request.Request) { |
||||
r.HTTP().HTTPHost("normal.example.com").HTTPPath("/foo") |
||||
}). |
||||
ExpectResp([]byte("foo")). |
||||
Ensure() |
||||
|
||||
// bar path
|
||||
framework.NewRequestExpect(f).Explain("bar path").Port(vhostHTTPPort). |
||||
RequestModify(func(r *request.Request) { |
||||
r.HTTP().HTTPHost("normal.example.com").HTTPPath("/bar") |
||||
}). |
||||
ExpectResp([]byte("bar")). |
||||
Ensure() |
||||
|
||||
// other path
|
||||
framework.NewRequestExpect(f).Explain("other path").Port(vhostHTTPPort). |
||||
RequestModify(func(r *request.Request) { |
||||
r.HTTP().HTTPHost("normal.example.com").HTTPPath("/other") |
||||
}). |
||||
ExpectResp([]byte("foo")). |
||||
Ensure() |
||||
}) |
||||
|
||||
It("HTTP Basic Auth", func() { |
||||
vhostHTTPPort := f.AllocPort() |
||||
serverConf := getDefaultServerConf(vhostHTTPPort) |
||||
|
||||
clientConf := consts.DefaultClientConfig |
||||
clientConf += fmt.Sprintf(` |
||||
[test] |
||||
type = http |
||||
local_port = {{ .%s }} |
||||
custom_domains = normal.example.com |
||||
http_user = test |
||||
http_pwd = test |
||||
`, framework.HTTPSimpleServerPort) |
||||
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf}) |
||||
|
||||
// not set auth header
|
||||
framework.NewRequestExpect(f).Port(vhostHTTPPort). |
||||
RequestModify(func(r *request.Request) { |
||||
r.HTTP().HTTPHost("normal.example.com") |
||||
}). |
||||
Ensure(framework.ExpectResponseCode(401)) |
||||
|
||||
// set incorrect auth header
|
||||
framework.NewRequestExpect(f).Port(vhostHTTPPort). |
||||
RequestModify(func(r *request.Request) { |
||||
r.HTTP().HTTPHost("normal.example.com").HTTPHeaders(map[string]string{ |
||||
"Authorization": utils.BasicAuth("test", "invalid"), |
||||
}) |
||||
}). |
||||
Ensure(framework.ExpectResponseCode(401)) |
||||
|
||||
// set correct auth header
|
||||
framework.NewRequestExpect(f).Port(vhostHTTPPort). |
||||
RequestModify(func(r *request.Request) { |
||||
r.HTTP().HTTPHost("normal.example.com").HTTPHeaders(map[string]string{ |
||||
"Authorization": utils.BasicAuth("test", "test"), |
||||
}) |
||||
}). |
||||
Ensure() |
||||
}) |
||||
|
||||
It("Wildcard domain", func() { |
||||
vhostHTTPPort := f.AllocPort() |
||||
serverConf := getDefaultServerConf(vhostHTTPPort) |
||||
|
||||
clientConf := consts.DefaultClientConfig |
||||
clientConf += fmt.Sprintf(` |
||||
[test] |
||||
type = http |
||||
local_port = {{ .%s }} |
||||
custom_domains = *.example.com |
||||
`, framework.HTTPSimpleServerPort) |
||||
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf}) |
||||
|
||||
// not match host
|
||||
framework.NewRequestExpect(f).Port(vhostHTTPPort). |
||||
RequestModify(func(r *request.Request) { |
||||
r.HTTP().HTTPHost("not-match.test.com") |
||||
}). |
||||
Ensure(framework.ExpectResponseCode(404)) |
||||
|
||||
// test.example.com match *.example.com
|
||||
framework.NewRequestExpect(f).Port(vhostHTTPPort). |
||||
RequestModify(func(r *request.Request) { |
||||
r.HTTP().HTTPHost("test.example.com") |
||||
}). |
||||
Ensure() |
||||
|
||||
// sub.test.example.com match *.example.com
|
||||
framework.NewRequestExpect(f).Port(vhostHTTPPort). |
||||
RequestModify(func(r *request.Request) { |
||||
r.HTTP().HTTPHost("sub.test.example.com") |
||||
}). |
||||
Ensure() |
||||
}) |
||||
|
||||
It("Subdomain", func() { |
||||
vhostHTTPPort := f.AllocPort() |
||||
serverConf := getDefaultServerConf(vhostHTTPPort) |
||||
serverConf += ` |
||||
subdomain_host = example.com |
||||
` |
||||
|
||||
fooPort := f.AllocPort() |
||||
f.RunServer("", newHTTPServer(fooPort, "foo")) |
||||
|
||||
barPort := f.AllocPort() |
||||
f.RunServer("", newHTTPServer(barPort, "bar")) |
||||
|
||||
clientConf := consts.DefaultClientConfig |
||||
clientConf += fmt.Sprintf(` |
||||
[foo] |
||||
type = http |
||||
local_port = %d |
||||
subdomain = foo |
||||
|
||||
[bar] |
||||
type = http |
||||
local_port = %d |
||||
subdomain = bar |
||||
`, fooPort, barPort) |
||||
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf}) |
||||
|
||||
// foo
|
||||
framework.NewRequestExpect(f).Explain("foo subdomain").Port(vhostHTTPPort). |
||||
RequestModify(func(r *request.Request) { |
||||
r.HTTP().HTTPHost("foo.example.com") |
||||
}). |
||||
ExpectResp([]byte("foo")). |
||||
Ensure() |
||||
|
||||
// bar
|
||||
framework.NewRequestExpect(f).Explain("bar subdomain").Port(vhostHTTPPort). |
||||
RequestModify(func(r *request.Request) { |
||||
r.HTTP().HTTPHost("bar.example.com") |
||||
}). |
||||
ExpectResp([]byte("bar")). |
||||
Ensure() |
||||
}) |
||||
|
||||
It("Modify headers", func() { |
||||
vhostHTTPPort := f.AllocPort() |
||||
serverConf := getDefaultServerConf(vhostHTTPPort) |
||||
|
||||
localPort := f.AllocPort() |
||||
localServer := httpserver.New( |
||||
httpserver.WithBindPort(localPort), |
||||
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { |
||||
w.Write([]byte(req.Header.Get("X-From-Where"))) |
||||
})), |
||||
) |
||||
f.RunServer("", localServer) |
||||
|
||||
clientConf := consts.DefaultClientConfig |
||||
clientConf += fmt.Sprintf(` |
||||
[test] |
||||
type = http |
||||
local_port = %d |
||||
custom_domains = normal.example.com |
||||
header_X-From-Where = frp |
||||
`, localPort) |
||||
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf}) |
||||
|
||||
// not set auth header
|
||||
framework.NewRequestExpect(f).Port(vhostHTTPPort). |
||||
RequestModify(func(r *request.Request) { |
||||
r.HTTP().HTTPHost("normal.example.com") |
||||
}). |
||||
ExpectResp([]byte("frp")). // local http server will write this X-From-Where header to response body
|
||||
Ensure() |
||||
}) |
||||
|
||||
It("Host Header Rewrite", func() { |
||||
vhostHTTPPort := f.AllocPort() |
||||
serverConf := getDefaultServerConf(vhostHTTPPort) |
||||
|
||||
localPort := f.AllocPort() |
||||
localServer := httpserver.New( |
||||
httpserver.WithBindPort(localPort), |
||||
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { |
||||
w.Write([]byte(req.Host)) |
||||
})), |
||||
) |
||||
f.RunServer("", localServer) |
||||
|
||||
clientConf := consts.DefaultClientConfig |
||||
clientConf += fmt.Sprintf(` |
||||
[test] |
||||
type = http |
||||
local_port = %d |
||||
custom_domains = normal.example.com |
||||
host_header_rewrite = rewrite.example.com |
||||
`, localPort) |
||||
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf}) |
||||
|
||||
framework.NewRequestExpect(f).Port(vhostHTTPPort). |
||||
RequestModify(func(r *request.Request) { |
||||
r.HTTP().HTTPHost("normal.example.com") |
||||
}). |
||||
ExpectResp([]byte("rewrite.example.com")). // local http server will write host header to response body
|
||||
Ensure() |
||||
}) |
||||
|
||||
It("websocket", func() { |
||||
vhostHTTPPort := f.AllocPort() |
||||
serverConf := getDefaultServerConf(vhostHTTPPort) |
||||
|
||||
upgrader := websocket.Upgrader{} |
||||
|
||||
localPort := f.AllocPort() |
||||
localServer := httpserver.New( |
||||
httpserver.WithBindPort(localPort), |
||||
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { |
||||
c, err := upgrader.Upgrade(w, req, nil) |
||||
if err != nil { |
||||
return |
||||
} |
||||
defer c.Close() |
||||
for { |
||||
mt, message, err := c.ReadMessage() |
||||
if err != nil { |
||||
break |
||||
} |
||||
err = c.WriteMessage(mt, message) |
||||
if err != nil { |
||||
break |
||||
} |
||||
} |
||||
})), |
||||
) |
||||
|
||||
f.RunServer("", localServer) |
||||
|
||||
clientConf := consts.DefaultClientConfig |
||||
clientConf += fmt.Sprintf(` |
||||
[test] |
||||
type = http |
||||
local_port = %d |
||||
custom_domains = 127.0.0.1 |
||||
`, localPort) |
||||
|
||||
f.RunProcesses([]string{serverConf}, []string{clientConf}) |
||||
|
||||
u := url.URL{Scheme: "ws", Host: "127.0.0.1:" + strconv.Itoa(vhostHTTPPort)} |
||||
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil) |
||||
framework.ExpectNoError(err) |
||||
|
||||
err = c.WriteMessage(websocket.TextMessage, []byte(consts.TestString)) |
||||
framework.ExpectNoError(err) |
||||
|
||||
_, msg, err := c.ReadMessage() |
||||
framework.ExpectNoError(err) |
||||
framework.ExpectEqualValues(consts.TestString, string(msg)) |
||||
}) |
||||
}) |
@ -0,0 +1,86 @@
|
||||
package httpserver |
||||
|
||||
import ( |
||||
"fmt" |
||||
"net" |
||||
"net/http" |
||||
"strconv" |
||||
) |
||||
|
||||
type Server struct { |
||||
bindAddr string |
||||
bindPort int |
||||
hanlder http.Handler |
||||
|
||||
l net.Listener |
||||
hs *http.Server |
||||
} |
||||
|
||||
type Option func(*Server) *Server |
||||
|
||||
func New(options ...Option) *Server { |
||||
s := &Server{ |
||||
bindAddr: "127.0.0.1", |
||||
} |
||||
|
||||
for _, option := range options { |
||||
s = option(s) |
||||
} |
||||
return s |
||||
} |
||||
|
||||
func WithBindAddr(addr string) Option { |
||||
return func(s *Server) *Server { |
||||
s.bindAddr = addr |
||||
return s |
||||
} |
||||
} |
||||
|
||||
func WithBindPort(port int) Option { |
||||
return func(s *Server) *Server { |
||||
s.bindPort = port |
||||
return s |
||||
} |
||||
} |
||||
|
||||
func WithHandler(h http.Handler) Option { |
||||
return func(s *Server) *Server { |
||||
s.hanlder = h |
||||
return s |
||||
} |
||||
} |
||||
|
||||
func (s *Server) Run() error { |
||||
if err := s.initListener(); err != nil { |
||||
return err |
||||
} |
||||
|
||||
addr := net.JoinHostPort(s.bindAddr, strconv.Itoa(s.bindPort)) |
||||
hs := &http.Server{ |
||||
Addr: addr, |
||||
Handler: s.hanlder, |
||||
} |
||||
s.hs = hs |
||||
go hs.Serve(s.l) |
||||
return nil |
||||
} |
||||
|
||||
func (s *Server) Close() error { |
||||
if s.hs != nil { |
||||
return s.hs.Close() |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
func (s *Server) initListener() (err error) { |
||||
s.l, err = net.Listen("tcp", fmt.Sprintf("%s:%d", s.bindAddr, s.bindPort)) |
||||
return |
||||
} |
||||
|
||||
func (s *Server) BindAddr() string { |
||||
return s.bindAddr |
||||
} |
||||
|
||||
func (s *Server) BindPort() int { |
||||
return s.bindPort |
||||
} |
@ -0,0 +1,8 @@
|
||||
package server |
||||
|
||||
type Server interface { |
||||
Run() error |
||||
Close() error |
||||
BindAddr() string |
||||
BindPort() int |
||||
} |
@ -0,0 +1,133 @@
|
||||
package client |
||||
|
||||
import ( |
||||
"encoding/json" |
||||
"fmt" |
||||
"io/ioutil" |
||||
"net" |
||||
"net/http" |
||||
"strconv" |
||||
"strings" |
||||
|
||||
"github.com/fatedier/frp/client" |
||||
"github.com/fatedier/frp/test/e2e/pkg/utils" |
||||
) |
||||
|
||||
type Client struct { |
||||
address string |
||||
authUser string |
||||
authPwd string |
||||
} |
||||
|
||||
func New(host string, port int) *Client { |
||||
return &Client{ |
||||
address: net.JoinHostPort(host, strconv.Itoa(port)), |
||||
} |
||||
} |
||||
|
||||
func (c *Client) SetAuth(user, pwd string) { |
||||
c.authUser = user |
||||
c.authPwd = pwd |
||||
} |
||||
|
||||
func (c *Client) GetProxyStatus(name string) (*client.ProxyStatusResp, error) { |
||||
req, err := http.NewRequest("GET", "http://"+c.address+"/api/status", nil) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
content, err := c.do(req) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
allStatus := &client.StatusResp{} |
||||
if err = json.Unmarshal([]byte(content), &allStatus); err != nil { |
||||
return nil, fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(content)) |
||||
} |
||||
for _, s := range allStatus.TCP { |
||||
if s.Name == name { |
||||
return &s, nil |
||||
} |
||||
} |
||||
for _, s := range allStatus.UDP { |
||||
if s.Name == name { |
||||
return &s, nil |
||||
} |
||||
} |
||||
for _, s := range allStatus.HTTP { |
||||
if s.Name == name { |
||||
return &s, nil |
||||
} |
||||
} |
||||
for _, s := range allStatus.HTTPS { |
||||
if s.Name == name { |
||||
return &s, nil |
||||
} |
||||
} |
||||
for _, s := range allStatus.STCP { |
||||
if s.Name == name { |
||||
return &s, nil |
||||
} |
||||
} |
||||
for _, s := range allStatus.XTCP { |
||||
if s.Name == name { |
||||
return &s, nil |
||||
} |
||||
} |
||||
for _, s := range allStatus.SUDP { |
||||
if s.Name == name { |
||||
return &s, nil |
||||
} |
||||
} |
||||
return nil, fmt.Errorf("no proxy status found") |
||||
} |
||||
|
||||
func (c *Client) Reload() error { |
||||
req, err := http.NewRequest("GET", "http://"+c.address+"/api/reload", nil) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
_, err = c.do(req) |
||||
return err |
||||
} |
||||
|
||||
func (c *Client) GetConfig() (string, error) { |
||||
req, err := http.NewRequest("GET", "http://"+c.address+"/api/config", nil) |
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
return c.do(req) |
||||
} |
||||
|
||||
func (c *Client) UpdateConfig(content string) error { |
||||
req, err := http.NewRequest("PUT", "http://"+c.address+"/api/config", strings.NewReader(content)) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
_, err = c.do(req) |
||||
return err |
||||
} |
||||
|
||||
func (c *Client) setAuthHeader(req *http.Request) { |
||||
if c.authUser != "" || c.authPwd != "" { |
||||
req.Header.Set("Authorization", utils.BasicAuth(c.authUser, c.authPwd)) |
||||
} |
||||
} |
||||
|
||||
func (c *Client) do(req *http.Request) (string, error) { |
||||
c.setAuthHeader(req) |
||||
|
||||
resp, err := http.DefaultClient.Do(req) |
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
defer resp.Body.Close() |
||||
|
||||
if resp.StatusCode != 200 { |
||||
return "", fmt.Errorf("api status code [%d]", resp.StatusCode) |
||||
} |
||||
buf, err := ioutil.ReadAll(resp.Body) |
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
return string(buf), nil |
||||
} |
@ -0,0 +1,10 @@
|
||||
package utils |
||||
|
||||
import ( |
||||
"encoding/base64" |
||||
) |
||||
|
||||
func BasicAuth(username, passwd string) string { |
||||
auth := username + ":" + passwd |
||||
return "Basic " + base64.StdEncoding.EncodeToString([]byte(auth)) |
||||
} |
@ -1,204 +0,0 @@
|
||||
[common] |
||||
server_addr = 127.0.0.1 |
||||
server_port = 10700 |
||||
log_file = console |
||||
log_level = trace |
||||
token = 123456 |
||||
admin_port = 10600 |
||||
admin_user = abc |
||||
admin_pwd = abc |
||||
|
||||
[tcp_normal] |
||||
type = tcp |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10701 |
||||
remote_port = 10801 |
||||
|
||||
[tcp_ec] |
||||
type = tcp |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10701 |
||||
remote_port = 10901 |
||||
use_encryption = true |
||||
use_compression = true |
||||
|
||||
[tcp_group1] |
||||
type = tcp |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10701 |
||||
remote_port = 10802 |
||||
group = test1 |
||||
group_key = 123 |
||||
|
||||
[tcp_group2] |
||||
type = tcp |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10702 |
||||
remote_port = 10802 |
||||
group = test1 |
||||
group_key = 123 |
||||
|
||||
[udp_normal] |
||||
type = udp |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10702 |
||||
remote_port = 10802 |
||||
|
||||
[udp_ec] |
||||
type = udp |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10702 |
||||
remote_port = 10902 |
||||
use_encryption = true |
||||
use_compression = true |
||||
|
||||
[unix_domain] |
||||
type = tcp |
||||
remote_port = 10803 |
||||
plugin = unix_domain_socket |
||||
plugin_unix_path = /tmp/frp_echo_server.sock |
||||
|
||||
[stcp] |
||||
type = stcp |
||||
sk = abcdefg |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10701 |
||||
|
||||
[stcp_ec] |
||||
type = stcp |
||||
sk = abc |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10701 |
||||
use_encryption = true |
||||
use_compression = true |
||||
|
||||
[sudp] |
||||
type = sudp |
||||
sk = abcdefg |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10702 |
||||
|
||||
[web01] |
||||
type = http |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10704 |
||||
custom_domains = 127.0.0.1 |
||||
|
||||
[web02] |
||||
type = http |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10704 |
||||
custom_domains = test2.frp.com |
||||
host_header_rewrite = test2.frp.com |
||||
use_encryption = true |
||||
use_compression = true |
||||
|
||||
[web03] |
||||
type = http |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10704 |
||||
custom_domains = test3.frp.com |
||||
use_encryption = true |
||||
use_compression = true |
||||
host_header_rewrite = test3.frp.com |
||||
locations = /,/foo |
||||
|
||||
[web04] |
||||
type = http |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10704 |
||||
custom_domains = test3.frp.com |
||||
use_encryption = true |
||||
use_compression = true |
||||
host_header_rewrite = test3.frp.com |
||||
locations = /bar |
||||
|
||||
[web05] |
||||
type = http |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10704 |
||||
custom_domains = test5.frp.com |
||||
host_header_rewrite = test5.frp.com |
||||
use_encryption = true |
||||
use_compression = true |
||||
http_user = test |
||||
http_user = test |
||||
|
||||
[web06] |
||||
type = http |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10704 |
||||
custom_domains = test6.frp.com |
||||
host_header_rewrite = test6.frp.com |
||||
header_X-From-Where = frp |
||||
|
||||
[wildcard_http] |
||||
type = http |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10704 |
||||
custom_domains = *.frp1.com |
||||
|
||||
[subhost01] |
||||
type = http |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10704 |
||||
subdomain = test01 |
||||
|
||||
[subhost02] |
||||
type = http |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10704 |
||||
subdomain = test02 |
||||
|
||||
[tcp_port_not_allowed] |
||||
type = tcp |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10701 |
||||
remote_port = 20001 |
||||
|
||||
[tcp_port_unavailable] |
||||
type =tcp |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10701 |
||||
remote_port = 10700 |
||||
|
||||
[tcp_port_normal] |
||||
type = tcp |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10701 |
||||
remote_port = 20002 |
||||
|
||||
[tcp_random_port] |
||||
type = tcp |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10701 |
||||
remote_port = 0 |
||||
|
||||
[udp_port_not_allowed] |
||||
type = udp |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10702 |
||||
remote_port = 20001 |
||||
|
||||
[udp_port_normal] |
||||
type = udp |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10702 |
||||
remote_port = 20002 |
||||
|
||||
[udp_random_port] |
||||
type = udp |
||||
local_ip = 127.0.0.1 |
||||
local_port = 10702 |
||||
remote_port = 0 |
||||
|
||||
[http_proxy] |
||||
type = tcp |
||||
plugin = http_proxy |
||||
remote_port = 0 |
||||
|
||||
[range:range_tcp] |
||||
type = tcp |
||||
local_ip = 127.0.0.1 |
||||
local_port = 30000-30001,30003 |
||||
remote_port = 30000-30001,30003 |
@ -1,34 +0,0 @@
|
||||
[common] |
||||
server_addr = 0.0.0.0 |
||||
server_port = 10700 |
||||
log_file = console |
||||
# debug, info, warn, error |
||||
log_level = debug |
||||
token = 123456 |
||||
|
||||
[stcp_visitor] |
||||
type = stcp |
||||
role = visitor |
||||
server_name = stcp |
||||
sk = abcdefg |
||||
bind_addr = 127.0.0.1 |
||||
bind_port = 10805 |
||||
|
||||
[stcp_ec_visitor] |
||||
type = stcp |
||||
role = visitor |
||||
server_name = stcp_ec |
||||
sk = abc |
||||
bind_addr = 127.0.0.1 |
||||
bind_port = 10905 |
||||
use_encryption = true |
||||
use_compression = true |
||||
|
||||
|
||||
[sudp_visitor] |
||||
type = sudp |
||||
role = visitor |
||||
server_name = sudp |
||||
sk = abcdefg |
||||
bind_addr = 127.0.0.1 |
||||
bind_port = 10816 |
@ -1,9 +0,0 @@
|
||||
[common] |
||||
bind_addr = 0.0.0.0 |
||||
bind_port = 10700 |
||||
vhost_http_port = 10804 |
||||
tcpmux_httpconnect_port = 10806 |
||||
log_level = trace |
||||
token = 123456 |
||||
allow_ports = 10000-20000,20002,30000-50000 |
||||
subdomain_host = sub.com |
@ -1,85 +0,0 @@
|
||||
package ci |
||||
|
||||
import ( |
||||
"testing" |
||||
"time" |
||||
|
||||
"github.com/fatedier/frp/tests/consts" |
||||
"github.com/fatedier/frp/tests/util" |
||||
|
||||
"github.com/stretchr/testify/assert" |
||||
) |
||||
|
||||
func TestCmdTCP(t *testing.T) { |
||||
assert := assert.New(t) |
||||
|
||||
var err error |
||||
s := util.NewProcess(consts.FRPS_BIN_PATH, []string{"-t", "123", "-p", "20000"}) |
||||
err = s.Start() |
||||
if assert.NoError(err) { |
||||
defer s.Stop() |
||||
} |
||||
time.Sleep(500 * time.Millisecond) |
||||
|
||||
c := util.NewProcess(consts.FRPC_BIN_PATH, []string{"tcp", "-s", "127.0.0.1:20000", "-t", "123", "-u", "test", |
||||
"-l", "10701", "-r", "20801", "-n", "tcp_test"}) |
||||
err = c.Start() |
||||
if assert.NoError(err) { |
||||
defer c.Stop() |
||||
} |
||||
time.Sleep(500 * time.Millisecond) |
||||
|
||||
res, err := util.SendTCPMsg("127.0.0.1:20801", consts.TEST_TCP_ECHO_STR) |
||||
assert.NoError(err) |
||||
assert.Equal(consts.TEST_TCP_ECHO_STR, res) |
||||
} |
||||
|
||||
func TestCmdUDP(t *testing.T) { |
||||
assert := assert.New(t) |
||||
|
||||
var err error |
||||
s := util.NewProcess(consts.FRPS_BIN_PATH, []string{"-t", "123", "-p", "20000"}) |
||||
err = s.Start() |
||||
if assert.NoError(err) { |
||||
defer s.Stop() |
||||
} |
||||
time.Sleep(500 * time.Millisecond) |
||||
|
||||
c := util.NewProcess(consts.FRPC_BIN_PATH, []string{"udp", "-s", "127.0.0.1:20000", "-t", "123", "-u", "test", |
||||
"-l", "10702", "-r", "20802", "-n", "udp_test"}) |
||||
err = c.Start() |
||||
if assert.NoError(err) { |
||||
defer c.Stop() |
||||
} |
||||
time.Sleep(500 * time.Millisecond) |
||||
|
||||
res, err := util.SendUDPMsg("127.0.0.1:20802", consts.TEST_UDP_ECHO_STR) |
||||
assert.NoError(err) |
||||
assert.Equal(consts.TEST_UDP_ECHO_STR, res) |
||||
} |
||||
|
||||
func TestCmdHTTP(t *testing.T) { |
||||
assert := assert.New(t) |
||||
|
||||
var err error |
||||
s := util.NewProcess(consts.FRPS_BIN_PATH, []string{"-t", "123", "-p", "20000", "--vhost_http_port", "20001"}) |
||||
err = s.Start() |
||||
if assert.NoError(err) { |
||||
defer s.Stop() |
||||
} |
||||
time.Sleep(500 * time.Millisecond) |
||||
|
||||
c := util.NewProcess(consts.FRPC_BIN_PATH, []string{"http", "-s", "127.0.0.1:20000", "-t", "123", "-u", "test", |
||||
"-n", "udp_test", "-l", "10704", "--custom_domain", "127.0.0.1"}) |
||||
err = c.Start() |
||||
if assert.NoError(err) { |
||||
defer c.Stop() |
||||
} |
||||
time.Sleep(500 * time.Millisecond) |
||||
|
||||
code, body, _, err := util.SendHTTPMsg("GET", "http://127.0.0.1:20001", "", nil, "") |
||||
if assert.NoError(err) { |
||||
assert.Equal(200, code) |
||||
assert.Equal(consts.TEST_HTTP_NORMAL_STR, body) |
||||
} |
||||
} |
@ -1,309 +0,0 @@
|
||||
package health |
||||
|
||||
import ( |
||||
"net/http" |
||||
"os" |
||||
"strings" |
||||
"sync" |
||||
"testing" |
||||
"time" |
||||
|
||||
"github.com/fatedier/frp/tests/config" |
||||
"github.com/fatedier/frp/tests/consts" |
||||
"github.com/fatedier/frp/tests/mock" |
||||
"github.com/fatedier/frp/tests/util" |
||||
|
||||
"github.com/stretchr/testify/assert" |
||||
) |
||||
|
||||
const FRPS_CONF = ` |
||||
[common] |
||||
bind_addr = 0.0.0.0 |
||||
bind_port = 14000 |
||||
vhost_http_port = 14000 |
||||
log_file = console |
||||
log_level = debug |
||||
token = 123456 |
||||
` |
||||
|
||||
const FRPC_CONF = ` |
||||
[common] |
||||
server_addr = 127.0.0.1 |
||||
server_port = 14000 |
||||
log_file = console |
||||
log_level = debug |
||||
token = 123456 |
||||
|
||||
[tcp1] |
||||
type = tcp |
||||
local_port = 15001 |
||||
remote_port = 15000 |
||||
group = test |
||||
group_key = 123 |
||||
health_check_type = tcp |
||||
health_check_interval_s = 1 |
||||
|
||||
[tcp2] |
||||
type = tcp |
||||
local_port = 15002 |
||||
remote_port = 15000 |
||||
group = test |
||||
group_key = 123 |
||||
health_check_type = tcp |
||||
health_check_interval_s = 1 |
||||
|
||||
[http1] |
||||
type = http |
||||
local_port = 15003 |
||||
custom_domains = test1.com |
||||
health_check_type = http |
||||
health_check_interval_s = 1 |
||||
health_check_url = /health |
||||
|
||||
[http2] |
||||
type = http |
||||
local_port = 15004 |
||||
custom_domains = test2.com |
||||
health_check_type = http |
||||
health_check_interval_s = 1 |
||||
health_check_url = /health |
||||
|
||||
[http3] |
||||
type = http |
||||
local_port = 15005 |
||||
custom_domains = test.balancing.com |
||||
group = test-balancing |
||||
group_key = 123 |
||||
|
||||
[http4] |
||||
type = http |
||||
local_port = 15006 |
||||
custom_domains = test.balancing.com |
||||
group = test-balancing |
||||
group_key = 123 |
||||
` |
||||
|
||||
func TestHealthCheck(t *testing.T) { |
||||
assert := assert.New(t) |
||||
|
||||
// ****** start background services ******
|
||||
echoSvc1 := mock.NewEchoServer(15001, 1, "echo1") |
||||
err := echoSvc1.Start() |
||||
if assert.NoError(err) { |
||||
defer echoSvc1.Stop() |
||||
} |
||||
|
||||
echoSvc2 := mock.NewEchoServer(15002, 1, "echo2") |
||||
err = echoSvc2.Start() |
||||
if assert.NoError(err) { |
||||
defer echoSvc2.Stop() |
||||
} |
||||
|
||||
var healthMu sync.RWMutex |
||||
svc1Health := true |
||||
svc2Health := true |
||||
httpSvc1 := mock.NewHTTPServer(15003, func(w http.ResponseWriter, r *http.Request) { |
||||
if strings.Contains(r.URL.Path, "health") { |
||||
healthMu.RLock() |
||||
defer healthMu.RUnlock() |
||||
if svc1Health { |
||||
w.WriteHeader(200) |
||||
} else { |
||||
w.WriteHeader(500) |
||||
} |
||||
} else { |
||||
w.Write([]byte("http1")) |
||||
} |
||||
}) |
||||
err = httpSvc1.Start() |
||||
if assert.NoError(err) { |
||||
defer httpSvc1.Stop() |
||||
} |
||||
|
||||
httpSvc2 := mock.NewHTTPServer(15004, func(w http.ResponseWriter, r *http.Request) { |
||||
if strings.Contains(r.URL.Path, "health") { |
||||
healthMu.RLock() |
||||
defer healthMu.RUnlock() |
||||
if svc2Health { |
||||
w.WriteHeader(200) |
||||
} else { |
||||
w.WriteHeader(500) |
||||
} |
||||
} else { |
||||
w.Write([]byte("http2")) |
||||
} |
||||
}) |
||||
err = httpSvc2.Start() |
||||
if assert.NoError(err) { |
||||
defer httpSvc2.Stop() |
||||
} |
||||
|
||||
httpSvc3 := mock.NewHTTPServer(15005, func(w http.ResponseWriter, r *http.Request) { |
||||
time.Sleep(time.Second) |
||||
w.Write([]byte("http3")) |
||||
}) |
||||
err = httpSvc3.Start() |
||||
if assert.NoError(err) { |
||||
defer httpSvc3.Stop() |
||||
} |
||||
|
||||
httpSvc4 := mock.NewHTTPServer(15006, func(w http.ResponseWriter, r *http.Request) { |
||||
time.Sleep(time.Second) |
||||
w.Write([]byte("http4")) |
||||
}) |
||||
err = httpSvc4.Start() |
||||
if assert.NoError(err) { |
||||
defer httpSvc4.Stop() |
||||
} |
||||
|
||||
time.Sleep(200 * time.Millisecond) |
||||
|
||||
// ****** start frps and frpc ******
|
||||
frpsCfgPath, err := config.GenerateConfigFile(consts.FRPS_NORMAL_CONFIG, FRPS_CONF) |
||||
if assert.NoError(err) { |
||||
defer os.Remove(frpsCfgPath) |
||||
} |
||||
|
||||
frpcCfgPath, err := config.GenerateConfigFile(consts.FRPC_NORMAL_CONFIG, FRPC_CONF) |
||||
if assert.NoError(err) { |
||||
defer os.Remove(frpcCfgPath) |
||||
} |
||||
|
||||
frpsProcess := util.NewProcess(consts.FRPS_SUB_BIN_PATH, []string{"-c", frpsCfgPath}) |
||||
err = frpsProcess.Start() |
||||
if assert.NoError(err) { |
||||
defer frpsProcess.Stop() |
||||
} |
||||
|
||||
time.Sleep(500 * time.Millisecond) |
||||
|
||||
frpcProcess := util.NewProcess(consts.FRPC_SUB_BIN_PATH, []string{"-c", frpcCfgPath}) |
||||
err = frpcProcess.Start() |
||||
if assert.NoError(err) { |
||||
defer frpcProcess.Stop() |
||||
} |
||||
time.Sleep(1000 * time.Millisecond) |
||||
|
||||
// ****** healcheck type tcp ******
|
||||
// echo1 and echo2 is ok
|
||||
result := make([]string, 0) |
||||
res, err := util.SendTCPMsg("127.0.0.1:15000", "echo") |
||||
assert.NoError(err) |
||||
result = append(result, res) |
||||
|
||||
res, err = util.SendTCPMsg("127.0.0.1:15000", "echo") |
||||
assert.NoError(err) |
||||
result = append(result, res) |
||||
|
||||
assert.Contains(result, "echo1") |
||||
assert.Contains(result, "echo2") |
||||
|
||||
// close echo2 server, echo1 is work
|
||||
echoSvc2.Stop() |
||||
time.Sleep(1200 * time.Millisecond) |
||||
|
||||
result = make([]string, 0) |
||||
res, err = util.SendTCPMsg("127.0.0.1:15000", "echo") |
||||
assert.NoError(err) |
||||
result = append(result, res) |
||||
|
||||
res, err = util.SendTCPMsg("127.0.0.1:15000", "echo") |
||||
assert.NoError(err) |
||||
result = append(result, res) |
||||
|
||||
assert.NotContains(result, "echo2") |
||||
|
||||
// resume echo2 server, all services are ok
|
||||
echoSvc2 = mock.NewEchoServer(15002, 1, "echo2") |
||||
err = echoSvc2.Start() |
||||
if assert.NoError(err) { |
||||
defer echoSvc2.Stop() |
||||
} |
||||
|
||||
time.Sleep(1200 * time.Millisecond) |
||||
|
||||
result = make([]string, 0) |
||||
res, err = util.SendTCPMsg("127.0.0.1:15000", "echo") |
||||
assert.NoError(err) |
||||
result = append(result, res) |
||||
|
||||
res, err = util.SendTCPMsg("127.0.0.1:15000", "echo") |
||||
assert.NoError(err) |
||||
result = append(result, res) |
||||
|
||||
assert.Contains(result, "echo1") |
||||
assert.Contains(result, "echo2") |
||||
|
||||
// ****** healcheck type http ******
|
||||
// http1 and http2 is ok
|
||||
code, body, _, err := util.SendHTTPMsg("GET", "http://127.0.0.1:14000/xxx", "test1.com", nil, "") |
||||
assert.NoError(err) |
||||
assert.Equal(200, code) |
||||
assert.Equal("http1", body) |
||||
|
||||
code, body, _, err = util.SendHTTPMsg("GET", "http://127.0.0.1:14000/xxx", "test2.com", nil, "") |
||||
assert.NoError(err) |
||||
assert.Equal(200, code) |
||||
assert.Equal("http2", body) |
||||
|
||||
// http2 health check error
|
||||
healthMu.Lock() |
||||
svc2Health = false |
||||
healthMu.Unlock() |
||||
time.Sleep(1200 * time.Millisecond) |
||||
|
||||
code, body, _, err = util.SendHTTPMsg("GET", "http://127.0.0.1:14000/xxx", "test1.com", nil, "") |
||||
assert.NoError(err) |
||||
assert.Equal(200, code) |
||||
assert.Equal("http1", body) |
||||
|
||||
code, _, _, err = util.SendHTTPMsg("GET", "http://127.0.0.1:14000/xxx", "test2.com", nil, "") |
||||
assert.NoError(err) |
||||
assert.Equal(404, code) |
||||
|
||||
// resume http2 service, http1 and http2 are ok
|
||||
healthMu.Lock() |
||||
svc2Health = true |
||||
healthMu.Unlock() |
||||
time.Sleep(1200 * time.Millisecond) |
||||
|
||||
code, body, _, err = util.SendHTTPMsg("GET", "http://127.0.0.1:14000/xxx", "test1.com", nil, "") |
||||
assert.NoError(err) |
||||
assert.Equal(200, code) |
||||
assert.Equal("http1", body) |
||||
|
||||
code, body, _, err = util.SendHTTPMsg("GET", "http://127.0.0.1:14000/xxx", "test2.com", nil, "") |
||||
assert.NoError(err) |
||||
assert.Equal(200, code) |
||||
assert.Equal("http2", body) |
||||
|
||||
// ****** load balancing type http ******
|
||||
result = make([]string, 0) |
||||
var wait sync.WaitGroup |
||||
var mu sync.Mutex |
||||
wait.Add(2) |
||||
|
||||
go func() { |
||||
defer wait.Done() |
||||
code, body, _, err := util.SendHTTPMsg("GET", "http://127.0.0.1:14000/xxx", "test.balancing.com", nil, "") |
||||
assert.NoError(err) |
||||
assert.Equal(200, code) |
||||
mu.Lock() |
||||
result = append(result, body) |
||||
mu.Unlock() |
||||
}() |
||||
|
||||
go func() { |
||||
defer wait.Done() |
||||
code, body, _, err = util.SendHTTPMsg("GET", "http://127.0.0.1:14000/xxx", "test.balancing.com", nil, "") |
||||
assert.NoError(err) |
||||
assert.Equal(200, code) |
||||
mu.Lock() |
||||
result = append(result, body) |
||||
mu.Unlock() |
||||
}() |
||||
wait.Wait() |
||||
|
||||
assert.Contains(result, "http3") |
||||
assert.Contains(result, "http4") |
||||
} |
@ -1,250 +0,0 @@
|
||||
package ci |
||||
|
||||
import ( |
||||
"fmt" |
||||
"net/http" |
||||
"net/url" |
||||
"os" |
||||
"testing" |
||||
"time" |
||||
|
||||
"github.com/gorilla/websocket" |
||||
"github.com/stretchr/testify/assert" |
||||
|
||||
"github.com/fatedier/frp/client/proxy" |
||||
"github.com/fatedier/frp/tests/consts" |
||||
"github.com/fatedier/frp/tests/mock" |
||||
"github.com/fatedier/frp/tests/util" |
||||
|
||||
gnet "github.com/fatedier/golib/net" |
||||
) |
||||
|
||||
func TestMain(m *testing.M) { |
||||
var err error |
||||
tcpEcho1 := mock.NewEchoServer(consts.TEST_TCP_PORT, 1, "") |
||||
tcpEcho2 := mock.NewEchoServer(consts.TEST_TCP2_PORT, 2, "") |
||||
|
||||
if err = tcpEcho1.Start(); err != nil { |
||||
panic(err) |
||||
} |
||||
if err = tcpEcho2.Start(); err != nil { |
||||
panic(err) |
||||
} |
||||
|
||||
go mock.StartUDPEchoServer(consts.TEST_UDP_PORT) |
||||
go mock.StartUnixDomainServer(consts.TEST_UNIX_DOMAIN_ADDR) |
||||
go mock.StartHTTPServer(consts.TEST_HTTP_PORT) |
||||
|
||||
p1 := util.NewProcess(consts.FRPS_BIN_PATH, []string{"-c", "./auto_test_frps.ini"}) |
||||
if err = p1.Start(); err != nil { |
||||
panic(err) |
||||
} |
||||
|
||||
time.Sleep(500 * time.Millisecond) |
||||
p2 := util.NewProcess(consts.FRPC_BIN_PATH, []string{"-c", "./auto_test_frpc.ini"}) |
||||
if err = p2.Start(); err != nil { |
||||
panic(err) |
||||
} |
||||
|
||||
p3 := util.NewProcess(consts.FRPC_BIN_PATH, []string{"-c", "./auto_test_frpc_visitor.ini"}) |
||||
if err = p3.Start(); err != nil { |
||||
panic(err) |
||||
} |
||||
time.Sleep(500 * time.Millisecond) |
||||
|
||||
exitCode := m.Run() |
||||
p1.Stop() |
||||
p2.Stop() |
||||
p3.Stop() |
||||
os.Exit(exitCode) |
||||
} |
||||
|
||||
func TestHTTP(t *testing.T) { |
||||
assert := assert.New(t) |
||||
// web01
|
||||
code, body, _, err := util.SendHTTPMsg("GET", fmt.Sprintf("http://127.0.0.1:%d", consts.TEST_HTTP_FRP_PORT), "", nil, "") |
||||
if assert.NoError(err) { |
||||
assert.Equal(200, code) |
||||
assert.Equal(consts.TEST_HTTP_NORMAL_STR, body) |
||||
} |
||||
|
||||
// web02
|
||||
code, body, _, err = util.SendHTTPMsg("GET", fmt.Sprintf("http://127.0.0.1:%d", consts.TEST_HTTP_FRP_PORT), "test2.frp.com", nil, "") |
||||
if assert.NoError(err) { |
||||
assert.Equal(200, code) |
||||
assert.Equal(consts.TEST_HTTP_NORMAL_STR, body) |
||||
} |
||||
|
||||
// error host header
|
||||
code, body, _, err = util.SendHTTPMsg("GET", fmt.Sprintf("http://127.0.0.1:%d", consts.TEST_HTTP_FRP_PORT), "errorhost.frp.com", nil, "") |
||||
if assert.NoError(err) { |
||||
assert.Equal(404, code) |
||||
} |
||||
|
||||
// web03
|
||||
code, body, _, err = util.SendHTTPMsg("GET", fmt.Sprintf("http://127.0.0.1:%d", consts.TEST_HTTP_FRP_PORT), "test3.frp.com", nil, "") |
||||
if assert.NoError(err) { |
||||
assert.Equal(200, code) |
||||
assert.Equal(consts.TEST_HTTP_NORMAL_STR, body) |
||||
} |
||||
|
||||
code, body, _, err = util.SendHTTPMsg("GET", fmt.Sprintf("http://127.0.0.1:%d/foo", consts.TEST_HTTP_FRP_PORT), "test3.frp.com", nil, "") |
||||
if assert.NoError(err) { |
||||
assert.Equal(200, code) |
||||
assert.Equal(consts.TEST_HTTP_FOO_STR, body) |
||||
} |
||||
|
||||
// web04
|
||||
code, body, _, err = util.SendHTTPMsg("GET", fmt.Sprintf("http://127.0.0.1:%d/bar", consts.TEST_HTTP_FRP_PORT), "test3.frp.com", nil, "") |
||||
if assert.NoError(err) { |
||||
assert.Equal(200, code) |
||||
assert.Equal(consts.TEST_HTTP_BAR_STR, body) |
||||
} |
||||
|
||||
// web05
|
||||
code, body, _, err = util.SendHTTPMsg("GET", fmt.Sprintf("http://127.0.0.1:%d", consts.TEST_HTTP_FRP_PORT), "test5.frp.com", nil, "") |
||||
if assert.NoError(err) { |
||||
assert.Equal(401, code) |
||||
} |
||||
|
||||
headers := make(map[string]string) |
||||
headers["Authorization"] = util.BasicAuth("test", "test") |
||||
code, body, _, err = util.SendHTTPMsg("GET", fmt.Sprintf("http://127.0.0.1:%d", consts.TEST_HTTP_FRP_PORT), "test5.frp.com", headers, "") |
||||
if assert.NoError(err) { |
||||
assert.Equal(401, code) |
||||
} |
||||
|
||||
// web06
|
||||
var header http.Header |
||||
code, body, header, err = util.SendHTTPMsg("GET", fmt.Sprintf("http://127.0.0.1:%d", consts.TEST_HTTP_FRP_PORT), "test6.frp.com", nil, "") |
||||
if assert.NoError(err) { |
||||
assert.Equal(200, code) |
||||
assert.Equal(consts.TEST_HTTP_NORMAL_STR, body) |
||||
assert.Equal("true", header.Get("X-Header-Set")) |
||||
} |
||||
|
||||
// wildcard_http
|
||||
// test.frp1.com match *.frp1.com
|
||||
code, body, _, err = util.SendHTTPMsg("GET", fmt.Sprintf("http://127.0.0.1:%d", consts.TEST_HTTP_FRP_PORT), "test.frp1.com", nil, "") |
||||
if assert.NoError(err) { |
||||
assert.Equal(200, code) |
||||
assert.Equal(consts.TEST_HTTP_NORMAL_STR, body) |
||||
} |
||||
|
||||
// new.test.frp1.com also match *.frp1.com
|
||||
code, body, _, err = util.SendHTTPMsg("GET", fmt.Sprintf("http://127.0.0.1:%d", consts.TEST_HTTP_FRP_PORT), "new.test.frp1.com", nil, "") |
||||
if assert.NoError(err) { |
||||
assert.Equal(200, code) |
||||
assert.Equal(consts.TEST_HTTP_NORMAL_STR, body) |
||||
} |
||||
|
||||
// subhost01
|
||||
code, body, _, err = util.SendHTTPMsg("GET", fmt.Sprintf("http://127.0.0.1:%d", consts.TEST_HTTP_FRP_PORT), "test01.sub.com", nil, "") |
||||
if assert.NoError(err) { |
||||
assert.Equal(200, code) |
||||
assert.Equal("test01.sub.com", body) |
||||
} |
||||
|
||||
// subhost02
|
||||
code, body, _, err = util.SendHTTPMsg("GET", fmt.Sprintf("http://127.0.0.1:%d", consts.TEST_HTTP_FRP_PORT), "test02.sub.com", nil, "") |
||||
if assert.NoError(err) { |
||||
assert.Equal(200, code) |
||||
assert.Equal("test02.sub.com", body) |
||||
} |
||||
} |
||||
|
||||
func TestWebSocket(t *testing.T) { |
||||
assert := assert.New(t) |
||||
|
||||
u := url.URL{Scheme: "ws", Host: fmt.Sprintf("%s:%d", "127.0.0.1", consts.TEST_HTTP_FRP_PORT), Path: "/ws"} |
||||
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil) |
||||
assert.NoError(err) |
||||
defer c.Close() |
||||
|
||||
err = c.WriteMessage(websocket.TextMessage, []byte(consts.TEST_HTTP_NORMAL_STR)) |
||||
assert.NoError(err) |
||||
|
||||
_, msg, err := c.ReadMessage() |
||||
assert.NoError(err) |
||||
assert.Equal(consts.TEST_HTTP_NORMAL_STR, string(msg)) |
||||
} |
||||
|
||||
func TestRandomPort(t *testing.T) { |
||||
assert := assert.New(t) |
||||
// tcp
|
||||
status, err := util.GetProxyStatus(consts.ADMIN_ADDR, consts.ADMIN_USER, consts.ADMIN_PWD, consts.ProxyTCPRandomPort) |
||||
if assert.NoError(err) { |
||||
addr := status.RemoteAddr |
||||
res, err := util.SendTCPMsg(addr, consts.TEST_TCP_ECHO_STR) |
||||
assert.NoError(err) |
||||
assert.Equal(consts.TEST_TCP_ECHO_STR, res) |
||||
} |
||||
|
||||
// udp
|
||||
status, err = util.GetProxyStatus(consts.ADMIN_ADDR, consts.ADMIN_USER, consts.ADMIN_PWD, consts.ProxyUDPRandomPort) |
||||
if assert.NoError(err) { |
||||
addr := status.RemoteAddr |
||||
res, err := util.SendUDPMsg(addr, consts.TEST_UDP_ECHO_STR) |
||||
assert.NoError(err) |
||||
assert.Equal(consts.TEST_UDP_ECHO_STR, res) |
||||
} |
||||
} |
||||
|
||||
func TestPluginHTTPProxy(t *testing.T) { |
||||
assert := assert.New(t) |
||||
status, err := util.GetProxyStatus(consts.ADMIN_ADDR, consts.ADMIN_USER, consts.ADMIN_PWD, consts.ProxyHTTPProxy) |
||||
if assert.NoError(err) { |
||||
assert.Equal(proxy.ProxyPhaseRunning, status.Status) |
||||
|
||||
// http proxy
|
||||
addr := status.RemoteAddr |
||||
code, body, _, err := util.SendHTTPMsg("GET", fmt.Sprintf("http://127.0.0.1:%d", consts.TEST_HTTP_FRP_PORT), |
||||
"", nil, "http://"+addr) |
||||
if assert.NoError(err) { |
||||
assert.Equal(200, code) |
||||
assert.Equal(consts.TEST_HTTP_NORMAL_STR, body) |
||||
} |
||||
|
||||
// connect method
|
||||
conn, err := gnet.DialTcpByProxy("http://"+addr, fmt.Sprintf("127.0.0.1:%d", consts.TEST_TCP_FRP_PORT)) |
||||
if assert.NoError(err) { |
||||
res, err := util.SendTCPMsgByConn(conn, consts.TEST_TCP_ECHO_STR) |
||||
assert.NoError(err) |
||||
assert.Equal(consts.TEST_TCP_ECHO_STR, res) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestRangePortsMapping(t *testing.T) { |
||||
assert := assert.New(t) |
||||
|
||||
for i := 0; i < 3; i++ { |
||||
name := fmt.Sprintf("%s_%d", consts.ProxyRangeTCPPrefix, i) |
||||
status, err := util.GetProxyStatus(consts.ADMIN_ADDR, consts.ADMIN_USER, consts.ADMIN_PWD, name) |
||||
if assert.NoError(err) { |
||||
assert.Equal(proxy.ProxyPhaseRunning, status.Status) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestGroup(t *testing.T) { |
||||
assert := assert.New(t) |
||||
|
||||
var ( |
||||
p1 int |
||||
p2 int |
||||
) |
||||
addr := fmt.Sprintf("127.0.0.1:%d", consts.TEST_TCP2_FRP_PORT) |
||||
|
||||
for i := 0; i < 6; i++ { |
||||
res, err := util.SendTCPMsg(addr, consts.TEST_TCP_ECHO_STR) |
||||
assert.NoError(err) |
||||
switch res { |
||||
case consts.TEST_TCP_ECHO_STR: |
||||
p1++ |
||||
case consts.TEST_TCP_ECHO_STR + consts.TEST_TCP_ECHO_STR: |
||||
p2++ |
||||
} |
||||
} |
||||
assert.True(p1 > 0 && p2 > 0, "group proxies load balancing") |
||||
} |
@ -1,115 +0,0 @@
|
||||
package ci |
||||
|
||||
import ( |
||||
"os" |
||||
"testing" |
||||
"time" |
||||
|
||||
"github.com/fatedier/frp/tests/config" |
||||
"github.com/fatedier/frp/tests/consts" |
||||
"github.com/fatedier/frp/tests/util" |
||||
|
||||
"github.com/stretchr/testify/assert" |
||||
) |
||||
|
||||
const FRPS_RECONNECT_CONF = ` |
||||
[common] |
||||
bind_addr = 0.0.0.0 |
||||
bind_port = 20000 |
||||
log_file = console |
||||
log_level = debug |
||||
token = 123456 |
||||
` |
||||
|
||||
const FRPC_RECONNECT_CONF = ` |
||||
[common] |
||||
server_addr = 127.0.0.1 |
||||
server_port = 20000 |
||||
log_file = console |
||||
log_level = debug |
||||
token = 123456 |
||||
admin_port = 21000 |
||||
admin_user = abc |
||||
admin_pwd = abc |
||||
|
||||
[tcp] |
||||
type = tcp |
||||
local_port = 10701 |
||||
remote_port = 20801 |
||||
` |
||||
|
||||
func TestReconnect(t *testing.T) { |
||||
assert := assert.New(t) |
||||
frpsCfgPath, err := config.GenerateConfigFile(consts.FRPS_NORMAL_CONFIG, FRPS_RECONNECT_CONF) |
||||
if assert.NoError(err) { |
||||
defer os.Remove(frpsCfgPath) |
||||
} |
||||
|
||||
frpcCfgPath, err := config.GenerateConfigFile(consts.FRPC_NORMAL_CONFIG, FRPC_RECONNECT_CONF) |
||||
if assert.NoError(err) { |
||||
defer os.Remove(frpcCfgPath) |
||||
} |
||||
|
||||
frpsProcess := util.NewProcess(consts.FRPS_BIN_PATH, []string{"-c", frpsCfgPath}) |
||||
err = frpsProcess.Start() |
||||
if assert.NoError(err) { |
||||
defer frpsProcess.Stop() |
||||
} |
||||
|
||||
time.Sleep(500 * time.Millisecond) |
||||
|
||||
frpcProcess := util.NewProcess(consts.FRPC_BIN_PATH, []string{"-c", frpcCfgPath}) |
||||
err = frpcProcess.Start() |
||||
if assert.NoError(err) { |
||||
defer frpcProcess.Stop() |
||||
} |
||||
time.Sleep(500 * time.Millisecond) |
||||
|
||||
// test tcp
|
||||
res, err := util.SendTCPMsg("127.0.0.1:20801", consts.TEST_TCP_ECHO_STR) |
||||
assert.NoError(err) |
||||
assert.Equal(consts.TEST_TCP_ECHO_STR, res) |
||||
|
||||
// stop frpc
|
||||
frpcProcess.Stop() |
||||
time.Sleep(200 * time.Millisecond) |
||||
|
||||
// test tcp, expect failed
|
||||
_, err = util.SendTCPMsg("127.0.0.1:20801", consts.TEST_TCP_ECHO_STR) |
||||
assert.Error(err) |
||||
|
||||
// restart frpc
|
||||
newFrpcProcess := util.NewProcess(consts.FRPC_BIN_PATH, []string{"-c", frpcCfgPath}) |
||||
err = newFrpcProcess.Start() |
||||
if assert.NoError(err) { |
||||
defer newFrpcProcess.Stop() |
||||
} |
||||
time.Sleep(500 * time.Millisecond) |
||||
|
||||
// test tcp
|
||||
res, err = util.SendTCPMsg("127.0.0.1:20801", consts.TEST_TCP_ECHO_STR) |
||||
assert.NoError(err) |
||||
assert.Equal(consts.TEST_TCP_ECHO_STR, res) |
||||
|
||||
// stop frps
|
||||
frpsProcess.Stop() |
||||
time.Sleep(200 * time.Millisecond) |
||||
|
||||
// test tcp, expect failed
|
||||
_, err = util.SendTCPMsg("127.0.0.1:20801", consts.TEST_TCP_ECHO_STR) |
||||
assert.Error(err) |
||||
|
||||
// restart frps
|
||||
newFrpsProcess := util.NewProcess(consts.FRPS_BIN_PATH, []string{"-c", frpsCfgPath}) |
||||
err = newFrpsProcess.Start() |
||||
if assert.NoError(err) { |
||||
defer newFrpsProcess.Stop() |
||||
} |
||||
|
||||
time.Sleep(2 * time.Second) |
||||
|
||||
// test tcp
|
||||
res, err = util.SendTCPMsg("127.0.0.1:20801", consts.TEST_TCP_ECHO_STR) |
||||
assert.NoError(err) |
||||
assert.Equal(consts.TEST_TCP_ECHO_STR, res) |
||||
} |
@ -1,150 +0,0 @@
|
||||
package ci |
||||
|
||||
import ( |
||||
"os" |
||||
"testing" |
||||
"time" |
||||
|
||||
"github.com/stretchr/testify/assert" |
||||
|
||||
"github.com/fatedier/frp/tests/config" |
||||
"github.com/fatedier/frp/tests/consts" |
||||
"github.com/fatedier/frp/tests/util" |
||||
) |
||||
|
||||
const FRPS_RELOAD_CONF = ` |
||||
[common] |
||||
bind_addr = 0.0.0.0 |
||||
bind_port = 20000 |
||||
log_file = console |
||||
# debug, info, warn, error |
||||
log_level = debug |
||||
token = 123456 |
||||
` |
||||
|
||||
const FRPC_RELOAD_CONF_1 = ` |
||||
[common] |
||||
server_addr = 127.0.0.1 |
||||
server_port = 20000 |
||||
log_file = console |
||||
# debug, info, warn, error |
||||
log_level = debug |
||||
token = 123456 |
||||
admin_port = 21000 |
||||
admin_user = abc |
||||
admin_pwd = abc |
||||
|
||||
[tcp] |
||||
type = tcp |
||||
local_port = 10701 |
||||
remote_port = 20801 |
||||
|
||||
# change remote port |
||||
[tcp2] |
||||
type = tcp |
||||
local_port = 10701 |
||||
remote_port = 20802 |
||||
|
||||
# delete |
||||
[tcp3] |
||||
type = tcp |
||||
local_port = 10701 |
||||
remote_port = 20803 |
||||
` |
||||
|
||||
const FRPC_RELOAD_CONF_2 = ` |
||||
[common] |
||||
server_addr = 127.0.0.1 |
||||
server_port = 20000 |
||||
log_file = console |
||||
# debug, info, warn, error |
||||
log_level = debug |
||||
token = 123456 |
||||
admin_port = 21000 |
||||
admin_user = abc |
||||
admin_pwd = abc |
||||
|
||||
[tcp] |
||||
type = tcp |
||||
local_port = 10701 |
||||
remote_port = 20801 |
||||
|
||||
[tcp2] |
||||
type = tcp |
||||
local_port = 10701 |
||||
remote_port = 20902 |
||||
` |
||||
|
||||
func TestReload(t *testing.T) { |
||||
assert := assert.New(t) |
||||
frpsCfgPath, err := config.GenerateConfigFile(consts.FRPS_NORMAL_CONFIG, FRPS_RELOAD_CONF) |
||||
if assert.NoError(err) { |
||||
defer os.Remove(frpsCfgPath) |
||||
} |
||||
|
||||
frpcCfgPath, err := config.GenerateConfigFile(consts.FRPC_NORMAL_CONFIG, FRPC_RELOAD_CONF_1) |
||||
if assert.NoError(err) { |
||||
rmFile1 := frpcCfgPath |
||||
defer os.Remove(rmFile1) |
||||
} |
||||
|
||||
frpsProcess := util.NewProcess(consts.FRPS_BIN_PATH, []string{"-c", frpsCfgPath}) |
||||
err = frpsProcess.Start() |
||||
if assert.NoError(err) { |
||||
defer frpsProcess.Stop() |
||||
} |
||||
|
||||
time.Sleep(500 * time.Millisecond) |
||||
|
||||
frpcProcess := util.NewProcess(consts.FRPC_BIN_PATH, []string{"-c", frpcCfgPath}) |
||||
err = frpcProcess.Start() |
||||
if assert.NoError(err) { |
||||
defer frpcProcess.Stop() |
||||
} |
||||
|
||||
time.Sleep(500 * time.Millisecond) |
||||
|
||||
// test tcp1
|
||||
res, err := util.SendTCPMsg("127.0.0.1:20801", consts.TEST_TCP_ECHO_STR) |
||||
assert.NoError(err) |
||||
assert.Equal(consts.TEST_TCP_ECHO_STR, res) |
||||
|
||||
// test tcp2
|
||||
res, err = util.SendTCPMsg("127.0.0.1:20802", consts.TEST_TCP_ECHO_STR) |
||||
assert.NoError(err) |
||||
assert.Equal(consts.TEST_TCP_ECHO_STR, res) |
||||
|
||||
// test tcp3
|
||||
res, err = util.SendTCPMsg("127.0.0.1:20803", consts.TEST_TCP_ECHO_STR) |
||||
assert.NoError(err) |
||||
assert.Equal(consts.TEST_TCP_ECHO_STR, res) |
||||
|
||||
// reload frpc config
|
||||
frpcCfgPath, err = config.GenerateConfigFile(consts.FRPC_NORMAL_CONFIG, FRPC_RELOAD_CONF_2) |
||||
if assert.NoError(err) { |
||||
rmFile2 := frpcCfgPath |
||||
defer os.Remove(rmFile2) |
||||
} |
||||
err = util.ReloadConf("127.0.0.1:21000", "abc", "abc") |
||||
assert.NoError(err) |
||||
|
||||
time.Sleep(time.Second) |
||||
|
||||
// test tcp1
|
||||
res, err = util.SendTCPMsg("127.0.0.1:20801", consts.TEST_TCP_ECHO_STR) |
||||
assert.NoError(err) |
||||
assert.Equal(consts.TEST_TCP_ECHO_STR, res) |
||||
|
||||
// test origin tcp2, expect failed
|
||||
res, err = util.SendTCPMsg("127.0.0.1:20802", consts.TEST_TCP_ECHO_STR) |
||||
assert.Error(err) |
||||
|
||||
// test new origin tcp2 with different port
|
||||
res, err = util.SendTCPMsg("127.0.0.1:20902", consts.TEST_TCP_ECHO_STR) |
||||
assert.NoError(err) |
||||
assert.Equal(consts.TEST_TCP_ECHO_STR, res) |
||||
|
||||
// test tcp3, expect failed
|
||||
res, err = util.SendTCPMsg("127.0.0.1:20803", consts.TEST_TCP_ECHO_STR) |
||||
assert.Error(err) |
||||
} |
@ -1,72 +0,0 @@
|
||||
package ci |
||||
|
||||
import ( |
||||
"os" |
||||
"testing" |
||||
"time" |
||||
|
||||
"github.com/fatedier/frp/tests/config" |
||||
"github.com/fatedier/frp/tests/consts" |
||||
"github.com/fatedier/frp/tests/util" |
||||
|
||||
"github.com/stretchr/testify/assert" |
||||
) |
||||
|
||||
const FRPS_TEMPLATE_CONF = ` |
||||
[common] |
||||
bind_addr = 0.0.0.0 |
||||
bind_port = {{ .Envs.SERVER_PORT }} |
||||
log_file = console |
||||
# debug, info, warn, error |
||||
log_level = debug |
||||
token = 123456 |
||||
` |
||||
|
||||
const FRPC_TEMPLATE_CONF = ` |
||||
[common] |
||||
server_addr = 127.0.0.1 |
||||
server_port = 20000 |
||||
log_file = console |
||||
# debug, info, warn, error |
||||
log_level = debug |
||||
token = {{ .Envs.FRP_TOKEN }} |
||||
|
||||
[tcp] |
||||
type = tcp |
||||
local_port = 10701 |
||||
remote_port = {{ .Envs.TCP_REMOTE_PORT }} |
||||
` |
||||
|
||||
func TestConfTemplate(t *testing.T) { |
||||
assert := assert.New(t) |
||||
frpsCfgPath, err := config.GenerateConfigFile(consts.FRPS_NORMAL_CONFIG, FRPS_TEMPLATE_CONF) |
||||
if assert.NoError(err) { |
||||
defer os.Remove(frpsCfgPath) |
||||
} |
||||
|
||||
frpcCfgPath, err := config.GenerateConfigFile(consts.FRPC_NORMAL_CONFIG, FRPC_TEMPLATE_CONF) |
||||
if assert.NoError(err) { |
||||
defer os.Remove(frpcCfgPath) |
||||
} |
||||
|
||||
frpsProcess := util.NewProcess("env", []string{"SERVER_PORT=20000", consts.FRPS_BIN_PATH, "-c", frpsCfgPath}) |
||||
err = frpsProcess.Start() |
||||
if assert.NoError(err) { |
||||
defer frpsProcess.Stop() |
||||
} |
||||
|
||||
time.Sleep(500 * time.Millisecond) |
||||
|
||||
frpcProcess := util.NewProcess("env", []string{"FRP_TOKEN=123456", "TCP_REMOTE_PORT=20801", consts.FRPC_BIN_PATH, "-c", frpcCfgPath}) |
||||
err = frpcProcess.Start() |
||||
if assert.NoError(err) { |
||||
defer frpcProcess.Stop() |
||||
} |
||||
|
||||
time.Sleep(500 * time.Millisecond) |
||||
|
||||
// test tcp1
|
||||
res, err := util.SendTCPMsg("127.0.0.1:20801", consts.TEST_TCP_ECHO_STR) |
||||
assert.NoError(err) |
||||
assert.Equal(consts.TEST_TCP_ECHO_STR, res) |
||||
} |
@ -1,13 +0,0 @@
|
||||
package config |
||||
|
||||
import ( |
||||
"io/ioutil" |
||||
"os" |
||||
"path/filepath" |
||||
) |
||||
|
||||
func GenerateConfigFile(path string, content string) (realPath string, err error) { |
||||
realPath = filepath.Join(os.TempDir(), path) |
||||
err = ioutil.WriteFile(realPath, []byte(content), 0666) |
||||
return realPath, err |
||||
} |
@ -1,76 +0,0 @@
|
||||
package consts |
||||
|
||||
import "path/filepath" |
||||
|
||||
var ( |
||||
FRPS_BIN_PATH = "../../bin/frps" |
||||
FRPC_BIN_PATH = "../../bin/frpc" |
||||
|
||||
FRPS_SUB_BIN_PATH = "../../../bin/frps" |
||||
FRPC_SUB_BIN_PATH = "../../../bin/frpc" |
||||
|
||||
FRPS_NORMAL_CONFIG = "./auto_test_frps.ini" |
||||
FRPC_NORMAL_CONFIG = "./auto_test_frpc.ini" |
||||
|
||||
SERVER_ADDR = "127.0.0.1" |
||||
ADMIN_ADDR = "127.0.0.1:10600" |
||||
ADMIN_USER = "abc" |
||||
ADMIN_PWD = "abc" |
||||
|
||||
TEST_STR = "frp is a fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet." |
||||
TEST_TCP_PORT int = 10701 |
||||
TEST_TCP2_PORT int = 10702 |
||||
TEST_TCP_FRP_PORT int = 10801 |
||||
TEST_TCP2_FRP_PORT int = 10802 |
||||
TEST_TCP_EC_FRP_PORT int = 10901 |
||||
TEST_TCP_ECHO_STR string = "tcp type:" + TEST_STR |
||||
|
||||
TEST_UDP_PORT int = 10702 |
||||
TEST_UDP_FRP_PORT int = 10802 |
||||
TEST_UDP_EC_FRP_PORT int = 10902 |
||||
TEST_UDP_ECHO_STR string = "udp type:" + TEST_STR |
||||
|
||||
TEST_UNIX_DOMAIN_ADDR string = "/tmp/frp_echo_server.sock" |
||||
TEST_UNIX_DOMAIN_FRP_PORT int = 10803 |
||||
TEST_UNIX_DOMAIN_STR string = "unix domain type:" + TEST_STR |
||||
|
||||
TEST_HTTP_PORT int = 10704 |
||||
TEST_HTTP_FRP_PORT int = 10804 |
||||
TEST_HTTP_NORMAL_STR string = "http normal string: " + TEST_STR |
||||
TEST_HTTP_FOO_STR string = "http foo string: " + TEST_STR |
||||
TEST_HTTP_BAR_STR string = "http bar string: " + TEST_STR |
||||
|
||||
TEST_TCP_MUX_FRP_PORT int = 10806 |
||||
|
||||
TEST_STCP_FRP_PORT int = 10805 |
||||
TEST_STCP_EC_FRP_PORT int = 10905 |
||||
TEST_STCP_ECHO_STR string = "stcp type:" + TEST_STR |
||||
|
||||
TEST_SUDP_FRP_PORT int = 10816 |
||||
TEST_SUDP_ECHO_STR string = "sudp type:" + TEST_STR |
||||
|
||||
ProxyTCPPortNotAllowed string = "tcp_port_not_allowed" |
||||
ProxyTCPPortUnavailable string = "tcp_port_unavailable" |
||||
ProxyTCPPortNormal string = "tcp_port_normal" |
||||
ProxyTCPRandomPort string = "tcp_random_port" |
||||
ProxyUDPPortNotAllowed string = "udp_port_not_allowed" |
||||
ProxyUDPPortNormal string = "udp_port_normal" |
||||
ProxyUDPRandomPort string = "udp_random_port" |
||||
ProxyHTTPProxy string = "http_proxy" |
||||
|
||||
ProxyRangeTCPPrefix string = "range_tcp" |
||||
) |
||||
|
||||
func init() { |
||||
if path, err := filepath.Abs(FRPS_BIN_PATH); err != nil { |
||||
panic(err) |
||||
} else { |
||||
FRPS_BIN_PATH = path |
||||
} |
||||
|
||||
if path, err := filepath.Abs(FRPC_BIN_PATH); err != nil { |
||||
panic(err) |
||||
} else { |
||||
FRPC_BIN_PATH = path |
||||
} |
||||
} |
@ -1,120 +0,0 @@
|
||||
package mock |
||||
|
||||
import ( |
||||
"fmt" |
||||
"io" |
||||
"net" |
||||
"os" |
||||
"syscall" |
||||
|
||||
frpNet "github.com/fatedier/frp/pkg/util/net" |
||||
) |
||||
|
||||
type EchoServer struct { |
||||
l net.Listener |
||||
|
||||
port int |
||||
repeatedNum int |
||||
specifyStr string |
||||
} |
||||
|
||||
func NewEchoServer(port int, repeatedNum int, specifyStr string) *EchoServer { |
||||
if repeatedNum <= 0 { |
||||
repeatedNum = 1 |
||||
} |
||||
return &EchoServer{ |
||||
port: port, |
||||
repeatedNum: repeatedNum, |
||||
specifyStr: specifyStr, |
||||
} |
||||
} |
||||
|
||||
func (es *EchoServer) Start() error { |
||||
l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", es.port)) |
||||
if err != nil { |
||||
fmt.Printf("echo server listen error: %v\n", err) |
||||
return err |
||||
} |
||||
es.l = l |
||||
|
||||
go func() { |
||||
for { |
||||
c, err := l.Accept() |
||||
if err != nil { |
||||
return |
||||
} |
||||
|
||||
go echoWorker(c, es.repeatedNum, es.specifyStr) |
||||
} |
||||
}() |
||||
return nil |
||||
} |
||||
|
||||
func (es *EchoServer) Stop() { |
||||
es.l.Close() |
||||
} |
||||
|
||||
func StartUDPEchoServer(port int) { |
||||
l, err := frpNet.ListenUDP("127.0.0.1", port) |
||||
if err != nil { |
||||
fmt.Printf("udp echo server listen error: %v\n", err) |
||||
return |
||||
} |
||||
|
||||
for { |
||||
c, err := l.Accept() |
||||
if err != nil { |
||||
fmt.Printf("udp echo server accept error: %v\n", err) |
||||
return |
||||
} |
||||
|
||||
go echoWorker(c, 1, "") |
||||
} |
||||
} |
||||
|
||||
func StartUnixDomainServer(unixPath string) { |
||||
os.Remove(unixPath) |
||||
syscall.Umask(0) |
||||
l, err := net.Listen("unix", unixPath) |
||||
if err != nil { |
||||
fmt.Printf("unix domain server listen error: %v\n", err) |
||||
return |
||||
} |
||||
|
||||
for { |
||||
c, err := l.Accept() |
||||
if err != nil { |
||||
fmt.Printf("unix domain server accept error: %v\n", err) |
||||
return |
||||
} |
||||
|
||||
go echoWorker(c, 1, "") |
||||
} |
||||
} |
||||
|
||||
func echoWorker(c net.Conn, repeatedNum int, specifyStr string) { |
||||
buf := make([]byte, 2048) |
||||
|
||||
for { |
||||
n, err := c.Read(buf) |
||||
if err != nil { |
||||
if err == io.EOF { |
||||
c.Close() |
||||
break |
||||
} else { |
||||
fmt.Printf("echo server read error: %v\n", err) |
||||
return |
||||
} |
||||
} |
||||
|
||||
if specifyStr != "" { |
||||
c.Write([]byte(specifyStr)) |
||||
} else { |
||||
var w []byte |
||||
for i := 0; i < repeatedNum; i++ { |
||||
w = append(w, buf[:n]...) |
||||
} |
||||
c.Write(w) |
||||
} |
||||
} |
||||
} |
@ -1,110 +0,0 @@
|
||||
package mock |
||||
|
||||
import ( |
||||
"fmt" |
||||
"log" |
||||
"net" |
||||
"net/http" |
||||
"regexp" |
||||
"strings" |
||||
|
||||
"github.com/fatedier/frp/tests/consts" |
||||
|
||||
"github.com/gorilla/websocket" |
||||
) |
||||
|
||||
type HTTPServer struct { |
||||
l net.Listener |
||||
|
||||
port int |
||||
handler http.HandlerFunc |
||||
} |
||||
|
||||
func NewHTTPServer(port int, handler http.HandlerFunc) *HTTPServer { |
||||
return &HTTPServer{ |
||||
port: port, |
||||
handler: handler, |
||||
} |
||||
} |
||||
|
||||
func (hs *HTTPServer) Start() error { |
||||
l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", hs.port)) |
||||
if err != nil { |
||||
fmt.Printf("http server listen error: %v\n", err) |
||||
return err |
||||
} |
||||
hs.l = l |
||||
|
||||
go http.Serve(l, http.HandlerFunc(hs.handler)) |
||||
return nil |
||||
} |
||||
|
||||
func (hs *HTTPServer) Stop() { |
||||
hs.l.Close() |
||||
} |
||||
|
||||
var upgrader = websocket.Upgrader{} |
||||
|
||||
func StartHTTPServer(port int) { |
||||
http.HandleFunc("/", handleHTTP) |
||||
http.HandleFunc("/ws", handleWebSocket) |
||||
http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", port), nil) |
||||
} |
||||
|
||||
func handleWebSocket(w http.ResponseWriter, r *http.Request) { |
||||
c, err := upgrader.Upgrade(w, r, nil) |
||||
if err != nil { |
||||
log.Print("upgrade:", err) |
||||
return |
||||
} |
||||
defer c.Close() |
||||
for { |
||||
mt, message, err := c.ReadMessage() |
||||
if err != nil { |
||||
break |
||||
} |
||||
err = c.WriteMessage(mt, message) |
||||
if err != nil { |
||||
log.Println("write:", err) |
||||
break |
||||
} |
||||
} |
||||
} |
||||
|
||||
func handleHTTP(w http.ResponseWriter, r *http.Request) { |
||||
if r.Header.Get("X-From-Where") == "frp" { |
||||
w.Header().Set("X-Header-Set", "true") |
||||
} |
||||
|
||||
match, err := regexp.Match(`.*\.sub\.com`, []byte(r.Host)) |
||||
if err != nil { |
||||
w.WriteHeader(500) |
||||
return |
||||
} |
||||
|
||||
if match { |
||||
w.WriteHeader(200) |
||||
w.Write([]byte(r.Host)) |
||||
return |
||||
} |
||||
|
||||
if strings.HasPrefix(r.Host, "127.0.0.1") || strings.HasPrefix(r.Host, "test2.frp.com") || |
||||
strings.HasPrefix(r.Host, "test5.frp.com") || strings.HasPrefix(r.Host, "test6.frp.com") || |
||||
strings.HasPrefix(r.Host, "test.frp1.com") || strings.HasPrefix(r.Host, "new.test.frp1.com") { |
||||
|
||||
w.WriteHeader(200) |
||||
w.Write([]byte(consts.TEST_HTTP_NORMAL_STR)) |
||||
} else if strings.Contains(r.Host, "test3.frp.com") { |
||||
w.WriteHeader(200) |
||||
if strings.Contains(r.URL.Path, "foo") { |
||||
w.Write([]byte(consts.TEST_HTTP_FOO_STR)) |
||||
} else if strings.Contains(r.URL.Path, "bar") { |
||||
w.Write([]byte(consts.TEST_HTTP_BAR_STR)) |
||||
} else { |
||||
w.Write([]byte(consts.TEST_HTTP_NORMAL_STR)) |
||||
} |
||||
} else { |
||||
w.WriteHeader(404) |
||||
} |
||||
return |
||||
} |
@ -1,47 +0,0 @@
|
||||
package util |
||||
|
||||
import ( |
||||
"bytes" |
||||
"context" |
||||
"os/exec" |
||||
) |
||||
|
||||
type Process struct { |
||||
cmd *exec.Cmd |
||||
cancel context.CancelFunc |
||||
errorOutput *bytes.Buffer |
||||
|
||||
beforeStopHandler func() |
||||
} |
||||
|
||||
func NewProcess(path string, params []string) *Process { |
||||
ctx, cancel := context.WithCancel(context.Background()) |
||||
cmd := exec.CommandContext(ctx, path, params...) |
||||
p := &Process{ |
||||
cmd: cmd, |
||||
cancel: cancel, |
||||
} |
||||
p.errorOutput = bytes.NewBufferString("") |
||||
cmd.Stderr = p.errorOutput |
||||
return p |
||||
} |
||||
|
||||
func (p *Process) Start() error { |
||||
return p.cmd.Start() |
||||
} |
||||
|
||||
func (p *Process) Stop() error { |
||||
if p.beforeStopHandler != nil { |
||||
p.beforeStopHandler() |
||||
} |
||||
p.cancel() |
||||
return p.cmd.Wait() |
||||
} |
||||
|
||||
func (p *Process) ErrorOutput() string { |
||||
return p.errorOutput.String() |
||||
} |
||||
|
||||
func (p *Process) SetBeforeStopHandler(fn func()) { |
||||
p.beforeStopHandler = fn |
||||
} |
@ -1,210 +0,0 @@
|
||||
package util |
||||
|
||||
import ( |
||||
"encoding/base64" |
||||
"encoding/json" |
||||
"errors" |
||||
"fmt" |
||||
"io" |
||||
"io/ioutil" |
||||
"net" |
||||
"net/http" |
||||
"net/url" |
||||
"strings" |
||||
"time" |
||||
|
||||
"github.com/fatedier/frp/client" |
||||
) |
||||
|
||||
func GetProxyStatus(statusAddr string, user string, passwd string, name string) (status *client.ProxyStatusResp, err error) { |
||||
req, err := http.NewRequest("GET", "http://"+statusAddr+"/api/status", nil) |
||||
if err != nil { |
||||
return status, err |
||||
} |
||||
|
||||
authStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(user+":"+passwd)) |
||||
req.Header.Add("Authorization", authStr) |
||||
resp, err := http.DefaultClient.Do(req) |
||||
if err != nil { |
||||
return status, err |
||||
} |
||||
defer resp.Body.Close() |
||||
if resp.StatusCode != 200 { |
||||
return status, fmt.Errorf("admin api status code [%d]", resp.StatusCode) |
||||
} |
||||
body, err := ioutil.ReadAll(resp.Body) |
||||
if err != nil { |
||||
return status, err |
||||
} |
||||
allStatus := &client.StatusResp{} |
||||
err = json.Unmarshal(body, &allStatus) |
||||
if err != nil { |
||||
return status, fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(string(body))) |
||||
} |
||||
for _, s := range allStatus.TCP { |
||||
if s.Name == name { |
||||
return &s, nil |
||||
} |
||||
} |
||||
for _, s := range allStatus.UDP { |
||||
if s.Name == name { |
||||
return &s, nil |
||||
} |
||||
} |
||||
for _, s := range allStatus.HTTP { |
||||
if s.Name == name { |
||||
return &s, nil |
||||
} |
||||
} |
||||
for _, s := range allStatus.HTTPS { |
||||
if s.Name == name { |
||||
return &s, nil |
||||
} |
||||
} |
||||
for _, s := range allStatus.STCP { |
||||
if s.Name == name { |
||||
return &s, nil |
||||
} |
||||
} |
||||
for _, s := range allStatus.XTCP { |
||||
if s.Name == name { |
||||
return &s, nil |
||||
} |
||||
} |
||||
for _, s := range allStatus.SUDP { |
||||
if s.Name == name { |
||||
return &s, nil |
||||
} |
||||
} |
||||
|
||||
return status, errors.New("no proxy status found") |
||||
} |
||||
|
||||
func ReloadConf(reloadAddr string, user string, passwd string) error { |
||||
req, err := http.NewRequest("GET", "http://"+reloadAddr+"/api/reload", nil) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
authStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(user+":"+passwd)) |
||||
req.Header.Add("Authorization", authStr) |
||||
resp, err := http.DefaultClient.Do(req) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
defer resp.Body.Close() |
||||
|
||||
if resp.StatusCode != 200 { |
||||
return fmt.Errorf("admin api status code [%d]", resp.StatusCode) |
||||
} |
||||
io.Copy(ioutil.Discard, resp.Body) |
||||
return nil |
||||
} |
||||
|
||||
func SendTCPMsg(addr string, msg string) (res string, err error) { |
||||
c, err := net.Dial("tcp", addr) |
||||
if err != nil { |
||||
err = fmt.Errorf("connect to tcp server error: %v", err) |
||||
return |
||||
} |
||||
defer c.Close() |
||||
return SendTCPMsgByConn(c, msg) |
||||
} |
||||
|
||||
func SendTCPMsgByConn(c net.Conn, msg string) (res string, err error) { |
||||
timer := time.Now().Add(5 * time.Second) |
||||
c.SetDeadline(timer) |
||||
c.Write([]byte(msg)) |
||||
|
||||
buf := make([]byte, 2048) |
||||
n, errRet := c.Read(buf) |
||||
if errRet != nil { |
||||
err = fmt.Errorf("read from tcp server error: %v", errRet) |
||||
return |
||||
} |
||||
return string(buf[:n]), nil |
||||
} |
||||
|
||||
func SendUDPMsg(addr string, msg string) (res string, err error) { |
||||
udpAddr, errRet := net.ResolveUDPAddr("udp", addr) |
||||
if errRet != nil { |
||||
err = fmt.Errorf("resolve udp addr error: %v", err) |
||||
return |
||||
} |
||||
conn, errRet := net.DialUDP("udp", nil, udpAddr) |
||||
if errRet != nil { |
||||
err = fmt.Errorf("dial udp server error: %v", err) |
||||
return |
||||
} |
||||
defer conn.Close() |
||||
_, err = conn.Write([]byte(msg)) |
||||
if err != nil { |
||||
err = fmt.Errorf("write to udp server error: %v", err) |
||||
return |
||||
} |
||||
|
||||
conn.SetReadDeadline(time.Now().Add(10 * time.Second)) |
||||
buf := make([]byte, 2048) |
||||
n, errRet := conn.Read(buf) |
||||
if errRet != nil { |
||||
err = fmt.Errorf("read from udp server error: %v", err) |
||||
return |
||||
} |
||||
return string(buf[:n]), nil |
||||
} |
||||
|
||||
func SendHTTPMsg(method, urlStr string, host string, headers map[string]string, proxy string) (code int, body string, header http.Header, err error) { |
||||
req, errRet := http.NewRequest(method, urlStr, nil) |
||||
if errRet != nil { |
||||
err = errRet |
||||
return |
||||
} |
||||
|
||||
if host != "" { |
||||
req.Host = host |
||||
} |
||||
for k, v := range headers { |
||||
req.Header.Set(k, v) |
||||
} |
||||
|
||||
tr := &http.Transport{ |
||||
DialContext: (&net.Dialer{ |
||||
Timeout: 30 * time.Second, |
||||
KeepAlive: 30 * time.Second, |
||||
DualStack: true, |
||||
}).DialContext, |
||||
MaxIdleConns: 100, |
||||
IdleConnTimeout: 90 * time.Second, |
||||
TLSHandshakeTimeout: 10 * time.Second, |
||||
ExpectContinueTimeout: 1 * time.Second, |
||||
} |
||||
|
||||
if len(proxy) != 0 { |
||||
tr.Proxy = func(req *http.Request) (*url.URL, error) { |
||||
return url.Parse(proxy) |
||||
} |
||||
} |
||||
client := http.Client{ |
||||
Transport: tr, |
||||
} |
||||
|
||||
resp, errRet := client.Do(req) |
||||
if errRet != nil { |
||||
err = errRet |
||||
return |
||||
} |
||||
code = resp.StatusCode |
||||
header = resp.Header |
||||
buf, errRet := ioutil.ReadAll(resp.Body) |
||||
if errRet != nil { |
||||
err = errRet |
||||
return |
||||
} |
||||
body = string(buf) |
||||
return |
||||
} |
||||
|
||||
func BasicAuth(username, passwd string) string { |
||||
auth := username + ":" + passwd |
||||
return "Basic " + base64.StdEncoding.EncodeToString([]byte(auth)) |
||||
} |
Loading…
Reference in new issue