diff options
author | feistel <6742251-feistel@users.noreply.gitlab.com> | 2022-05-22 17:02:51 +0300 |
---|---|---|
committer | feistel <6742251-feistel@users.noreply.gitlab.com> | 2022-05-22 17:02:51 +0300 |
commit | f8d62fd4de797a64734f08f09f57bd2271b740c7 (patch) | |
tree | 83bea64ba87773f9299ff1057ee911f70862e52c | |
parent | a80c58682c3c313f52deecdebecfef2d1f7e3b21 (diff) |
Reduce lookup path requests in the handler pipeline
-rw-r--r-- | app.go | 59 | ||||
-rw-r--r-- | internal/auth/middleware.go | 47 |
2 files changed, 46 insertions, 60 deletions
@@ -87,68 +87,10 @@ func (a *theApp) getTLSConfig() (*cryptotls.Config, error) { return a.tlsConfig, err } -func (a *theApp) redirectToHTTPS(w http.ResponseWriter, r *http.Request, statusCode int) { - u := *r.URL - u.Scheme = request.SchemeHTTPS - u.Host = r.Host - u.User = nil - - http.Redirect(w, r, u.String(), statusCode) -} - func (a *theApp) domain(ctx context.Context, host string) (*domain.Domain, error) { return a.source.GetDomain(ctx, host) } -// checkAuthAndServeNotFound performs the auth process if domain can't be found -// the main purpose of this process is to avoid leaking the project existence/not-existence -// by behaving the same if user has no access to the project or if project simply does not exists -func (a *theApp) checkAuthAndServeNotFound(domain *domain.Domain, w http.ResponseWriter, r *http.Request) { - // To avoid user knowing if pages exist, we will force user to login and authorize pages - if a.Auth.CheckAuthenticationWithoutProject(w, r, domain) { - return - } - - // auth succeeded try to serve the correct 404 page - domain.ServeNotFoundAuthFailed(w, r) -} - -func (a *theApp) tryAuxiliaryHandlers(w http.ResponseWriter, r *http.Request, https bool, domain *domain.Domain) bool { - if _, err := domain.GetLookupPath(r); err != nil { - if errors.Is(err, gitlab.ErrDiskDisabled) { - errortracking.CaptureErrWithReqAndStackTrace(err, r) - httperrors.Serve500(w) - return true - } - - // redirect to auth and serve not found - a.checkAuthAndServeNotFound(domain, w, r) - return true - } - - if !https && domain.IsHTTPSOnly(r) { - a.redirectToHTTPS(w, r, http.StatusMovedPermanently) - return true - } - - return false -} - -// auxiliaryMiddleware will handle status updates, not-ready requests and other -// not static-content responses -func (a *theApp) auxiliaryMiddleware(handler http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - domain := domain.FromRequest(r) - https := request.IsHTTPS(r) - - if a.tryAuxiliaryHandlers(w, r, https, domain) { - return - } - - handler.ServeHTTP(w, r) - }) -} - // serveFileOrNotFoundHandler will serve static content or // return a 404 Not Found response func (a *theApp) serveFileOrNotFoundHandler() http.Handler { @@ -202,7 +144,6 @@ func (a *theApp) buildHandlerPipeline() (http.Handler, error) { handler = corsHandler.Handler(handler) } handler = a.Auth.AuthorizationMiddleware(handler) - handler = a.auxiliaryMiddleware(handler) handler = handlers.ArtifactMiddleware(handler, a.Handlers) handler = a.Auth.AuthenticationMiddleware(handler, a.source) handler = a.AcmeMiddleware.AcmeMiddleware(handler) diff --git a/internal/auth/middleware.go b/internal/auth/middleware.go index 23ea0cf3..f9800b95 100644 --- a/internal/auth/middleware.go +++ b/internal/auth/middleware.go @@ -1,10 +1,15 @@ package auth import ( + "errors" "net/http" domainCfg "gitlab.com/gitlab-org/gitlab-pages/internal/domain" + "gitlab.com/gitlab-org/gitlab-pages/internal/errortracking" + "gitlab.com/gitlab-org/gitlab-pages/internal/httperrors" + "gitlab.com/gitlab-org/gitlab-pages/internal/request" "gitlab.com/gitlab-org/gitlab-pages/internal/source" + "gitlab.com/gitlab-org/gitlab-pages/internal/source/gitlab" ) // AuthenticationMiddleware handles authentication requests @@ -22,9 +27,27 @@ func (a *Auth) AuthenticationMiddleware(handler http.Handler, s source.Source) h func (a *Auth) AuthorizationMiddleware(handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { domain := domainCfg.FromRequest(r) + lp, err := domain.GetLookupPath(r) + + if err != nil { + if errors.Is(err, gitlab.ErrDiskDisabled) { + errortracking.CaptureErrWithReqAndStackTrace(err, r) + httperrors.Serve500(w) + return + } + + // redirect to auth and serve not found + a.checkAuthAndServeNotFound(domain, w, r) + return + } + + if lp.IsHTTPSOnly && !request.IsHTTPS(r) { + redirectToHTTPS(w, r, http.StatusMovedPermanently) + return + } // Only for projects that have access control enabled - if domain.IsAccessControlEnabled(r) { + if lp.HasAccessControl { // accessControlMiddleware if a.CheckAuthentication(w, r, domain) { return @@ -34,3 +57,25 @@ func (a *Auth) AuthorizationMiddleware(handler http.Handler) http.Handler { handler.ServeHTTP(w, r) }) } + +// checkAuthAndServeNotFound performs the auth process if domain can't be found +// the main purpose of this process is to avoid leaking the project existence/not-existence +// by behaving the same if user has no access to the project or if project simply does not exists +func (a *Auth) checkAuthAndServeNotFound(domain *domainCfg.Domain, w http.ResponseWriter, r *http.Request) { + // To avoid user knowing if pages exist, we will force user to login and authorize pages + if a.CheckAuthenticationWithoutProject(w, r, domain) { + return + } + + // auth succeeded try to serve the correct 404 page + domain.ServeNotFoundAuthFailed(w, r) +} + +func redirectToHTTPS(w http.ResponseWriter, r *http.Request, statusCode int) { + u := *r.URL + u.Scheme = request.SchemeHTTPS + u.Host = r.Host + u.User = nil + + http.Redirect(w, r, u.String(), statusCode) +} |