123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- 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 protocol", 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))
- })
- })
|