github.com/coreos/goproxy@v0.0.0-20190513173959-f8dc2d7ba04e/ext/auth/basic_test.go (about)

     1  package auth_test
     2  
     3  import (
     4  	"encoding/base64"
     5  	"io"
     6  	"io/ioutil"
     7  	"net"
     8  	"net/http"
     9  	"net/http/httptest"
    10  	"net/url"
    11  	"os"
    12  	"os/exec"
    13  	"os/signal"
    14  	"sync/atomic"
    15  	"testing"
    16  
    17  	"github.com/elazarl/goproxy"
    18  	"github.com/elazarl/goproxy/ext/auth"
    19  )
    20  
    21  type ConstantHanlder string
    22  
    23  func (h ConstantHanlder) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    24  	io.WriteString(w, string(h))
    25  }
    26  
    27  func oneShotProxy(proxy *goproxy.ProxyHttpServer) (client *http.Client, s *httptest.Server) {
    28  	s = httptest.NewServer(proxy)
    29  
    30  	proxyUrl, _ := url.Parse(s.URL)
    31  	tr := &http.Transport{Proxy: http.ProxyURL(proxyUrl)}
    32  	client = &http.Client{Transport: tr}
    33  	return
    34  }
    35  
    36  func times(n int, s string) string {
    37  	r := make([]byte, 0, n*len(s))
    38  	for i := 0; i < n; i++ {
    39  		r = append(r, s...)
    40  	}
    41  	return string(r)
    42  }
    43  
    44  func TestBasicConnectAuthWithCurl(t *testing.T) {
    45  	expected := ":c>"
    46  	background := httptest.NewTLSServer(ConstantHanlder(expected))
    47  	defer background.Close()
    48  	proxy := goproxy.NewProxyHttpServer()
    49  	proxy.OnRequest().HandleConnect(auth.BasicConnect("my_realm", func(user, passwd string) bool {
    50  		return user == "user" && passwd == "open sesame"
    51  	}))
    52  	_, proxyserver := oneShotProxy(proxy)
    53  	defer proxyserver.Close()
    54  
    55  	cmd := exec.Command("curl",
    56  		"--silent", "--show-error", "--insecure",
    57  		"-x", proxyserver.URL,
    58  		"-U", "user:open sesame",
    59  		"-p",
    60  		"--url", background.URL+"/[1-3]",
    61  	)
    62  	out, err := cmd.CombinedOutput() // if curl got error, it'll show up in stderr
    63  	if err != nil {
    64  		t.Fatal(err, string(out))
    65  	}
    66  	finalexpected := times(3, expected)
    67  	if string(out) != finalexpected {
    68  		t.Error("Expected", finalexpected, "got", string(out))
    69  	}
    70  }
    71  
    72  func TestBasicAuthWithCurl(t *testing.T) {
    73  	expected := ":c>"
    74  	background := httptest.NewServer(ConstantHanlder(expected))
    75  	defer background.Close()
    76  	proxy := goproxy.NewProxyHttpServer()
    77  	proxy.OnRequest().Do(auth.Basic("my_realm", func(user, passwd string) bool {
    78  		return user == "user" && passwd == "open sesame"
    79  	}))
    80  	_, proxyserver := oneShotProxy(proxy)
    81  	defer proxyserver.Close()
    82  
    83  	cmd := exec.Command("curl",
    84  		"--silent", "--show-error",
    85  		"-x", proxyserver.URL,
    86  		"-U", "user:open sesame",
    87  		"--url", background.URL+"/[1-3]",
    88  	)
    89  	out, err := cmd.CombinedOutput() // if curl got error, it'll show up in stderr
    90  	if err != nil {
    91  		t.Fatal(err, string(out))
    92  	}
    93  	finalexpected := times(3, expected)
    94  	if string(out) != finalexpected {
    95  		t.Error("Expected", finalexpected, "got", string(out))
    96  	}
    97  }
    98  
    99  func TestBasicAuth(t *testing.T) {
   100  	expected := "hello"
   101  	background := httptest.NewServer(ConstantHanlder(expected))
   102  	defer background.Close()
   103  	proxy := goproxy.NewProxyHttpServer()
   104  	proxy.OnRequest().Do(auth.Basic("my_realm", func(user, passwd string) bool {
   105  		return user == "user" && passwd == "open sesame"
   106  	}))
   107  	client, proxyserver := oneShotProxy(proxy)
   108  	defer proxyserver.Close()
   109  
   110  	// without auth
   111  	resp, err := client.Get(background.URL)
   112  	if err != nil {
   113  		t.Fatal(err)
   114  	}
   115  	if resp.Header.Get("Proxy-Authenticate") != "Basic realm=my_realm" {
   116  		t.Error("Expected Proxy-Authenticate header got", resp.Header.Get("Proxy-Authenticate"))
   117  	}
   118  	if resp.StatusCode != 407 {
   119  		t.Error("Expected status 407 Proxy Authentication Required, got", resp.Status)
   120  	}
   121  
   122  	// with auth
   123  	req, err := http.NewRequest("GET", background.URL, nil)
   124  	if err != nil {
   125  		t.Fatal(err)
   126  	}
   127  	req.Header.Set("Proxy-Authorization",
   128  		"Basic "+base64.StdEncoding.EncodeToString([]byte("user:open sesame")))
   129  	resp, err = client.Do(req)
   130  	if err != nil {
   131  		t.Fatal(err)
   132  	}
   133  	if resp.StatusCode != 200 {
   134  		t.Error("Expected status 200 OK, got", resp.Status)
   135  	}
   136  	msg, err := ioutil.ReadAll(resp.Body)
   137  	if err != nil {
   138  		t.Fatal(err)
   139  	}
   140  	if string(msg) != "hello" {
   141  		t.Errorf("Expected '%s', actual '%s'", expected, string(msg))
   142  	}
   143  }
   144  
   145  func TestWithBrowser(t *testing.T) {
   146  	// an easy way to check if auth works with webserver
   147  	// to test, run with
   148  	// $ go test -run TestWithBrowser -- server
   149  	// configure a browser to use the printed proxy address, use the proxy
   150  	// and exit with Ctrl-C. It will throw error if your haven't acutally used the proxy
   151  	if os.Args[len(os.Args)-1] != "server" {
   152  		return
   153  	}
   154  	proxy := goproxy.NewProxyHttpServer()
   155  	println("proxy localhost port 8082")
   156  	access := int32(0)
   157  	proxy.OnRequest().Do(auth.Basic("my_realm", func(user, passwd string) bool {
   158  		atomic.AddInt32(&access, 1)
   159  		return user == "user" && passwd == "1234"
   160  	}))
   161  	l, err := net.Listen("tcp", "localhost:8082")
   162  	if err != nil {
   163  		t.Fatal(err)
   164  	}
   165  	ch := make(chan os.Signal)
   166  	signal.Notify(ch, os.Interrupt)
   167  	go func() {
   168  		<-ch
   169  		l.Close()
   170  	}()
   171  	http.Serve(l, proxy)
   172  	if access <= 0 {
   173  		t.Error("No one accessed the proxy")
   174  	}
   175  }