Files
athens/pkg/middleware/filter.go
Chad Kunde 7811524c22 Version filtering (#1050)
* 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.
2019-02-05 09:04:09 +01:00

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
}