mirror of
https://github.com/gomods/athens
synced 2026-02-03 14:20:31 +00:00
* extend filtering logic and configuration to include version lists Module filtering is very useful, but many deployments will need to satisfy even more granular constrainsts. Enterprises may need approved lists specific down to the minor (or patch) version element. Version filtering logic is similar to the module filtering, in that it's a prefix match of the version requested against each entry in the version filter list. Closes #1045 * include version filtering in documentation with example * allow filtering when version is missing Endpoints that do not specify a version, such as "@v/list", only need to be filtered by module rules.
55 lines
1.5 KiB
Go
55 lines
1.5 KiB
Go
package middleware
|
|
|
|
import (
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"github.com/gomods/athens/pkg/errors"
|
|
"github.com/gomods/athens/pkg/module"
|
|
"github.com/gomods/athens/pkg/paths"
|
|
"github.com/gorilla/mux"
|
|
)
|
|
|
|
// NewFilterMiddleware builds a middleware function that implements the
|
|
// filters configured in the filter file.
|
|
func NewFilterMiddleware(mf *module.Filter, upstreamEndpoint string) mux.MiddlewareFunc {
|
|
const op errors.Op = "actions.NewFilterMiddleware"
|
|
return func(h http.Handler) http.Handler {
|
|
f := func(w http.ResponseWriter, r *http.Request) {
|
|
mod, err := paths.GetModule(r)
|
|
if err != nil {
|
|
// if there is no module the path we are hitting is not one related to modules, like /
|
|
h.ServeHTTP(w, r)
|
|
return
|
|
}
|
|
ver, err := paths.GetVersion(r)
|
|
if err != nil {
|
|
ver = ""
|
|
}
|
|
rule := mf.Rule(mod, ver)
|
|
switch rule {
|
|
case module.Exclude:
|
|
// Exclude: ignore request for this module
|
|
w.WriteHeader(http.StatusForbidden)
|
|
return
|
|
case module.Include:
|
|
// Include: please handle this module in a usual way
|
|
h.ServeHTTP(w, r)
|
|
return
|
|
case module.Direct:
|
|
// Direct: do not store modules locally, use upstream proxy
|
|
newURL := redirectToUpstreamURL(upstreamEndpoint, r.URL)
|
|
http.Redirect(w, r, newURL, http.StatusSeeOther)
|
|
return
|
|
}
|
|
h.ServeHTTP(w, r)
|
|
}
|
|
return http.HandlerFunc(f)
|
|
}
|
|
}
|
|
|
|
func redirectToUpstreamURL(upstreamEndpoint string, u *url.URL) string {
|
|
return strings.TrimSuffix(upstreamEndpoint, "/") + u.Path
|
|
}
|