github.com/mika/distribution@v2.2.2-0.20160108133430-a75790e3d8e0+incompatible/registry/api/v2/urls_test.go (about) 1 package v2 2 3 import ( 4 "net/http" 5 "net/url" 6 "testing" 7 ) 8 9 type urlBuilderTestCase struct { 10 description string 11 expectedPath string 12 build func() (string, error) 13 } 14 15 func makeURLBuilderTestCases(urlBuilder *URLBuilder) []urlBuilderTestCase { 16 return []urlBuilderTestCase{ 17 { 18 description: "test base url", 19 expectedPath: "/v2/", 20 build: urlBuilder.BuildBaseURL, 21 }, 22 { 23 description: "test tags url", 24 expectedPath: "/v2/foo/bar/tags/list", 25 build: func() (string, error) { 26 return urlBuilder.BuildTagsURL("foo/bar") 27 }, 28 }, 29 { 30 description: "test manifest url", 31 expectedPath: "/v2/foo/bar/manifests/tag", 32 build: func() (string, error) { 33 return urlBuilder.BuildManifestURL("foo/bar", "tag") 34 }, 35 }, 36 { 37 description: "build blob url", 38 expectedPath: "/v2/foo/bar/blobs/sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5", 39 build: func() (string, error) { 40 return urlBuilder.BuildBlobURL("foo/bar", "sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5") 41 }, 42 }, 43 { 44 description: "build blob upload url", 45 expectedPath: "/v2/foo/bar/blobs/uploads/", 46 build: func() (string, error) { 47 return urlBuilder.BuildBlobUploadURL("foo/bar") 48 }, 49 }, 50 { 51 description: "build blob upload url with digest and size", 52 expectedPath: "/v2/foo/bar/blobs/uploads/?digest=sha256%3A3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5&size=10000", 53 build: func() (string, error) { 54 return urlBuilder.BuildBlobUploadURL("foo/bar", url.Values{ 55 "size": []string{"10000"}, 56 "digest": []string{"sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5"}, 57 }) 58 }, 59 }, 60 { 61 description: "build blob upload chunk url", 62 expectedPath: "/v2/foo/bar/blobs/uploads/uuid-part", 63 build: func() (string, error) { 64 return urlBuilder.BuildBlobUploadChunkURL("foo/bar", "uuid-part") 65 }, 66 }, 67 { 68 description: "build blob upload chunk url with digest and size", 69 expectedPath: "/v2/foo/bar/blobs/uploads/uuid-part?digest=sha256%3A3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5&size=10000", 70 build: func() (string, error) { 71 return urlBuilder.BuildBlobUploadChunkURL("foo/bar", "uuid-part", url.Values{ 72 "size": []string{"10000"}, 73 "digest": []string{"sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5"}, 74 }) 75 }, 76 }, 77 } 78 } 79 80 // TestURLBuilder tests the various url building functions, ensuring they are 81 // returning the expected values. 82 func TestURLBuilder(t *testing.T) { 83 roots := []string{ 84 "http://example.com", 85 "https://example.com", 86 "http://localhost:5000", 87 "https://localhost:5443", 88 } 89 90 for _, root := range roots { 91 urlBuilder, err := NewURLBuilderFromString(root) 92 if err != nil { 93 t.Fatalf("unexpected error creating urlbuilder: %v", err) 94 } 95 96 for _, testCase := range makeURLBuilderTestCases(urlBuilder) { 97 url, err := testCase.build() 98 if err != nil { 99 t.Fatalf("%s: error building url: %v", testCase.description, err) 100 } 101 102 expectedURL := root + testCase.expectedPath 103 104 if url != expectedURL { 105 t.Fatalf("%s: %q != %q", testCase.description, url, expectedURL) 106 } 107 } 108 } 109 } 110 111 func TestURLBuilderWithPrefix(t *testing.T) { 112 roots := []string{ 113 "http://example.com/prefix/", 114 "https://example.com/prefix/", 115 "http://localhost:5000/prefix/", 116 "https://localhost:5443/prefix/", 117 } 118 119 for _, root := range roots { 120 urlBuilder, err := NewURLBuilderFromString(root) 121 if err != nil { 122 t.Fatalf("unexpected error creating urlbuilder: %v", err) 123 } 124 125 for _, testCase := range makeURLBuilderTestCases(urlBuilder) { 126 url, err := testCase.build() 127 if err != nil { 128 t.Fatalf("%s: error building url: %v", testCase.description, err) 129 } 130 131 expectedURL := root[0:len(root)-1] + testCase.expectedPath 132 133 if url != expectedURL { 134 t.Fatalf("%s: %q != %q", testCase.description, url, expectedURL) 135 } 136 } 137 } 138 } 139 140 type builderFromRequestTestCase struct { 141 request *http.Request 142 base string 143 } 144 145 func TestBuilderFromRequest(t *testing.T) { 146 u, err := url.Parse("http://example.com") 147 if err != nil { 148 t.Fatal(err) 149 } 150 151 forwardedProtoHeader := make(http.Header, 1) 152 forwardedProtoHeader.Set("X-Forwarded-Proto", "https") 153 154 forwardedHostHeader1 := make(http.Header, 1) 155 forwardedHostHeader1.Set("X-Forwarded-Host", "first.example.com") 156 157 forwardedHostHeader2 := make(http.Header, 1) 158 forwardedHostHeader2.Set("X-Forwarded-Host", "first.example.com, proxy1.example.com") 159 160 testRequests := []struct { 161 request *http.Request 162 base string 163 configHost url.URL 164 }{ 165 { 166 request: &http.Request{URL: u, Host: u.Host}, 167 base: "http://example.com", 168 }, 169 170 { 171 request: &http.Request{URL: u, Host: u.Host, Header: forwardedProtoHeader}, 172 base: "http://example.com", 173 }, 174 { 175 request: &http.Request{URL: u, Host: u.Host, Header: forwardedProtoHeader}, 176 base: "https://example.com", 177 }, 178 { 179 request: &http.Request{URL: u, Host: u.Host, Header: forwardedHostHeader1}, 180 base: "http://first.example.com", 181 }, 182 { 183 request: &http.Request{URL: u, Host: u.Host, Header: forwardedHostHeader2}, 184 base: "http://first.example.com", 185 }, 186 { 187 request: &http.Request{URL: u, Host: u.Host, Header: forwardedHostHeader2}, 188 base: "https://third.example.com:5000", 189 configHost: url.URL{ 190 Scheme: "https", 191 Host: "third.example.com:5000", 192 }, 193 }, 194 } 195 196 for _, tr := range testRequests { 197 var builder *URLBuilder 198 if tr.configHost.Scheme != "" && tr.configHost.Host != "" { 199 builder = NewURLBuilder(&tr.configHost) 200 } else { 201 builder = NewURLBuilderFromRequest(tr.request) 202 } 203 204 for _, testCase := range makeURLBuilderTestCases(builder) { 205 buildURL, err := testCase.build() 206 if err != nil { 207 t.Fatalf("%s: error building url: %v", testCase.description, err) 208 } 209 210 var expectedURL string 211 proto, ok := tr.request.Header["X-Forwarded-Proto"] 212 if !ok { 213 expectedURL = tr.base + testCase.expectedPath 214 } else { 215 urlBase, err := url.Parse(tr.base) 216 if err != nil { 217 t.Fatal(err) 218 } 219 urlBase.Scheme = proto[0] 220 expectedURL = urlBase.String() + testCase.expectedPath 221 } 222 223 if buildURL != expectedURL { 224 t.Fatalf("%s: %q != %q", testCase.description, buildURL, expectedURL) 225 } 226 } 227 } 228 } 229 230 func TestBuilderFromRequestWithPrefix(t *testing.T) { 231 u, err := url.Parse("http://example.com/prefix/v2/") 232 if err != nil { 233 t.Fatal(err) 234 } 235 236 forwardedProtoHeader := make(http.Header, 1) 237 forwardedProtoHeader.Set("X-Forwarded-Proto", "https") 238 239 testRequests := []struct { 240 request *http.Request 241 base string 242 configHost url.URL 243 }{ 244 { 245 request: &http.Request{URL: u, Host: u.Host}, 246 base: "http://example.com/prefix/", 247 }, 248 249 { 250 request: &http.Request{URL: u, Host: u.Host, Header: forwardedProtoHeader}, 251 base: "http://example.com/prefix/", 252 }, 253 { 254 request: &http.Request{URL: u, Host: u.Host, Header: forwardedProtoHeader}, 255 base: "https://example.com/prefix/", 256 }, 257 { 258 request: &http.Request{URL: u, Host: u.Host, Header: forwardedProtoHeader}, 259 base: "https://subdomain.example.com/prefix/", 260 configHost: url.URL{ 261 Scheme: "https", 262 Host: "subdomain.example.com", 263 Path: "/prefix/", 264 }, 265 }, 266 } 267 268 for _, tr := range testRequests { 269 var builder *URLBuilder 270 if tr.configHost.Scheme != "" && tr.configHost.Host != "" { 271 builder = NewURLBuilder(&tr.configHost) 272 } else { 273 builder = NewURLBuilderFromRequest(tr.request) 274 } 275 276 for _, testCase := range makeURLBuilderTestCases(builder) { 277 buildURL, err := testCase.build() 278 if err != nil { 279 t.Fatalf("%s: error building url: %v", testCase.description, err) 280 } 281 var expectedURL string 282 proto, ok := tr.request.Header["X-Forwarded-Proto"] 283 if !ok { 284 expectedURL = tr.base[0:len(tr.base)-1] + testCase.expectedPath 285 } else { 286 urlBase, err := url.Parse(tr.base) 287 if err != nil { 288 t.Fatal(err) 289 } 290 urlBase.Scheme = proto[0] 291 expectedURL = urlBase.String()[0:len(urlBase.String())-1] + testCase.expectedPath 292 } 293 294 if buildURL != expectedURL { 295 t.Fatalf("%s: %q != %q", testCase.description, buildURL, expectedURL) 296 } 297 } 298 } 299 }