14 "github.com/stretchr/testify/assert"
15 "github.com/stretchr/testify/require"
18 type redirectTest struct {
22 func TestClientRedirect(t *testing.T) {
23 var srv3Https, srv3Http string
28 srv3 := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
29 atomic.AddUint32(&called3, 1)
30 t.Logf("srv3 req %s %s", r.Method, r.URL.Path)
31 assert.Equal(t, "POST", r.Method)
35 assert.Equal(t, "auth", r.Header.Get("Authorization"))
36 assert.Equal(t, "1", r.Header.Get("A"))
37 w.Header().Set("Location", srv3Https+"/upgraded")
40 // Since srv3 listens on both a TLS-enabled socket and a
41 // TLS-disabled one, they are two different hosts.
42 // Ensure that, even though this is a "secure" upgrade,
43 // the authorization header is stripped.
44 assert.Equal(t, "", r.Header.Get("Authorization"))
45 assert.Equal(t, "1", r.Header.Get("A"))
48 assert.Equal(t, "auth", r.Header.Get("Authorization"))
49 assert.Equal(t, "1", r.Header.Get("A"))
50 w.Header().Set("Location", srv3Http+"/404")
58 srv2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
59 atomic.AddUint32(&called2, 1)
60 t.Logf("srv2 req %s %s", r.Method, r.URL.Path)
61 assert.Equal(t, "POST", r.Method)
65 assert.Equal(t, "", r.Header.Get("Authorization"))
66 assert.Equal(t, "1", r.Header.Get("A"))
67 body := &redirectTest{}
68 err := json.NewDecoder(r.Body).Decode(body)
70 assert.Equal(t, "External", body.Test)
78 srv1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
79 atomic.AddUint32(&called1, 1)
80 t.Logf("srv1 req %s %s", r.Method, r.URL.Path)
81 assert.Equal(t, "POST", r.Method)
85 w.Header().Set("Location", "/ok")
88 w.Header().Set("Location", srv2.URL+"/ok")
91 assert.Equal(t, "auth", r.Header.Get("Authorization"))
92 assert.Equal(t, "1", r.Header.Get("A"))
93 body := &redirectTest{}
94 err := json.NewDecoder(r.Body).Decode(body)
96 assert.Equal(t, "Local", body.Test)
107 srv3InsecureListener, err := net.Listen("tcp", "127.0.0.1:0")
110 go http.Serve(srv3InsecureListener, srv3.Config.Handler)
111 defer srv3InsecureListener.Close()
114 srv3Http = fmt.Sprintf("http://%s", srv3InsecureListener.Addr().String())
116 c, err := NewClient(NewContext(nil, nil, map[string]string{
117 fmt.Sprintf("http.%s.sslverify", srv3Https): "false",
118 fmt.Sprintf("http.%s/.sslverify", srv3Https): "false",
119 fmt.Sprintf("http.%s.sslverify", srv3Http): "false",
120 fmt.Sprintf("http.%s/.sslverify", srv3Http): "false",
121 fmt.Sprintf("http.sslverify"): "false",
126 req, err := http.NewRequest("POST", srv1.URL+"/local", nil)
128 req.Header.Set("Authorization", "auth")
129 req.Header.Set("A", "1")
131 require.Nil(t, MarshalToRequest(req, &redirectTest{Test: "Local"}))
133 res, err := c.Do(req)
135 assert.Equal(t, 200, res.StatusCode)
136 assert.EqualValues(t, 2, called1)
137 assert.EqualValues(t, 0, called2)
140 req, err = http.NewRequest("POST", srv1.URL+"/external", nil)
142 req.Header.Set("Authorization", "auth")
143 req.Header.Set("A", "1")
145 require.Nil(t, MarshalToRequest(req, &redirectTest{Test: "External"}))
149 assert.Equal(t, 200, res.StatusCode)
150 assert.EqualValues(t, 3, called1)
151 assert.EqualValues(t, 1, called2)
153 // http -> https (secure upgrade)
155 req, err = http.NewRequest("POST", srv3Http+"/upgrade", nil)
157 req.Header.Set("Authorization", "auth")
158 req.Header.Set("A", "1")
160 require.Nil(t, MarshalToRequest(req, &redirectTest{Test: "http->https"}))
164 assert.Equal(t, 200, res.StatusCode)
165 assert.EqualValues(t, 2, atomic.LoadUint32(&called3))
167 // https -> http (insecure downgrade)
169 req, err = http.NewRequest("POST", srv3Https+"/downgrade", nil)
171 req.Header.Set("Authorization", "auth")
172 req.Header.Set("A", "1")
174 require.Nil(t, MarshalToRequest(req, &redirectTest{Test: "https->http"}))
177 assert.EqualError(t, err, "lfsapi/client: refusing insecure redirect, https->http")
180 func TestClientRedirectReauthenticate(t *testing.T) {
181 var srv1, srv2 *httptest.Server
182 var called1, called2 uint32
183 var creds1, creds2 Creds
185 srv1 = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
186 atomic.AddUint32(&called1, 1)
188 if hdr := r.Header.Get("Authorization"); len(hdr) > 0 {
189 parts := strings.SplitN(hdr, " ", 2)
190 typ, b64 := parts[0], parts[1]
192 auth, err := base64.URLEncoding.DecodeString(b64)
194 assert.Equal(t, "Basic", typ)
195 assert.Equal(t, "user1:pass1", string(auth))
197 http.Redirect(w, r, srv2.URL+r.URL.Path, http.StatusMovedPermanently)
200 w.WriteHeader(http.StatusUnauthorized)
203 srv2 = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
204 atomic.AddUint32(&called2, 1)
206 parts := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
207 typ, b64 := parts[0], parts[1]
209 auth, err := base64.URLEncoding.DecodeString(b64)
211 assert.Equal(t, "Basic", typ)
212 assert.Equal(t, "user2:pass2", string(auth))
215 // Change the URL of srv2 to make it appears as if it is a different
217 srv2.URL = strings.Replace(srv2.URL, "127.0.0.1", "0.0.0.0", 1)
219 creds1 = Creds(map[string]string{
221 "host": strings.TrimPrefix(srv1.URL, "http://"),
226 creds2 = Creds(map[string]string{
228 "host": strings.TrimPrefix(srv2.URL, "http://"),
237 c, err := NewClient(NewContext(nil, nil, nil))
238 creds := newCredentialCacher()
239 creds.Approve(creds1)
240 creds.Approve(creds2)
241 c.Credentials = creds
243 req, err := http.NewRequest("GET", srv1.URL, nil)
246 _, err = c.DoWithAuth("", req)
249 // called1 is 2 since LFS tries an unauthenticated request first
250 assert.EqualValues(t, 2, called1)
251 assert.EqualValues(t, 1, called2)
254 func TestNewClient(t *testing.T) {
255 c, err := NewClient(NewContext(nil, nil, map[string]string{
256 "lfs.dialtimeout": "151",
257 "lfs.keepalive": "152",
258 "lfs.tlstimeout": "153",
259 "lfs.concurrenttransfers": "154",
263 assert.Equal(t, 151, c.DialTimeout)
264 assert.Equal(t, 152, c.KeepaliveTimeout)
265 assert.Equal(t, 153, c.TLSTimeout)
266 assert.Equal(t, 154, c.ConcurrentTransfers)
269 func TestNewClientWithGitSSLVerify(t *testing.T) {
270 c, err := NewClient(nil)
272 assert.False(t, c.SkipSSLVerify)
274 for _, value := range []string{"true", "1", "t"} {
275 c, err = NewClient(NewContext(nil, nil, map[string]string{
276 "http.sslverify": value,
278 t.Logf("http.sslverify: %q", value)
280 assert.False(t, c.SkipSSLVerify)
283 for _, value := range []string{"false", "0", "f"} {
284 c, err = NewClient(NewContext(nil, nil, map[string]string{
285 "http.sslverify": value,
287 t.Logf("http.sslverify: %q", value)
289 assert.True(t, c.SkipSSLVerify)
293 func TestNewClientWithOSSSLVerify(t *testing.T) {
294 c, err := NewClient(nil)
296 assert.False(t, c.SkipSSLVerify)
298 for _, value := range []string{"false", "0", "f"} {
299 c, err = NewClient(NewContext(nil, map[string]string{
300 "GIT_SSL_NO_VERIFY": value,
302 t.Logf("GIT_SSL_NO_VERIFY: %q", value)
304 assert.False(t, c.SkipSSLVerify)
307 for _, value := range []string{"true", "1", "t"} {
308 c, err = NewClient(NewContext(nil, map[string]string{
309 "GIT_SSL_NO_VERIFY": value,
311 t.Logf("GIT_SSL_NO_VERIFY: %q", value)
313 assert.True(t, c.SkipSSLVerify)
317 func TestNewRequest(t *testing.T) {
319 {"https://example.com", "a", "https://example.com/a"},
320 {"https://example.com/", "a", "https://example.com/a"},
321 {"https://example.com/a", "b", "https://example.com/a/b"},
322 {"https://example.com/a/", "b", "https://example.com/a/b"},
325 for _, test := range tests {
326 c, err := NewClient(NewContext(nil, nil, map[string]string{
331 req, err := c.NewRequest("POST", c.Endpoints.Endpoint("", ""), test[1], nil)
333 assert.Equal(t, "POST", req.Method)
334 assert.Equal(t, test[2], req.URL.String(), fmt.Sprintf("endpoint: %s, suffix: %s, expected: %s", test[0], test[1], test[2]))
338 func TestNewRequestWithBody(t *testing.T) {
339 c, err := NewClient(NewContext(nil, nil, map[string]string{
340 "lfs.url": "https://example.com",
347 req, err := c.NewRequest("POST", c.Endpoints.Endpoint("", ""), "body", body)
350 assert.NotNil(t, req.Body)
351 assert.Equal(t, "15", req.Header.Get("Content-Length"))
352 assert.EqualValues(t, 15, req.ContentLength)
355 func TestMarshalToRequest(t *testing.T) {
356 req, err := http.NewRequest("POST", "https://foo/bar", nil)
359 assert.Nil(t, req.Body)
360 assert.Equal(t, "", req.Header.Get("Content-Length"))
361 assert.EqualValues(t, 0, req.ContentLength)
366 require.Nil(t, MarshalToRequest(req, body))
368 assert.NotNil(t, req.Body)
369 assert.Equal(t, "15", req.Header.Get("Content-Length"))
370 assert.EqualValues(t, 15, req.ContentLength)