3dfecd99eaebd9549bb6bc0214d4348f6ed24adc

Author
Ayman Bagabas <ayman.bagabas@gmail.com>
Committer
Ayman Bagabas <ayman.bagabas@gmail.com>
Date

Message

fix(http): go-get requests

should always return 200

Diff

 1diff --git a/server/http.go b/server/http.go
 2index 1074a31a97b9f1d4ca72b6ae3947ec96e6b0e42a..60a8650c76adc523fd0963eb74f675f308ee8c24 100644
 3--- a/server/http.go
 4+++ b/server/http.go
 5@@ -5,6 +5,7 @@ import (
 6 	"fmt"
 7 	"net/http"
 8 	"net/url"
 9+	"path"
10 	"path/filepath"
11 	"regexp"
12 	"strings"
13@@ -248,43 +249,52 @@ Redirecting to docs at <a href="https://godoc.org/{{ .ImportRoot }}/{{ .Repo }}"
14 func (s *HTTPServer) handleIndex(w http.ResponseWriter, r *http.Request) {
15 	repo := pattern.Path(r.Context())
16 	repo = utils.SanitizeRepo(repo)
17-	if _, err := s.cfg.Backend.Repository(repo); err != nil {
18-		http.NotFound(w, r)
19-		return
20-	}
21-
22-	// Only respond to go-get requests
23-	if r.URL.Query().Get("go-get") != "1" {
24-		http.NotFound(w, r)
25-		return
26-	}
27-
28-	access := s.cfg.Backend.AccessLevel(repo, "")
29-	if access < backend.ReadOnlyAccess {
30-		http.NotFound(w, r)
31-		return
32-	}
33-
34-	importRoot, err := url.Parse(s.cfg.HTTP.PublicURL)
35-	if err != nil {
36-		http.Error(w, err.Error(), http.StatusInternalServerError)
37-		return
38-	}
39 
40-	if err := repoIndexHTMLTpl.Execute(w, struct {
41-		Repo       string
42-		Config     *config.Config
43-		ImportRoot string
44-	}{
45-		Repo:       repo,
46-		Config:     s.cfg,
47-		ImportRoot: importRoot.Host,
48-	}); err != nil {
49-		http.Error(w, err.Error(), http.StatusInternalServerError)
50+	// Handle go get requests.
51+	//
52+	// Always return a 200 status code, even if the repo doesn't exist.
53+	//
54+	// https://golang.org/cmd/go/#hdr-Remote_import_paths
55+	// https://go.dev/ref/mod#vcs-branch
56+	if r.URL.Query().Get("go-get") == "1" {
57+		repo := repo
58+		importRoot, err := url.Parse(s.cfg.HTTP.PublicURL)
59+		if err != nil {
60+			http.Error(w, err.Error(), http.StatusInternalServerError)
61+			return
62+		}
63+
64+		// find the repo
65+		for {
66+			if _, err := s.cfg.Backend.Repository(repo); err == nil {
67+				break
68+			}
69+
70+			if repo == "" || repo == "." || repo == "/" {
71+				return
72+			}
73+
74+			repo = path.Dir(repo)
75+		}
76+
77+		if err := repoIndexHTMLTpl.Execute(w, struct {
78+			Repo       string
79+			Config     *config.Config
80+			ImportRoot string
81+		}{
82+			Repo:       url.PathEscape(repo),
83+			Config:     s.cfg,
84+			ImportRoot: importRoot.Host,
85+		}); err != nil {
86+			http.Error(w, err.Error(), http.StatusInternalServerError)
87+			return
88+		}
89+
90+		goGetCounter.WithLabelValues(repo).Inc()
91 		return
92 	}
93 
94-	goGetCounter.WithLabelValues(repo).Inc()
95+	http.NotFound(w, r)
96 }
97 
98 func (s *HTTPServer) handleGit(w http.ResponseWriter, r *http.Request) {