mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-23 22:27:38 -05:00
proxy: Add basic proxying test and InsecureSkipVerify transport test
This commit is contained in:
parent
fae612d53b
commit
82b049229b
2 changed files with 112 additions and 9 deletions
|
@ -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…
Reference in a new issue