diff options
author | Jaime Martinez <jmartinez@gitlab.com> | 2022-06-02 05:20:46 +0300 |
---|---|---|
committer | Jaime Martinez <jmartinez@gitlab.com> | 2022-06-02 05:20:46 +0300 |
commit | 2fe03721dbc6abb0240a284186a4bc4f4545d008 (patch) | |
tree | 511ff062ab0d3a9ff4b6e9bde4ac90d450eb6eec | |
parent | 93566c8f6f83fb7877b61ae9142995e3a1703152 (diff) | |
parent | 08430ea180dda0e766a34b64de016649fb9c4549 (diff) |
Merge branch 'perf/reduce-lookup-path' into 'master'
refactor: reduce lookup path requests
See merge request gitlab-org/gitlab-pages!753
-rw-r--r-- | app.go | 59 | ||||
-rw-r--r-- | internal/auth/middleware.go | 49 |
2 files changed, 48 insertions, 60 deletions
@@ -86,68 +86,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 { @@ -201,7 +143,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..6894d8d0 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 @@ -23,8 +28,28 @@ 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 + } + + // This is not auth related but there's no point in having + // an extra middleware just for this. + 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 +59,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) +} |