github.com/toplink-cn/moby@v0.0.0-20240305205811-460b4aebdf81/registry/search_endpoint_v1_test.go (about) 1 package registry // import "github.com/docker/docker/registry" 2 3 import ( 4 "net/http" 5 "net/http/httptest" 6 "strings" 7 "testing" 8 9 "github.com/docker/docker/api/types/registry" 10 "gotest.tools/v3/assert" 11 is "gotest.tools/v3/assert/cmp" 12 ) 13 14 func TestV1EndpointPing(t *testing.T) { 15 testPing := func(index *registry.IndexInfo, expectedStandalone bool, assertMessage string) { 16 ep, err := newV1Endpoint(index, nil) 17 if err != nil { 18 t.Fatal(err) 19 } 20 regInfo, err := ep.ping() 21 if err != nil { 22 t.Fatal(err) 23 } 24 25 assert.Equal(t, regInfo.Standalone, expectedStandalone, assertMessage) 26 } 27 28 testPing(makeIndex("/v1/"), true, "Expected standalone to be true (default)") 29 testPing(makeHTTPSIndex("/v1/"), true, "Expected standalone to be true (default)") 30 testPing(makePublicIndex(), false, "Expected standalone to be false for public index") 31 } 32 33 func TestV1Endpoint(t *testing.T) { 34 // Simple wrapper to fail test if err != nil 35 expandEndpoint := func(index *registry.IndexInfo) *v1Endpoint { 36 endpoint, err := newV1Endpoint(index, nil) 37 if err != nil { 38 t.Fatal(err) 39 } 40 return endpoint 41 } 42 43 assertInsecureIndex := func(index *registry.IndexInfo) { 44 index.Secure = true 45 _, err := newV1Endpoint(index, nil) 46 assert.ErrorContains(t, err, "insecure-registry", index.Name+": Expected insecure-registry error for insecure index") 47 index.Secure = false 48 } 49 50 assertSecureIndex := func(index *registry.IndexInfo) { 51 index.Secure = true 52 _, err := newV1Endpoint(index, nil) 53 assert.ErrorContains(t, err, "certificate signed by unknown authority", index.Name+": Expected cert error for secure index") 54 index.Secure = false 55 } 56 57 index := ®istry.IndexInfo{} 58 index.Name = makeURL("/v1/") 59 endpoint := expandEndpoint(index) 60 assert.Equal(t, endpoint.String(), index.Name, "Expected endpoint to be "+index.Name) 61 assertInsecureIndex(index) 62 63 index.Name = makeURL("") 64 endpoint = expandEndpoint(index) 65 assert.Equal(t, endpoint.String(), index.Name+"/v1/", index.Name+": Expected endpoint to be "+index.Name+"/v1/") 66 assertInsecureIndex(index) 67 68 httpURL := makeURL("") 69 index.Name = strings.SplitN(httpURL, "://", 2)[1] 70 endpoint = expandEndpoint(index) 71 assert.Equal(t, endpoint.String(), httpURL+"/v1/", index.Name+": Expected endpoint to be "+httpURL+"/v1/") 72 assertInsecureIndex(index) 73 74 index.Name = makeHTTPSURL("/v1/") 75 endpoint = expandEndpoint(index) 76 assert.Equal(t, endpoint.String(), index.Name, "Expected endpoint to be "+index.Name) 77 assertSecureIndex(index) 78 79 index.Name = makeHTTPSURL("") 80 endpoint = expandEndpoint(index) 81 assert.Equal(t, endpoint.String(), index.Name+"/v1/", index.Name+": Expected endpoint to be "+index.Name+"/v1/") 82 assertSecureIndex(index) 83 84 httpsURL := makeHTTPSURL("") 85 index.Name = strings.SplitN(httpsURL, "://", 2)[1] 86 endpoint = expandEndpoint(index) 87 assert.Equal(t, endpoint.String(), httpsURL+"/v1/", index.Name+": Expected endpoint to be "+httpsURL+"/v1/") 88 assertSecureIndex(index) 89 90 badEndpoints := []string{ 91 "http://127.0.0.1/v1/", 92 "https://127.0.0.1/v1/", 93 "http://127.0.0.1", 94 "https://127.0.0.1", 95 "127.0.0.1", 96 } 97 for _, address := range badEndpoints { 98 index.Name = address 99 _, err := newV1Endpoint(index, nil) 100 assert.Check(t, err != nil, "Expected error while expanding bad endpoint: %s", address) 101 } 102 } 103 104 func TestV1EndpointParse(t *testing.T) { 105 tests := []struct { 106 address string 107 expected string 108 expectedErr string 109 }{ 110 { 111 address: IndexServer, 112 expected: IndexServer, 113 }, 114 { 115 address: "https://0.0.0.0:5000/v1/", 116 expected: "https://0.0.0.0:5000/v1/", 117 }, 118 { 119 address: "https://0.0.0.0:5000", 120 expected: "https://0.0.0.0:5000/v1/", 121 }, 122 { 123 address: "0.0.0.0:5000", 124 expected: "https://0.0.0.0:5000/v1/", 125 }, 126 { 127 address: "https://0.0.0.0:5000/nonversion/", 128 expected: "https://0.0.0.0:5000/nonversion/v1/", 129 }, 130 { 131 address: "https://0.0.0.0:5000/v0/", 132 expected: "https://0.0.0.0:5000/v0/v1/", 133 }, 134 { 135 address: "https://0.0.0.0:5000/v2/", 136 expectedErr: "search is not supported on v2 endpoints: https://0.0.0.0:5000/v2/", 137 }, 138 } 139 for _, tc := range tests { 140 tc := tc 141 t.Run(tc.address, func(t *testing.T) { 142 ep, err := newV1EndpointFromStr(tc.address, nil, nil) 143 if tc.expectedErr != "" { 144 assert.Check(t, is.Error(err, tc.expectedErr)) 145 assert.Check(t, is.Nil(ep)) 146 } else { 147 assert.NilError(t, err) 148 assert.Check(t, is.Equal(ep.String(), tc.expected)) 149 } 150 }) 151 } 152 } 153 154 // Ensure that a registry endpoint that responds with a 401 only is determined 155 // to be a valid v1 registry endpoint 156 func TestV1EndpointValidate(t *testing.T) { 157 requireBasicAuthHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 158 w.Header().Add("WWW-Authenticate", `Basic realm="localhost"`) 159 w.WriteHeader(http.StatusUnauthorized) 160 }) 161 162 // Make a test server which should validate as a v1 server. 163 testServer := httptest.NewServer(requireBasicAuthHandler) 164 defer testServer.Close() 165 166 testEndpoint, err := newV1Endpoint(®istry.IndexInfo{Name: testServer.URL}, nil) 167 if err != nil { 168 t.Fatal(err) 169 } 170 171 if testEndpoint.URL.Scheme != "http" { 172 t.Fatalf("expecting to validate endpoint as http, got url %s", testEndpoint.String()) 173 } 174 } 175 176 func TestTrustedLocation(t *testing.T) { 177 for _, u := range []string{"http://example.com", "https://example.com:7777", "http://docker.io", "http://test.docker.com", "https://fakedocker.com"} { 178 req, _ := http.NewRequest(http.MethodGet, u, nil) 179 assert.Check(t, !trustedLocation(req)) 180 } 181 182 for _, u := range []string{"https://docker.io", "https://test.docker.com:80"} { 183 req, _ := http.NewRequest(http.MethodGet, u, nil) 184 assert.Check(t, trustedLocation(req)) 185 } 186 } 187 188 func TestAddRequiredHeadersToRedirectedRequests(t *testing.T) { 189 for _, urls := range [][]string{ 190 {"http://docker.io", "https://docker.com"}, 191 {"https://foo.docker.io:7777", "http://bar.docker.com"}, 192 {"https://foo.docker.io", "https://example.com"}, 193 } { 194 reqFrom, _ := http.NewRequest(http.MethodGet, urls[0], nil) 195 reqFrom.Header.Add("Content-Type", "application/json") 196 reqFrom.Header.Add("Authorization", "super_secret") 197 reqTo, _ := http.NewRequest(http.MethodGet, urls[1], nil) 198 199 _ = addRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom}) 200 201 if len(reqTo.Header) != 1 { 202 t.Fatalf("Expected 1 headers, got %d", len(reqTo.Header)) 203 } 204 205 if reqTo.Header.Get("Content-Type") != "application/json" { 206 t.Fatal("'Content-Type' should be 'application/json'") 207 } 208 209 if reqTo.Header.Get("Authorization") != "" { 210 t.Fatal("'Authorization' should be empty") 211 } 212 } 213 214 for _, urls := range [][]string{ 215 {"https://docker.io", "https://docker.com"}, 216 {"https://foo.docker.io:7777", "https://bar.docker.com"}, 217 } { 218 reqFrom, _ := http.NewRequest(http.MethodGet, urls[0], nil) 219 reqFrom.Header.Add("Content-Type", "application/json") 220 reqFrom.Header.Add("Authorization", "super_secret") 221 reqTo, _ := http.NewRequest(http.MethodGet, urls[1], nil) 222 223 _ = addRequiredHeadersToRedirectedRequests(reqTo, []*http.Request{reqFrom}) 224 225 if len(reqTo.Header) != 2 { 226 t.Fatalf("Expected 2 headers, got %d", len(reqTo.Header)) 227 } 228 229 if reqTo.Header.Get("Content-Type") != "application/json" { 230 t.Fatal("'Content-Type' should be 'application/json'") 231 } 232 233 if reqTo.Header.Get("Authorization") != "super_secret" { 234 t.Fatal("'Authorization' should be 'super_secret'") 235 } 236 } 237 }