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 }