MCPcopy
hub / github.com/harness/harness / Middleware

Function Middleware

app/api/middleware/goget/goget.go:61–158  ·  view source on GitHub ↗

Middleware writes to response with html meta tags go-import and go-source. nolint:gocognit

(
	maxRepoPathDepth int,
	repoCtrl *repo.Controller,
	urlProvider url.Provider,
)

Source from the content-addressed store, hash-verified

59//
60//nolint:gocognit
61func Middleware(
62 maxRepoPathDepth int,
63 repoCtrl *repo.Controller,
64 urlProvider url.Provider,
65) func(http.Handler) http.Handler {
66 return func(next http.Handler) http.Handler {
67 return http.HandlerFunc(
68 func(w http.ResponseWriter, r *http.Request) {
69 if r.Method != http.MethodGet || r.URL.Query().Get("go-get") != "1" {
70 next.ServeHTTP(w, r)
71 return
72 }
73 ctx := r.Context()
74
75 session, _ := request.AuthSessionFrom(ctx)
76 importPath, err := request.GetRepoRefFromPath(r)
77 if err != nil {
78 render.TranslatedUserError(ctx, w, err)
79 return
80 }
81
82 // go get can also be used with (sub)module suffixes (e.g 127.0.0.1/my-project/my-repo/v2)
83 // for which go expects us to return the import path corresponding to the repository root
84 // (e.g. 127.0.0.1/my-project/my-repo).
85 //
86 // WARNING: This can lead to ambiguities as we allow matching paths between spaces and repos:
87 // 1. (space)foo + (repo)bar + (sufix)v2 = 127.0.0.1/my-project/my-repo/v2
88 // 2. (space)foo/bar + (repo)v2 = 127.0.0.1/my-project/my-repo/v2
89 //
90 // We handle ambiguities by always choosing the repo with the longest path (e.g. 2. case above).
91 // To solve go get related ambiguities users would have to move their repositories.
92 var repository *repo.RepositoryOutput
93 var repoRef string
94
95 pathSegments := paths.Segments(importPath)
96 if len(pathSegments) > maxRepoPathDepth {
97 pathSegments = pathSegments[:maxRepoPathDepth]
98 }
99
100 for l := len(pathSegments); l >= 2; l-- {
101 repoRef = paths.Concatenate(pathSegments[:l]...)
102
103 repository, err = repoCtrl.Find(ctx, session, repoRef)
104 if err == nil {
105 break
106 }
107 if errors.Is(err, store.ErrResourceNotFound) {
108 log.Ctx(ctx).Debug().Err(err).
109 Msgf("repository %q doesn't exist, assume submodule and try again", repoRef)
110 continue
111 }
112 if errors.Is(err, auth.ErrForbidden) {
113 // To avoid leaking information about repos' existence we continue as if it wasn't found.
114 // WARNING: This can lead to different import results depending on access (very unlikely)
115 log.Ctx(ctx).Debug().Err(err).
116 Msgf("user has no access on repository %q, assume submodule and try again", repoRef)
117 continue
118 }

Callers 1

NewGitHandlerFunction · 0.92

Calls 15

AuthSessionFromFunction · 0.92
GetRepoRefFromPathFunction · 0.92
TranslatedUserErrorFunction · 0.92
SegmentsFunction · 0.92
ConcatenateFunction · 0.92
NotFoundFunction · 0.92
ServeHTTPMethod · 0.80
MsgfMethod · 0.80
GetMethod · 0.65
FindMethod · 0.65
ErrMethod · 0.65
DebugMethod · 0.65

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…