github.com/slspeek/camlistore_namedsearch@v0.0.0-20140519202248-ed6f70f7721a/pkg/httputil/auth_test.go (about) 1 /* 2 Copyright 2013 The Camlistore Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package httputil 18 19 import ( 20 "fmt" 21 "io/ioutil" 22 "net" 23 "net/http" 24 "net/http/httptest" 25 "testing" 26 ) 27 28 func testServer(t *testing.T, l net.Listener) *httptest.Server { 29 ts := &httptest.Server{ 30 Listener: l, 31 Config: &http.Server{ 32 Handler: http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { 33 if IsLocalhost(r) { 34 fmt.Fprintf(rw, "authorized") 35 return 36 } 37 fmt.Fprintf(rw, "unauthorized") 38 }), 39 }, 40 } 41 ts.Start() 42 43 return ts 44 } 45 46 func TestLocalhostAuthIPv6(t *testing.T) { 47 l, err := net.Listen("tcp", "[::1]:0") 48 if err != nil { 49 t.Skip("skipping IPv6 test; can't listen on [::1]:0") 50 } 51 _, port, err := net.SplitHostPort(l.Addr().String()) 52 if err != nil { 53 t.Fatal(err) 54 } 55 56 // See if IPv6 works on this machine first. It seems the above 57 // Listen can pass on Linux but fail here in the dial. 58 c, err := net.Dial("tcp6", l.Addr().String()) 59 if err != nil { 60 t.Skipf("skipping IPv6 test; dial back to %s failed with %v", l.Addr(), err) 61 } 62 c.Close() 63 64 ts := testServer(t, l) 65 defer ts.Close() 66 67 // Use an explicit transport to force IPv6 (http.Get resolves localhost in IPv4 otherwise) 68 trans := &http.Transport{ 69 Dial: func(network, addr string) (net.Conn, error) { 70 c, err := net.Dial("tcp6", addr) 71 return c, err 72 }, 73 } 74 75 testLoginRequest(t, &http.Client{Transport: trans}, "http://[::1]:"+port) 76 77 // See if we can get an IPv6 from resolving localhost 78 localips, err := net.LookupIP("localhost") 79 if err != nil { 80 t.Skipf("skipping IPv6 test; resolving localhost failed with %v", err) 81 } 82 if hasIPv6(localips) { 83 testLoginRequest(t, &http.Client{Transport: trans}, "http://localhost:"+port) 84 } else { 85 t.Logf("incomplete IPv6 test; resolving localhost didn't return any IPv6 addresses") 86 } 87 } 88 89 func hasIPv6(ips []net.IP) bool { 90 for _, ip := range ips { 91 if ip.To4() == nil { 92 return true 93 } 94 } 95 return false 96 } 97 98 func TestLocalhostAuthIPv4(t *testing.T) { 99 l, err := net.Listen("tcp", "127.0.0.1:0") 100 if err != nil { 101 t.Skip("skipping IPv4 test; can't listen on 127.0.0.1:0") 102 } 103 _, port, err := net.SplitHostPort(l.Addr().String()) 104 if err != nil { 105 t.Fatal(err) 106 } 107 108 ts := testServer(t, l) 109 defer ts.Close() 110 111 testLoginRequest(t, &http.Client{}, "http://127.0.0.1:"+port) 112 testLoginRequest(t, &http.Client{}, "http://localhost:"+port) 113 } 114 115 func testLoginRequest(t *testing.T, client *http.Client, URL string) { 116 res, err := client.Get(URL) 117 if err != nil { 118 t.Fatal(err) 119 } 120 body, err := ioutil.ReadAll(res.Body) 121 if err != nil { 122 t.Fatal(err) 123 } 124 const exp = "authorized" 125 if string(body) != exp { 126 t.Errorf("got %q (instead of %v)", string(body), exp) 127 } 128 } 129 130 func TestBasicAuth(t *testing.T) { 131 for _, d := range []struct { 132 header string 133 u, pw string 134 valid bool 135 }{ 136 // Empty is invalid. 137 {}, 138 { 139 // Missing password. 140 header: "Basic QWxhZGRpbg==", 141 }, 142 { 143 // Malformed base64 encoding. 144 header: "Basic foo", 145 }, 146 { 147 // Malformed header, no 'Basic ' prefix. 148 header: "QWxhZGRpbg==", 149 }, 150 { 151 header: "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", 152 u: "Aladdin", 153 pw: "open sesame", 154 valid: true, 155 }, 156 } { 157 req, err := http.NewRequest("GET", "/", nil) 158 if err != nil { 159 t.Fatal(err) 160 } 161 if d.header != "" { 162 req.Header.Set("Authorization", d.header) 163 } 164 165 u, pw, err := BasicAuth(req) 166 t.Log(d.header, err) 167 if d.valid && err != nil { 168 t.Error("Want success parse of auth header, got", err) 169 } 170 if !d.valid && err == nil { 171 t.Error("Want error parsing", d.header) 172 } 173 174 if d.u != u { 175 t.Errorf("Want user %q, got %q", d.u, u) 176 } 177 178 if d.pw != pw { 179 t.Errorf("Want password %q, got %q", d.pw, pw) 180 } 181 } 182 }