github.com/stffabi/git-lfs@v2.3.5-0.20180214015214-8eeaa8d88902+incompatible/lfsapi/client_test.go (about) 1 package lfsapi 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net" 7 "net/http" 8 "net/http/httptest" 9 "sync/atomic" 10 "testing" 11 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 ) 15 16 type redirectTest struct { 17 Test string 18 } 19 20 func TestClientRedirect(t *testing.T) { 21 var srv3Https, srv3Http string 22 23 var called1 uint32 24 var called2 uint32 25 var called3 uint32 26 srv3 := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 27 atomic.AddUint32(&called3, 1) 28 t.Logf("srv3 req %s %s", r.Method, r.URL.Path) 29 assert.Equal(t, "POST", r.Method) 30 31 switch r.URL.Path { 32 case "/upgrade": 33 assert.Equal(t, "auth", r.Header.Get("Authorization")) 34 assert.Equal(t, "1", r.Header.Get("A")) 35 w.Header().Set("Location", srv3Https+"/upgraded") 36 w.WriteHeader(301) 37 case "/upgraded": 38 // Since srv3 listens on both a TLS-enabled socket and a 39 // TLS-disabled one, they are two different hosts. 40 // Ensure that, even though this is a "secure" upgrade, 41 // the authorization header is stripped. 42 assert.Equal(t, "", r.Header.Get("Authorization")) 43 assert.Equal(t, "1", r.Header.Get("A")) 44 45 case "/downgrade": 46 assert.Equal(t, "auth", r.Header.Get("Authorization")) 47 assert.Equal(t, "1", r.Header.Get("A")) 48 w.Header().Set("Location", srv3Http+"/404") 49 w.WriteHeader(301) 50 51 default: 52 w.WriteHeader(404) 53 } 54 })) 55 56 srv2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 57 atomic.AddUint32(&called2, 1) 58 t.Logf("srv2 req %s %s", r.Method, r.URL.Path) 59 assert.Equal(t, "POST", r.Method) 60 61 switch r.URL.Path { 62 case "/ok": 63 assert.Equal(t, "", r.Header.Get("Authorization")) 64 assert.Equal(t, "1", r.Header.Get("A")) 65 body := &redirectTest{} 66 err := json.NewDecoder(r.Body).Decode(body) 67 assert.Nil(t, err) 68 assert.Equal(t, "External", body.Test) 69 70 w.WriteHeader(200) 71 default: 72 w.WriteHeader(404) 73 } 74 })) 75 76 srv1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 77 atomic.AddUint32(&called1, 1) 78 t.Logf("srv1 req %s %s", r.Method, r.URL.Path) 79 assert.Equal(t, "POST", r.Method) 80 81 switch r.URL.Path { 82 case "/local": 83 w.Header().Set("Location", "/ok") 84 w.WriteHeader(307) 85 case "/external": 86 w.Header().Set("Location", srv2.URL+"/ok") 87 w.WriteHeader(307) 88 case "/ok": 89 assert.Equal(t, "auth", r.Header.Get("Authorization")) 90 assert.Equal(t, "1", r.Header.Get("A")) 91 body := &redirectTest{} 92 err := json.NewDecoder(r.Body).Decode(body) 93 assert.Nil(t, err) 94 assert.Equal(t, "Local", body.Test) 95 96 w.WriteHeader(200) 97 default: 98 w.WriteHeader(404) 99 } 100 })) 101 defer srv1.Close() 102 defer srv2.Close() 103 defer srv3.Close() 104 105 srv3InsecureListener, err := net.Listen("tcp", "127.0.0.1:0") 106 require.Nil(t, err) 107 108 go http.Serve(srv3InsecureListener, srv3.Config.Handler) 109 defer srv3InsecureListener.Close() 110 111 srv3Https = srv3.URL 112 srv3Http = fmt.Sprintf("http://%s", srv3InsecureListener.Addr().String()) 113 114 c, err := NewClient(NewContext(nil, nil, map[string]string{ 115 fmt.Sprintf("http.%s.sslverify", srv3Https): "false", 116 fmt.Sprintf("http.%s/.sslverify", srv3Https): "false", 117 fmt.Sprintf("http.%s.sslverify", srv3Http): "false", 118 fmt.Sprintf("http.%s/.sslverify", srv3Http): "false", 119 fmt.Sprintf("http.sslverify"): "false", 120 })) 121 require.Nil(t, err) 122 123 // local redirect 124 req, err := http.NewRequest("POST", srv1.URL+"/local", nil) 125 require.Nil(t, err) 126 req.Header.Set("Authorization", "auth") 127 req.Header.Set("A", "1") 128 129 require.Nil(t, MarshalToRequest(req, &redirectTest{Test: "Local"})) 130 131 res, err := c.Do(req) 132 require.Nil(t, err) 133 assert.Equal(t, 200, res.StatusCode) 134 assert.EqualValues(t, 2, called1) 135 assert.EqualValues(t, 0, called2) 136 137 // external redirect 138 req, err = http.NewRequest("POST", srv1.URL+"/external", nil) 139 require.Nil(t, err) 140 req.Header.Set("Authorization", "auth") 141 req.Header.Set("A", "1") 142 143 require.Nil(t, MarshalToRequest(req, &redirectTest{Test: "External"})) 144 145 res, err = c.Do(req) 146 require.Nil(t, err) 147 assert.Equal(t, 200, res.StatusCode) 148 assert.EqualValues(t, 3, called1) 149 assert.EqualValues(t, 1, called2) 150 151 // http -> https (secure upgrade) 152 153 req, err = http.NewRequest("POST", srv3Http+"/upgrade", nil) 154 require.Nil(t, err) 155 req.Header.Set("Authorization", "auth") 156 req.Header.Set("A", "1") 157 158 require.Nil(t, MarshalToRequest(req, &redirectTest{Test: "http->https"})) 159 160 res, err = c.Do(req) 161 require.Nil(t, err) 162 assert.Equal(t, 200, res.StatusCode) 163 assert.EqualValues(t, 2, atomic.LoadUint32(&called3)) 164 165 // https -> http (insecure downgrade) 166 167 req, err = http.NewRequest("POST", srv3Https+"/downgrade", nil) 168 require.Nil(t, err) 169 req.Header.Set("Authorization", "auth") 170 req.Header.Set("A", "1") 171 172 require.Nil(t, MarshalToRequest(req, &redirectTest{Test: "https->http"})) 173 174 _, err = c.Do(req) 175 assert.EqualError(t, err, "lfsapi/client: refusing insecure redirect, https->http") 176 } 177 178 func TestNewClient(t *testing.T) { 179 c, err := NewClient(NewContext(nil, nil, map[string]string{ 180 "lfs.dialtimeout": "151", 181 "lfs.keepalive": "152", 182 "lfs.tlstimeout": "153", 183 "lfs.concurrenttransfers": "154", 184 })) 185 186 require.Nil(t, err) 187 assert.Equal(t, 151, c.DialTimeout) 188 assert.Equal(t, 152, c.KeepaliveTimeout) 189 assert.Equal(t, 153, c.TLSTimeout) 190 assert.Equal(t, 154, c.ConcurrentTransfers) 191 } 192 193 func TestNewClientWithGitSSLVerify(t *testing.T) { 194 c, err := NewClient(nil) 195 assert.Nil(t, err) 196 assert.False(t, c.SkipSSLVerify) 197 198 for _, value := range []string{"true", "1", "t"} { 199 c, err = NewClient(NewContext(nil, nil, map[string]string{ 200 "http.sslverify": value, 201 })) 202 t.Logf("http.sslverify: %q", value) 203 assert.Nil(t, err) 204 assert.False(t, c.SkipSSLVerify) 205 } 206 207 for _, value := range []string{"false", "0", "f"} { 208 c, err = NewClient(NewContext(nil, nil, map[string]string{ 209 "http.sslverify": value, 210 })) 211 t.Logf("http.sslverify: %q", value) 212 assert.Nil(t, err) 213 assert.True(t, c.SkipSSLVerify) 214 } 215 } 216 217 func TestNewClientWithOSSSLVerify(t *testing.T) { 218 c, err := NewClient(nil) 219 assert.Nil(t, err) 220 assert.False(t, c.SkipSSLVerify) 221 222 for _, value := range []string{"false", "0", "f"} { 223 c, err = NewClient(NewContext(nil, map[string]string{ 224 "GIT_SSL_NO_VERIFY": value, 225 }, nil)) 226 t.Logf("GIT_SSL_NO_VERIFY: %q", value) 227 assert.Nil(t, err) 228 assert.False(t, c.SkipSSLVerify) 229 } 230 231 for _, value := range []string{"true", "1", "t"} { 232 c, err = NewClient(NewContext(nil, map[string]string{ 233 "GIT_SSL_NO_VERIFY": value, 234 }, nil)) 235 t.Logf("GIT_SSL_NO_VERIFY: %q", value) 236 assert.Nil(t, err) 237 assert.True(t, c.SkipSSLVerify) 238 } 239 } 240 241 func TestNewRequest(t *testing.T) { 242 tests := [][]string{ 243 {"https://example.com", "a", "https://example.com/a"}, 244 {"https://example.com/", "a", "https://example.com/a"}, 245 {"https://example.com/a", "b", "https://example.com/a/b"}, 246 {"https://example.com/a/", "b", "https://example.com/a/b"}, 247 } 248 249 for _, test := range tests { 250 c, err := NewClient(NewContext(nil, nil, map[string]string{ 251 "lfs.url": test[0], 252 })) 253 require.Nil(t, err) 254 255 req, err := c.NewRequest("POST", c.Endpoints.Endpoint("", ""), test[1], nil) 256 require.Nil(t, err) 257 assert.Equal(t, "POST", req.Method) 258 assert.Equal(t, test[2], req.URL.String(), fmt.Sprintf("endpoint: %s, suffix: %s, expected: %s", test[0], test[1], test[2])) 259 } 260 } 261 262 func TestNewRequestWithBody(t *testing.T) { 263 c, err := NewClient(NewContext(nil, nil, map[string]string{ 264 "lfs.url": "https://example.com", 265 })) 266 require.Nil(t, err) 267 268 body := struct { 269 Test string 270 }{Test: "test"} 271 req, err := c.NewRequest("POST", c.Endpoints.Endpoint("", ""), "body", body) 272 require.Nil(t, err) 273 274 assert.NotNil(t, req.Body) 275 assert.Equal(t, "15", req.Header.Get("Content-Length")) 276 assert.EqualValues(t, 15, req.ContentLength) 277 } 278 279 func TestMarshalToRequest(t *testing.T) { 280 req, err := http.NewRequest("POST", "https://foo/bar", nil) 281 require.Nil(t, err) 282 283 assert.Nil(t, req.Body) 284 assert.Equal(t, "", req.Header.Get("Content-Length")) 285 assert.EqualValues(t, 0, req.ContentLength) 286 287 body := struct { 288 Test string 289 }{Test: "test"} 290 require.Nil(t, MarshalToRequest(req, body)) 291 292 assert.NotNil(t, req.Body) 293 assert.Equal(t, "15", req.Header.Get("Content-Length")) 294 assert.EqualValues(t, 15, req.ContentLength) 295 }