Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 1 | // Copyright 2018 The Go Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
| 5 | package main_test |
| 6 | |
| 7 | import ( |
| 8 | "archive/zip" |
| 9 | "bytes" |
| 10 | "encoding/json" |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 11 | "errors" |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 12 | "flag" |
| 13 | "fmt" |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 14 | "io" |
Colin Cross | 1f80552 | 2021-05-14 11:10:59 -0700 | [diff] [blame] | 15 | "io/fs" |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 16 | "log" |
| 17 | "net" |
| 18 | "net/http" |
| 19 | "os" |
| 20 | "path/filepath" |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 21 | "strconv" |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 22 | "strings" |
| 23 | "sync" |
| 24 | "testing" |
| 25 | |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 26 | "cmd/go/internal/modfetch/codehost" |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 27 | "cmd/go/internal/par" |
Patrice Arruda | 748609c | 2020-06-25 12:12:21 -0700 | [diff] [blame] | 28 | |
| 29 | "golang.org/x/mod/module" |
| 30 | "golang.org/x/mod/semver" |
| 31 | "golang.org/x/mod/sumdb" |
| 32 | "golang.org/x/mod/sumdb/dirhash" |
Dan Willemsen | bc60c3c | 2021-12-15 01:09:00 -0800 | [diff] [blame] | 33 | "golang.org/x/tools/txtar" |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 34 | ) |
| 35 | |
| 36 | var ( |
| 37 | proxyAddr = flag.String("proxy", "", "run proxy on this network address instead of running any tests") |
| 38 | proxyURL string |
| 39 | ) |
| 40 | |
| 41 | var proxyOnce sync.Once |
| 42 | |
| 43 | // StartProxy starts the Go module proxy running on *proxyAddr (like "localhost:1234") |
| 44 | // and sets proxyURL to the GOPROXY setting to use to access the proxy. |
| 45 | // Subsequent calls are no-ops. |
| 46 | // |
| 47 | // The proxy serves from testdata/mod. See testdata/mod/README. |
| 48 | func StartProxy() { |
| 49 | proxyOnce.Do(func() { |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 50 | readModList() |
| 51 | addr := *proxyAddr |
| 52 | if addr == "" { |
| 53 | addr = "localhost:0" |
| 54 | } |
| 55 | l, err := net.Listen("tcp", addr) |
| 56 | if err != nil { |
| 57 | log.Fatal(err) |
| 58 | } |
| 59 | *proxyAddr = l.Addr().String() |
| 60 | proxyURL = "http://" + *proxyAddr + "/mod" |
| 61 | fmt.Fprintf(os.Stderr, "go test proxy running at GOPROXY=%s\n", proxyURL) |
| 62 | go func() { |
| 63 | log.Fatalf("go proxy: http.Serve: %v", http.Serve(l, http.HandlerFunc(proxyHandler))) |
| 64 | }() |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 65 | |
| 66 | // Prepopulate main sumdb. |
| 67 | for _, mod := range modList { |
Patrice Arruda | 748609c | 2020-06-25 12:12:21 -0700 | [diff] [blame] | 68 | sumdbOps.Lookup(nil, mod) |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 69 | } |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 70 | }) |
| 71 | } |
| 72 | |
| 73 | var modList []module.Version |
| 74 | |
| 75 | func readModList() { |
Colin Cross | 1f80552 | 2021-05-14 11:10:59 -0700 | [diff] [blame] | 76 | files, err := os.ReadDir("testdata/mod") |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 77 | if err != nil { |
| 78 | log.Fatal(err) |
| 79 | } |
Colin Cross | 1f80552 | 2021-05-14 11:10:59 -0700 | [diff] [blame] | 80 | for _, f := range files { |
| 81 | name := f.Name() |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 82 | if !strings.HasSuffix(name, ".txt") { |
| 83 | continue |
| 84 | } |
| 85 | name = strings.TrimSuffix(name, ".txt") |
| 86 | i := strings.LastIndex(name, "_v") |
| 87 | if i < 0 { |
| 88 | continue |
| 89 | } |
Colin Cross | d9c6b80 | 2019-03-19 21:10:31 -0700 | [diff] [blame] | 90 | encPath := strings.ReplaceAll(name[:i], "_", "/") |
Patrice Arruda | 748609c | 2020-06-25 12:12:21 -0700 | [diff] [blame] | 91 | path, err := module.UnescapePath(encPath) |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 92 | if err != nil { |
Colin Cross | 1f80552 | 2021-05-14 11:10:59 -0700 | [diff] [blame] | 93 | if testing.Verbose() && encPath != "example.com/invalidpath/v1" { |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 94 | fmt.Fprintf(os.Stderr, "go proxy_test: %v\n", err) |
| 95 | } |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 96 | continue |
| 97 | } |
| 98 | encVers := name[i+1:] |
Patrice Arruda | 748609c | 2020-06-25 12:12:21 -0700 | [diff] [blame] | 99 | vers, err := module.UnescapeVersion(encVers) |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 100 | if err != nil { |
| 101 | fmt.Fprintf(os.Stderr, "go proxy_test: %v\n", err) |
| 102 | continue |
| 103 | } |
| 104 | modList = append(modList, module.Version{Path: path, Version: vers}) |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | var zipCache par.Cache |
| 109 | |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 110 | const ( |
| 111 | testSumDBName = "localhost.localdev/sumdb" |
| 112 | testSumDBVerifierKey = "localhost.localdev/sumdb+00000c67+AcTrnkbUA+TU4heY3hkjiSES/DSQniBqIeQ/YppAUtK6" |
| 113 | testSumDBSignerKey = "PRIVATE+KEY+localhost.localdev/sumdb+00000c67+AXu6+oaVaOYuQOFrf1V59JK1owcFlJcHwwXHDfDGxSPk" |
| 114 | ) |
| 115 | |
Patrice Arruda | 748609c | 2020-06-25 12:12:21 -0700 | [diff] [blame] | 116 | var ( |
| 117 | sumdbOps = sumdb.NewTestServer(testSumDBSignerKey, proxyGoSum) |
| 118 | sumdbServer = sumdb.NewServer(sumdbOps) |
| 119 | |
| 120 | sumdbWrongOps = sumdb.NewTestServer(testSumDBSignerKey, proxyGoSumWrong) |
| 121 | sumdbWrongServer = sumdb.NewServer(sumdbWrongOps) |
| 122 | ) |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 123 | |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 124 | // proxyHandler serves the Go module proxy protocol. |
| 125 | // See the proxy section of https://research.swtch.com/vgo-module. |
| 126 | func proxyHandler(w http.ResponseWriter, r *http.Request) { |
| 127 | if !strings.HasPrefix(r.URL.Path, "/mod/") { |
| 128 | http.NotFound(w, r) |
| 129 | return |
| 130 | } |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 131 | path := r.URL.Path[len("/mod/"):] |
| 132 | |
Colin Cross | 1f80552 | 2021-05-14 11:10:59 -0700 | [diff] [blame] | 133 | // /mod/invalid returns faulty responses. |
| 134 | if strings.HasPrefix(path, "invalid/") { |
| 135 | w.Write([]byte("invalid")) |
| 136 | return |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 137 | } |
| 138 | |
| 139 | // Next element may opt into special behavior. |
| 140 | if j := strings.Index(path, "/"); j >= 0 { |
| 141 | n, err := strconv.Atoi(path[:j]) |
| 142 | if err == nil && n >= 200 { |
| 143 | w.WriteHeader(n) |
| 144 | return |
| 145 | } |
| 146 | if strings.HasPrefix(path, "sumdb-") { |
| 147 | n, err := strconv.Atoi(path[len("sumdb-"):j]) |
| 148 | if err == nil && n >= 200 { |
| 149 | if strings.HasPrefix(path[j:], "/sumdb/") { |
| 150 | w.WriteHeader(n) |
| 151 | return |
| 152 | } |
| 153 | path = path[j+1:] |
| 154 | } |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | // Request for $GOPROXY/sumdb-direct is direct sumdb access. |
| 159 | // (Client thinks it is talking directly to a sumdb.) |
| 160 | if strings.HasPrefix(path, "sumdb-direct/") { |
| 161 | r.URL.Path = path[len("sumdb-direct"):] |
Patrice Arruda | 748609c | 2020-06-25 12:12:21 -0700 | [diff] [blame] | 162 | sumdbServer.ServeHTTP(w, r) |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 163 | return |
| 164 | } |
| 165 | |
| 166 | // Request for $GOPROXY/sumdb-wrong is direct sumdb access |
| 167 | // but all the hashes are wrong. |
| 168 | // (Client thinks it is talking directly to a sumdb.) |
| 169 | if strings.HasPrefix(path, "sumdb-wrong/") { |
| 170 | r.URL.Path = path[len("sumdb-wrong"):] |
Patrice Arruda | 748609c | 2020-06-25 12:12:21 -0700 | [diff] [blame] | 171 | sumdbWrongServer.ServeHTTP(w, r) |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 172 | return |
| 173 | } |
| 174 | |
Patrice Arruda | 4fc930d | 2020-08-03 23:20:51 +0000 | [diff] [blame] | 175 | // Request for $GOPROXY/redirect/<count>/... goes to redirects. |
| 176 | if strings.HasPrefix(path, "redirect/") { |
| 177 | path = path[len("redirect/"):] |
| 178 | if j := strings.Index(path, "/"); j >= 0 { |
| 179 | count, err := strconv.Atoi(path[:j]) |
| 180 | if err != nil { |
| 181 | return |
| 182 | } |
| 183 | |
| 184 | // The last redirect. |
| 185 | if count <= 1 { |
| 186 | http.Redirect(w, r, fmt.Sprintf("/mod/%s", path[j+1:]), 302) |
| 187 | return |
| 188 | } |
| 189 | http.Redirect(w, r, fmt.Sprintf("/mod/redirect/%d/%s", count-1, path[j+1:]), 302) |
| 190 | return |
| 191 | } |
| 192 | } |
| 193 | |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 194 | // Request for $GOPROXY/sumdb/<name>/supported |
| 195 | // is checking whether it's OK to access sumdb via the proxy. |
| 196 | if path == "sumdb/"+testSumDBName+"/supported" { |
| 197 | w.WriteHeader(200) |
| 198 | return |
| 199 | } |
| 200 | |
| 201 | // Request for $GOPROXY/sumdb/<name>/... goes to sumdb. |
| 202 | if sumdbPrefix := "sumdb/" + testSumDBName + "/"; strings.HasPrefix(path, sumdbPrefix) { |
| 203 | r.URL.Path = path[len(sumdbPrefix)-1:] |
Patrice Arruda | 748609c | 2020-06-25 12:12:21 -0700 | [diff] [blame] | 204 | sumdbServer.ServeHTTP(w, r) |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 205 | return |
| 206 | } |
| 207 | |
| 208 | // Module proxy request: /mod/path/@latest |
| 209 | // Rewrite to /mod/path/@v/<latest>.info where <latest> is the semantically |
| 210 | // latest version, including pseudo-versions. |
| 211 | if i := strings.LastIndex(path, "/@latest"); i >= 0 { |
| 212 | enc := path[:i] |
Patrice Arruda | 748609c | 2020-06-25 12:12:21 -0700 | [diff] [blame] | 213 | modPath, err := module.UnescapePath(enc) |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 214 | if err != nil { |
Colin Cross | 1f80552 | 2021-05-14 11:10:59 -0700 | [diff] [blame] | 215 | if testing.Verbose() { |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 216 | fmt.Fprintf(os.Stderr, "go proxy_test: %v\n", err) |
| 217 | } |
| 218 | http.NotFound(w, r) |
| 219 | return |
| 220 | } |
| 221 | |
| 222 | // Imitate what "latest" does in direct mode and what proxy.golang.org does. |
| 223 | // Use the latest released version. |
| 224 | // If there is no released version, use the latest prereleased version. |
| 225 | // Otherwise, use the latest pseudoversion. |
| 226 | var latestRelease, latestPrerelease, latestPseudo string |
| 227 | for _, m := range modList { |
| 228 | if m.Path != modPath { |
| 229 | continue |
| 230 | } |
Dan Willemsen | cc753b7 | 2021-08-31 13:25:42 -0700 | [diff] [blame] | 231 | if module.IsPseudoVersion(m.Version) && (latestPseudo == "" || semver.Compare(latestPseudo, m.Version) > 0) { |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 232 | latestPseudo = m.Version |
| 233 | } else if semver.Prerelease(m.Version) != "" && (latestPrerelease == "" || semver.Compare(latestPrerelease, m.Version) > 0) { |
| 234 | latestPrerelease = m.Version |
| 235 | } else if latestRelease == "" || semver.Compare(latestRelease, m.Version) > 0 { |
| 236 | latestRelease = m.Version |
| 237 | } |
| 238 | } |
| 239 | var latest string |
| 240 | if latestRelease != "" { |
| 241 | latest = latestRelease |
| 242 | } else if latestPrerelease != "" { |
| 243 | latest = latestPrerelease |
| 244 | } else if latestPseudo != "" { |
| 245 | latest = latestPseudo |
| 246 | } else { |
| 247 | http.NotFound(w, r) |
| 248 | return |
| 249 | } |
| 250 | |
Patrice Arruda | 748609c | 2020-06-25 12:12:21 -0700 | [diff] [blame] | 251 | encVers, err := module.EscapeVersion(latest) |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 252 | if err != nil { |
| 253 | http.Error(w, err.Error(), http.StatusInternalServerError) |
| 254 | return |
| 255 | } |
| 256 | path = fmt.Sprintf("%s/@v/%s.info", enc, encVers) |
| 257 | } |
| 258 | |
| 259 | // Module proxy request: /mod/path/@v/version[.suffix] |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 260 | i := strings.Index(path, "/@v/") |
| 261 | if i < 0 { |
| 262 | http.NotFound(w, r) |
| 263 | return |
| 264 | } |
| 265 | enc, file := path[:i], path[i+len("/@v/"):] |
Patrice Arruda | 748609c | 2020-06-25 12:12:21 -0700 | [diff] [blame] | 266 | path, err := module.UnescapePath(enc) |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 267 | if err != nil { |
Colin Cross | 1f80552 | 2021-05-14 11:10:59 -0700 | [diff] [blame] | 268 | if testing.Verbose() { |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 269 | fmt.Fprintf(os.Stderr, "go proxy_test: %v\n", err) |
| 270 | } |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 271 | http.NotFound(w, r) |
| 272 | return |
| 273 | } |
| 274 | if file == "list" { |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 275 | // list returns a list of versions, not including pseudo-versions. |
| 276 | // If the module has no tagged versions, we should serve an empty 200. |
| 277 | // If the module doesn't exist, we should serve 404 or 410. |
| 278 | found := false |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 279 | for _, m := range modList { |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 280 | if m.Path != path { |
| 281 | continue |
| 282 | } |
| 283 | found = true |
Dan Willemsen | cc753b7 | 2021-08-31 13:25:42 -0700 | [diff] [blame] | 284 | if !module.IsPseudoVersion(m.Version) { |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 285 | if err := module.Check(m.Path, m.Version); err == nil { |
| 286 | fmt.Fprintf(w, "%s\n", m.Version) |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 287 | } |
| 288 | } |
| 289 | } |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 290 | if !found { |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 291 | http.NotFound(w, r) |
| 292 | } |
| 293 | return |
| 294 | } |
| 295 | |
| 296 | i = strings.LastIndex(file, ".") |
| 297 | if i < 0 { |
| 298 | http.NotFound(w, r) |
| 299 | return |
| 300 | } |
| 301 | encVers, ext := file[:i], file[i+1:] |
Patrice Arruda | 748609c | 2020-06-25 12:12:21 -0700 | [diff] [blame] | 302 | vers, err := module.UnescapeVersion(encVers) |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 303 | if err != nil { |
| 304 | fmt.Fprintf(os.Stderr, "go proxy_test: %v\n", err) |
| 305 | http.NotFound(w, r) |
| 306 | return |
| 307 | } |
| 308 | |
| 309 | if codehost.AllHex(vers) { |
| 310 | var best string |
| 311 | // Convert commit hash (only) to known version. |
| 312 | // Use latest version in semver priority, to match similar logic |
| 313 | // in the repo-based module server (see modfetch.(*codeRepo).convert). |
| 314 | for _, m := range modList { |
| 315 | if m.Path == path && semver.Compare(best, m.Version) < 0 { |
| 316 | var hash string |
Dan Willemsen | cc753b7 | 2021-08-31 13:25:42 -0700 | [diff] [blame] | 317 | if module.IsPseudoVersion(m.Version) { |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 318 | hash = m.Version[strings.LastIndex(m.Version, "-")+1:] |
| 319 | } else { |
| 320 | hash = findHash(m) |
| 321 | } |
| 322 | if strings.HasPrefix(hash, vers) || strings.HasPrefix(vers, hash) { |
| 323 | best = m.Version |
| 324 | } |
| 325 | } |
| 326 | } |
| 327 | if best != "" { |
| 328 | vers = best |
| 329 | } |
| 330 | } |
| 331 | |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 332 | a, err := readArchive(path, vers) |
| 333 | if err != nil { |
Colin Cross | 1f80552 | 2021-05-14 11:10:59 -0700 | [diff] [blame] | 334 | if testing.Verbose() { |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 335 | fmt.Fprintf(os.Stderr, "go proxy: no archive %s %s: %v\n", path, vers, err) |
| 336 | } |
Colin Cross | 1f80552 | 2021-05-14 11:10:59 -0700 | [diff] [blame] | 337 | if errors.Is(err, fs.ErrNotExist) { |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 338 | http.NotFound(w, r) |
| 339 | } else { |
| 340 | http.Error(w, "cannot load archive", 500) |
| 341 | } |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 342 | return |
| 343 | } |
| 344 | |
| 345 | switch ext { |
| 346 | case "info", "mod": |
| 347 | want := "." + ext |
| 348 | for _, f := range a.Files { |
| 349 | if f.Name == want { |
| 350 | w.Write(f.Data) |
| 351 | return |
| 352 | } |
| 353 | } |
| 354 | |
| 355 | case "zip": |
| 356 | type cached struct { |
| 357 | zip []byte |
| 358 | err error |
| 359 | } |
Dan Willemsen | bc60c3c | 2021-12-15 01:09:00 -0800 | [diff] [blame] | 360 | c := zipCache.Do(a, func() any { |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 361 | var buf bytes.Buffer |
| 362 | z := zip.NewWriter(&buf) |
| 363 | for _, f := range a.Files { |
Dan Willemsen | cc753b7 | 2021-08-31 13:25:42 -0700 | [diff] [blame] | 364 | if f.Name == ".info" || f.Name == ".mod" || f.Name == ".zip" { |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 365 | continue |
| 366 | } |
Colin Cross | d9c6b80 | 2019-03-19 21:10:31 -0700 | [diff] [blame] | 367 | var zipName string |
| 368 | if strings.HasPrefix(f.Name, "/") { |
| 369 | zipName = f.Name[1:] |
| 370 | } else { |
| 371 | zipName = path + "@" + vers + "/" + f.Name |
| 372 | } |
| 373 | zf, err := z.Create(zipName) |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 374 | if err != nil { |
| 375 | return cached{nil, err} |
| 376 | } |
| 377 | if _, err := zf.Write(f.Data); err != nil { |
| 378 | return cached{nil, err} |
| 379 | } |
| 380 | } |
| 381 | if err := z.Close(); err != nil { |
| 382 | return cached{nil, err} |
| 383 | } |
| 384 | return cached{buf.Bytes(), nil} |
| 385 | }).(cached) |
| 386 | |
| 387 | if c.err != nil { |
Colin Cross | 1f80552 | 2021-05-14 11:10:59 -0700 | [diff] [blame] | 388 | if testing.Verbose() { |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 389 | fmt.Fprintf(os.Stderr, "go proxy: %v\n", c.err) |
| 390 | } |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 391 | http.Error(w, c.err.Error(), 500) |
| 392 | return |
| 393 | } |
| 394 | w.Write(c.zip) |
| 395 | return |
| 396 | |
| 397 | } |
| 398 | http.NotFound(w, r) |
| 399 | } |
| 400 | |
| 401 | func findHash(m module.Version) string { |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 402 | a, err := readArchive(m.Path, m.Version) |
| 403 | if err != nil { |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 404 | return "" |
| 405 | } |
| 406 | var data []byte |
| 407 | for _, f := range a.Files { |
| 408 | if f.Name == ".info" { |
| 409 | data = f.Data |
| 410 | break |
| 411 | } |
| 412 | } |
| 413 | var info struct{ Short string } |
| 414 | json.Unmarshal(data, &info) |
| 415 | return info.Short |
| 416 | } |
| 417 | |
| 418 | var archiveCache par.Cache |
| 419 | |
| 420 | var cmdGoDir, _ = os.Getwd() |
| 421 | |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 422 | func readArchive(path, vers string) (*txtar.Archive, error) { |
Patrice Arruda | 748609c | 2020-06-25 12:12:21 -0700 | [diff] [blame] | 423 | enc, err := module.EscapePath(path) |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 424 | if err != nil { |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 425 | return nil, err |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 426 | } |
Patrice Arruda | 748609c | 2020-06-25 12:12:21 -0700 | [diff] [blame] | 427 | encVers, err := module.EscapeVersion(vers) |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 428 | if err != nil { |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 429 | return nil, err |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 430 | } |
| 431 | |
Colin Cross | d9c6b80 | 2019-03-19 21:10:31 -0700 | [diff] [blame] | 432 | prefix := strings.ReplaceAll(enc, "/", "_") |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 433 | name := filepath.Join(cmdGoDir, "testdata/mod", prefix+"_"+encVers+".txt") |
Dan Willemsen | bc60c3c | 2021-12-15 01:09:00 -0800 | [diff] [blame] | 434 | a := archiveCache.Do(name, func() any { |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 435 | a, err := txtar.ParseFile(name) |
| 436 | if err != nil { |
| 437 | if testing.Verbose() || !os.IsNotExist(err) { |
| 438 | fmt.Fprintf(os.Stderr, "go proxy: %v\n", err) |
| 439 | } |
| 440 | a = nil |
| 441 | } |
| 442 | return a |
| 443 | }).(*txtar.Archive) |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 444 | if a == nil { |
Colin Cross | 1f80552 | 2021-05-14 11:10:59 -0700 | [diff] [blame] | 445 | return nil, fs.ErrNotExist |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 446 | } |
| 447 | return a, nil |
| 448 | } |
| 449 | |
| 450 | // proxyGoSum returns the two go.sum lines for path@vers. |
| 451 | func proxyGoSum(path, vers string) ([]byte, error) { |
| 452 | a, err := readArchive(path, vers) |
| 453 | if err != nil { |
| 454 | return nil, err |
| 455 | } |
| 456 | var names []string |
| 457 | files := make(map[string][]byte) |
| 458 | var gomod []byte |
| 459 | for _, f := range a.Files { |
| 460 | if strings.HasPrefix(f.Name, ".") { |
| 461 | if f.Name == ".mod" { |
| 462 | gomod = f.Data |
| 463 | } |
| 464 | continue |
| 465 | } |
| 466 | name := path + "@" + vers + "/" + f.Name |
| 467 | names = append(names, name) |
| 468 | files[name] = f.Data |
| 469 | } |
| 470 | h1, err := dirhash.Hash1(names, func(name string) (io.ReadCloser, error) { |
| 471 | data := files[name] |
Colin Cross | 1f80552 | 2021-05-14 11:10:59 -0700 | [diff] [blame] | 472 | return io.NopCloser(bytes.NewReader(data)), nil |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 473 | }) |
| 474 | if err != nil { |
| 475 | return nil, err |
| 476 | } |
| 477 | h1mod, err := dirhash.Hash1([]string{"go.mod"}, func(string) (io.ReadCloser, error) { |
Colin Cross | 1f80552 | 2021-05-14 11:10:59 -0700 | [diff] [blame] | 478 | return io.NopCloser(bytes.NewReader(gomod)), nil |
Colin Cross | 430342c | 2019-09-07 08:36:04 -0700 | [diff] [blame] | 479 | }) |
| 480 | if err != nil { |
| 481 | return nil, err |
| 482 | } |
| 483 | data := []byte(fmt.Sprintf("%s %s %s\n%s %s/go.mod %s\n", path, vers, h1, path, vers, h1mod)) |
| 484 | return data, nil |
| 485 | } |
| 486 | |
| 487 | // proxyGoSumWrong returns the wrong lines. |
| 488 | func proxyGoSumWrong(path, vers string) ([]byte, error) { |
| 489 | data := []byte(fmt.Sprintf("%s %s %s\n%s %s/go.mod %s\n", path, vers, "h1:wrong", path, vers, "h1:wrong")) |
| 490 | return data, nil |
Dan Willemsen | c741332 | 2018-08-27 23:21:26 -0700 | [diff] [blame] | 491 | } |