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