mosn

Форк
0
/
redirect_test.go 
225 строк · 5.4 Кб
1
package functiontest
2

3
import (
4
	"crypto/tls"
5
	"fmt"
6
	"io"
7
	"io/ioutil"
8
	"net"
9
	"net/http"
10
	"net/url"
11
	"testing"
12
	"time"
13

14
	"golang.org/x/net/http2"
15

16
	v2 "mosn.io/mosn/pkg/config/v2"
17
	"mosn.io/mosn/pkg/protocol"
18
	"mosn.io/mosn/pkg/types"
19
	"mosn.io/mosn/test/util"
20
	"mosn.io/mosn/test/util/mosn"
21
)
22

23
// Test Redirect
24

25
// Redirect ignores upstream cluster information and route rule config
26
func CreateRedirectMeshProxy(addr string, proto types.ProtocolName, redirect *v2.RedirectAction) *v2.MOSNConfig {
27
	cmconfig := v2.ClusterManagerConfig{
28
		Clusters: []v2.Cluster{
29
			{
30
				Name: "cluster",
31
			},
32
		},
33
	}
34
	routers := []v2.Router{
35
		NewRedirectResponsePrefixRouter("/", redirect),
36
	}
37
	chains := []v2.FilterChain{
38
		util.NewFilterChain("proxyVirtualHost", proto, proto, routers),
39
	}
40
	listener := util.NewListener("proxyListener", addr, chains)
41
	return util.NewMOSNConfig([]v2.Listener{listener}, cmconfig)
42
}
43

44
func NewRedirectResponsePrefixRouter(prefix string, redirect *v2.RedirectAction) v2.Router {
45
	return v2.Router{
46
		RouterConfig: v2.RouterConfig{
47
			Match:    v2.RouterMatch{Prefix: prefix},
48
			Redirect: redirect,
49
		},
50
	}
51
}
52

53
// Proxy Mode is OK
54
type RedirectResponseCase struct {
55
	Protocol   types.ProtocolName
56
	C          chan error
57
	T          *testing.T
58
	ClientAddr string
59
	Finish     chan bool
60
	redirect   *v2.RedirectAction
61
}
62

63
func NewRedirectResponseCase(t *testing.T, proto types.ProtocolName, redirect *v2.RedirectAction) *RedirectResponseCase {
64
	return &RedirectResponseCase{
65
		Protocol: proto,
66
		C:        make(chan error),
67
		T:        t,
68
		Finish:   make(chan bool),
69
		redirect: redirect,
70
	}
71
}
72

73
func (c *RedirectResponseCase) StartProxy() {
74
	addr := util.CurrentMeshAddr()
75
	c.ClientAddr = addr
76
	cfg := CreateRedirectMeshProxy(addr, c.Protocol, c.redirect)
77
	mesh := mosn.NewMosn(cfg)
78
	go mesh.Start()
79
	go func() {
80
		<-c.Finish
81
		mesh.Close()
82
		c.Finish <- true
83
	}()
84
	time.Sleep(5 * time.Second) // wait server and mesh start
85
}
86

87
func (c *RedirectResponseCase) FinishCase() {
88
	c.Finish <- true
89
	<-c.Finish
90
}
91

92
func (c *RedirectResponseCase) RunCase(n int, interval time.Duration) {
93
	var (
94
		call func() error
95

96
		scheme = "http"
97
		path   = "/"
98
		host   = c.ClientAddr
99
	)
100
	if len(c.redirect.SchemeRedirect) != 0 {
101
		scheme = c.redirect.SchemeRedirect
102
	}
103
	if len(c.redirect.PathRedirect) != 0 {
104
		path = c.redirect.PathRedirect
105
	}
106
	if len(c.redirect.HostRedirect) != 0 {
107
		host = c.redirect.HostRedirect
108
	}
109
	u := url.URL{
110
		Scheme: scheme,
111
		Host:   host,
112
		Path:   path,
113
	}
114
	expectedLocation := u.String()
115
	expectedCode := c.redirect.ResponseCode
116
	if expectedCode == 0 {
117
		expectedCode = http.StatusMovedPermanently
118
	}
119

120
	checkRedirect := func(req *http.Request, via []*http.Request) error {
121
		// do not follow redirects
122
		return http.ErrUseLastResponse
123
	}
124
	http1Client := http.Client{
125
		CheckRedirect: checkRedirect,
126
	}
127
	http2Client := http.Client{
128
		CheckRedirect: checkRedirect,
129
		Transport: &http2.Transport{
130
			AllowHTTP: true,
131
			DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
132
				return net.Dial(network, addr)
133
			},
134
		},
135
	}
136

137
	switch c.Protocol {
138
	case protocol.HTTP1:
139
		call = func() error {
140
			url := fmt.Sprintf("http://%s/", c.ClientAddr)
141
			resp, err := http1Client.Get(url)
142
			if err != nil {
143
				return err
144
			}
145
			defer resp.Body.Close()
146
			_, _ = io.Copy(ioutil.Discard, resp.Body)
147
			if resp.StatusCode != expectedCode {
148
				return fmt.Errorf("unexpected response status: %d", resp.StatusCode)
149
			}
150
			gotLocation := resp.Header.Get("location")
151
			if gotLocation != expectedLocation {
152
				return fmt.Errorf("unexpected location: %s", gotLocation)
153
			}
154
			return nil
155
		}
156
	case protocol.HTTP2:
157
		call = func() error {
158
			url := fmt.Sprintf("http://%s/", c.ClientAddr)
159
			resp, err := http2Client.Get(url)
160
			if err != nil {
161
				return err
162
			}
163
			defer resp.Body.Close()
164
			_, _ = io.Copy(ioutil.Discard, resp.Body)
165
			if resp.StatusCode != expectedCode {
166
				return fmt.Errorf("unexpected response status: %d", resp.StatusCode)
167
			}
168
			gotLocation := resp.Header.Get("location")
169
			if gotLocation != expectedLocation {
170
				return fmt.Errorf("unexpected location: %s", gotLocation)
171
			}
172
			return nil
173
		}
174
	default:
175
		c.C <- fmt.Errorf("unknown protocol: %s", c.Protocol)
176
		return
177
	}
178
	for i := 0; i < n; i++ {
179
		if err := call(); err != nil {
180
			c.C <- err
181
			return
182
		}
183
		time.Sleep(interval)
184
	}
185
	c.C <- nil
186
}
187

188
func TestRedirect(t *testing.T) {
189
	testCases := []*RedirectResponseCase{
190
		NewRedirectResponseCase(t, protocol.HTTP1, &v2.RedirectAction{
191
			PathRedirect: "/foo",
192
		}),
193
		NewRedirectResponseCase(t, protocol.HTTP1, &v2.RedirectAction{
194
			ResponseCode: http.StatusTemporaryRedirect,
195
			HostRedirect: "foo.com",
196
		}),
197
		NewRedirectResponseCase(t, protocol.HTTP1, &v2.RedirectAction{
198
			SchemeRedirect: "https",
199
		}),
200
		NewRedirectResponseCase(t, protocol.HTTP2, &v2.RedirectAction{
201
			PathRedirect: "/foo",
202
		}),
203
		NewRedirectResponseCase(t, protocol.HTTP2, &v2.RedirectAction{
204
			ResponseCode: http.StatusTemporaryRedirect,
205
			HostRedirect: "foo.com",
206
		}),
207
		NewRedirectResponseCase(t, protocol.HTTP2, &v2.RedirectAction{
208
			SchemeRedirect: "https",
209
		}),
210
	}
211
	for i, tc := range testCases {
212
		t.Logf("start case #%d\n", i)
213
		tc.StartProxy()
214
		go tc.RunCase(1, 0)
215
		select {
216
		case err := <-tc.C:
217
			if err != nil {
218
				t.Errorf("[ERROR MESSAGE] #%d protocol %v test failed, error: %v\n", i, tc.Protocol, err)
219
			}
220
		case <-time.After(5 * time.Second):
221
			t.Errorf("[ERROR MESSAGE] #%d protocol %v hang\n", i, tc.Protocol)
222
		}
223
		tc.FinishCase()
224
	}
225
}
226

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.