mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-10-31 10:37:24 -04:00 
			
		
		
		
	proxy: Add basic proxying test and InsecureSkipVerify transport test
This commit is contained in:
		
							parent
							
								
									fae612d53b
								
							
						
					
					
						commit
						82b049229b
					
				| @ -57,6 +57,10 @@ func (uh *UpstreamHost) Down() bool { | |||||||
| 	return uh.CheckDown(uh) | 	return uh.CheckDown(uh) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // tryDuration is how long to try upstream hosts; failures result in | ||||||
|  | // immediate retries until this duration ends or we get a nil host. | ||||||
|  | var tryDuration = 60 * time.Second | ||||||
|  | 
 | ||||||
| // ServeHTTP satisfies the middleware.Handler interface. | // ServeHTTP satisfies the middleware.Handler interface. | ||||||
| func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { | func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { | ||||||
| 
 | 
 | ||||||
| @ -68,7 +72,7 @@ func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { | |||||||
| 
 | 
 | ||||||
| 			// Since Select() should give us "up" hosts, keep retrying | 			// Since Select() should give us "up" hosts, keep retrying | ||||||
| 			// hosts until timeout (or until we get a nil host). | 			// hosts until timeout (or until we get a nil host). | ||||||
| 			for time.Now().Sub(start) < (60 * time.Second) { | 			for time.Now().Sub(start) < tryDuration { | ||||||
| 				host := upstream.Select() | 				host := upstream.Select() | ||||||
| 				if host == nil { | 				if host == nil { | ||||||
| 					return http.StatusBadGateway, errUnreachable | 					return http.StatusBadGateway, errUnreachable | ||||||
|  | |||||||
| @ -4,10 +4,13 @@ import ( | |||||||
| 	"bufio" | 	"bufio" | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"io/ioutil" | ||||||
|  | 	"log" | ||||||
| 	"net" | 	"net" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"net/http/httptest" | 	"net/http/httptest" | ||||||
| 	"net/url" | 	"net/url" | ||||||
|  | 	"os" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" | 	"time" | ||||||
| @ -15,6 +18,70 @@ import ( | |||||||
| 	"golang.org/x/net/websocket" | 	"golang.org/x/net/websocket" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | func init() { | ||||||
|  | 	tryDuration = 50 * time.Millisecond // prevent tests from hanging | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestReverseProxy(t *testing.T) { | ||||||
|  | 	log.SetOutput(ioutil.Discard) | ||||||
|  | 	defer log.SetOutput(os.Stderr) | ||||||
|  | 
 | ||||||
|  | 	var requestReceived bool | ||||||
|  | 	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 		requestReceived = true | ||||||
|  | 		w.Write([]byte("Hello, client")) | ||||||
|  | 	})) | ||||||
|  | 	defer backend.Close() | ||||||
|  | 
 | ||||||
|  | 	// set up proxy | ||||||
|  | 	p := &Proxy{ | ||||||
|  | 		Upstreams: []Upstream{newFakeUpstream(backend.URL, false)}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// create request and response recorder | ||||||
|  | 	r, err := http.NewRequest("GET", "/", nil) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("Failed to create request: %v", err) | ||||||
|  | 	} | ||||||
|  | 	w := httptest.NewRecorder() | ||||||
|  | 
 | ||||||
|  | 	p.ServeHTTP(w, r) | ||||||
|  | 
 | ||||||
|  | 	if !requestReceived { | ||||||
|  | 		t.Error("Expected backend to receive request, but it didn't") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestReverseProxyInsecureSkipVerify(t *testing.T) { | ||||||
|  | 	log.SetOutput(ioutil.Discard) | ||||||
|  | 	defer log.SetOutput(os.Stderr) | ||||||
|  | 
 | ||||||
|  | 	var requestReceived bool | ||||||
|  | 	backend := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 		requestReceived = true | ||||||
|  | 		w.Write([]byte("Hello, client")) | ||||||
|  | 	})) | ||||||
|  | 	defer backend.Close() | ||||||
|  | 
 | ||||||
|  | 	// set up proxy | ||||||
|  | 	p := &Proxy{ | ||||||
|  | 		Upstreams: []Upstream{newFakeUpstream(backend.URL, true)}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// create request and response recorder | ||||||
|  | 	r, err := http.NewRequest("GET", "/", nil) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("Failed to create request: %v", err) | ||||||
|  | 	} | ||||||
|  | 	w := httptest.NewRecorder() | ||||||
|  | 
 | ||||||
|  | 	p.ServeHTTP(w, r) | ||||||
|  | 
 | ||||||
|  | 	if !requestReceived { | ||||||
|  | 		t.Error("Even with insecure HTTPS, expected backend to receive request, but it didn't") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func TestWebSocketReverseProxyServeHTTPHandler(t *testing.T) { | func TestWebSocketReverseProxyServeHTTPHandler(t *testing.T) { | ||||||
| 	// No-op websocket backend simply allows the WS connection to be | 	// No-op websocket backend simply allows the WS connection to be | ||||||
| 	// accepted then it will be immediately closed. Perfect for testing. | 	// accepted then it will be immediately closed. Perfect for testing. | ||||||
| @ -93,18 +160,24 @@ func TestWebSocketReverseProxyFromWSClient(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // newWebSocketTestProxy returns a test proxy that will | func newFakeUpstream(name string, insecure bool) *fakeUpstream { | ||||||
| // redirect to the specified backendAddr. The function | 	uri, _ := url.Parse(name) | ||||||
| // also sets up the rules/environment for testing WebSocket | 	u := &fakeUpstream{ | ||||||
| // proxy. | 		name: name, | ||||||
| func newWebSocketTestProxy(backendAddr string) *Proxy { | 		host: &UpstreamHost{ | ||||||
| 	return &Proxy{ | 			Name:         name, | ||||||
| 		Upstreams: []Upstream{&fakeUpstream{name: backendAddr}}, | 			ReverseProxy: NewSingleHostReverseProxy(uri, ""), | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
|  | 	if insecure { | ||||||
|  | 		u.host.ReverseProxy.Transport = InsecureTransport | ||||||
|  | 	} | ||||||
|  | 	return u | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type fakeUpstream struct { | type fakeUpstream struct { | ||||||
| 	name string | 	name string | ||||||
|  | 	host *UpstreamHost | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (u *fakeUpstream) From() string { | func (u *fakeUpstream) From() string { | ||||||
| @ -112,6 +185,32 @@ func (u *fakeUpstream) From() string { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (u *fakeUpstream) Select() *UpstreamHost { | func (u *fakeUpstream) Select() *UpstreamHost { | ||||||
|  | 	return u.host | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (u *fakeUpstream) IsAllowedPath(requestPath string) bool { | ||||||
|  | 	return true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // newWebSocketTestProxy returns a test proxy that will | ||||||
|  | // redirect to the specified backendAddr. The function | ||||||
|  | // also sets up the rules/environment for testing WebSocket | ||||||
|  | // proxy. | ||||||
|  | func newWebSocketTestProxy(backendAddr string) *Proxy { | ||||||
|  | 	return &Proxy{ | ||||||
|  | 		Upstreams: []Upstream{&fakeWsUpstream{name: backendAddr}}, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type fakeWsUpstream struct { | ||||||
|  | 	name string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (u *fakeWsUpstream) From() string { | ||||||
|  | 	return "/" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (u *fakeWsUpstream) Select() *UpstreamHost { | ||||||
| 	uri, _ := url.Parse(u.name) | 	uri, _ := url.Parse(u.name) | ||||||
| 	return &UpstreamHost{ | 	return &UpstreamHost{ | ||||||
| 		Name:         u.name, | 		Name:         u.name, | ||||||
| @ -122,7 +221,7 @@ func (u *fakeUpstream) Select() *UpstreamHost { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (u *fakeUpstream) IsAllowedPath(requestPath string) bool { | func (u *fakeWsUpstream) IsAllowedPath(requestPath string) bool { | ||||||
| 	return true | 	return true | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user