diff options
author | Kamil Trzciński <ayufan@ayufan.eu> | 2019-10-01 12:53:16 +0300 |
---|---|---|
committer | Kamil Trzciński <ayufan@ayufan.eu> | 2019-10-01 12:53:16 +0300 |
commit | b37ed1c0ff9880fb73ed2ed771c100333d79f3c5 (patch) | |
tree | e7e60fab0101acbda400e9cd98cf843cecc49236 | |
parent | 9660a822ed42dd28fa1d7e878a1a7f05c2b351b5 (diff) |
Refactor the code to use `Serving/LookupPath`
This moves the code from the concept
of `Project` to use a concept of `LookupPath`.
This makes the `LookupPath` to define a `Path` on disk that
the data is being served from.
This makes the `ACME` to not have special
handling, but rather try to serve the file
if succeeds, skip GitLab passthrough
for ACME.
-rw-r--r-- | internal/acme/acme.go | 4 | ||||
-rw-r--r-- | internal/acme/acme_test.go | 8 | ||||
-rw-r--r-- | internal/domain/domain.go | 41 | ||||
-rw-r--r-- | internal/domain/domain_test.go | 38 | ||||
-rw-r--r-- | internal/domain/handler.go | 42 | ||||
-rw-r--r-- | internal/domain/resolver.go | 8 | ||||
-rw-r--r-- | internal/serving/disk.go | 19 | ||||
-rw-r--r-- | internal/serving/disk/handler.go | 11 | ||||
-rw-r--r-- | internal/serving/disk/reader.go | 27 | ||||
-rw-r--r-- | internal/serving/disk/serving.go | 28 | ||||
-rw-r--r-- | internal/serving/handler.go | 20 | ||||
-rw-r--r-- | internal/serving/lookup_path.go (renamed from internal/domain/project.go) | 7 | ||||
-rw-r--r-- | internal/serving/serving.go | 16 | ||||
-rw-r--r-- | internal/source/disk/custom.go | 11 | ||||
-rw-r--r-- | internal/source/disk/domain_test.go | 36 | ||||
-rw-r--r-- | internal/source/disk/group.go | 21 | ||||
-rw-r--r-- | internal/source/disk/map.go | 22 |
17 files changed, 126 insertions, 233 deletions
diff --git a/internal/acme/acme.go b/internal/acme/acme.go index a6be01de..3bfa8f2e 100644 --- a/internal/acme/acme.go +++ b/internal/acme/acme.go @@ -18,7 +18,7 @@ type Middleware struct { // Domain interface represent D from domain package type Domain interface { - HasAcmeChallenge(*http.Request, string) bool + ServeFileHTTP(w http.ResponseWriter, r *http.Request) bool } // ServeAcmeChallenges identifies if request is acme-challenge and redirects to GitLab in that case @@ -31,7 +31,7 @@ func (m *Middleware) ServeAcmeChallenges(w http.ResponseWriter, r *http.Request, return false } - if domain.HasAcmeChallenge(r, filepath.Base(r.URL.Path)) { + if domain.ServeFileHTTP(w, r) { return false } diff --git a/internal/acme/acme_test.go b/internal/acme/acme_test.go index 00932d3e..ab191694 100644 --- a/internal/acme/acme_test.go +++ b/internal/acme/acme_test.go @@ -11,8 +11,12 @@ type domainStub struct { hasAcmeChallenge bool } -func (d *domainStub) HasAcmeChallenge(_ *http.Request, _ string) bool { - return d.hasAcmeChallenge +func (d *domainStub) ServeFileHTTP(w http.ResponseWriter, r *http.Request) bool { + if r.URL.Path == "/.well-known/acme-challenge/token" { + return d.hasAcmeChallenge + } + + return false } func serveAcmeOrNotFound(m *Middleware, domain Domain) http.HandlerFunc { diff --git a/internal/domain/domain.go b/internal/domain/domain.go index df484dd2..2941d174 100644 --- a/internal/domain/domain.go +++ b/internal/domain/domain.go @@ -8,19 +8,18 @@ import ( "gitlab.com/gitlab-org/gitlab-pages/internal/httperrors" "gitlab.com/gitlab-org/gitlab-pages/internal/serving" + "gitlab.com/gitlab-org/gitlab-pages/internal/serving/disk" ) // Domain is a domain that gitlab-pages can serve. type Domain struct { Name string - Location string CertificateCert string CertificateKey string Resolver Resolver - lookupPaths map[string]*Project - serving serving.Serving + serving serving.Serving certificate *tls.Certificate certificateError error @@ -40,7 +39,7 @@ func (d *Domain) isUnconfigured() bool { return d.Resolver == nil } -func (d *Domain) resolve(r *http.Request) (*Project, string) { +func (d *Domain) resolve(r *http.Request) (*serving.LookupPath, string) { // TODO use lookupPaths to cache information about projects better, to // improve performance and resilience @@ -55,7 +54,7 @@ func (d *Domain) resolve(r *http.Request) (*Project, string) { } // GetProject returns a project details based on the request -func (d *Domain) GetProject(r *http.Request) *Project { +func (d *Domain) GetProject(r *http.Request) *serving.LookupPath { project, _ := d.resolve(r) return project @@ -64,20 +63,20 @@ func (d *Domain) GetProject(r *http.Request) *Project { // Serving returns domain serving driver func (d *Domain) Serving() serving.Serving { if d.serving == nil { - d.serving = serving.NewDiskServing(d.Name, d.Location) + d.serving = disk.New() } return d.serving } -func (d *Domain) toHandler(w http.ResponseWriter, r *http.Request) *handler { +func (d *Domain) toHandler(w http.ResponseWriter, r *http.Request) serving.Handler { project, subpath := d.resolve(r) - return &handler{ - writer: w, - request: r, - project: project, - subpath: subpath, + return serving.Handler{ + Writer: w, + Request: r, + LookupPath: project, + SubPath: subpath, } } @@ -108,20 +107,6 @@ func (d *Domain) IsAccessControlEnabled(r *http.Request) bool { return false } -// HasAcmeChallenge checks domain directory contains particular acme challenge -func (d *Domain) HasAcmeChallenge(r *http.Request, token string) bool { - // TODO is that safe to redirect to acme challenge in GitLab if it is a grup domain? - if d.isUnconfigured() || !d.HasProject(r) { - return false - } - - // TODO we should improve that, we need different type of information to - // check if the ACME challenge is present in the serving. We should devise a - // better interface here or we should to extract this responsibility - // somewhere else. - return d.Serving().HasAcmeChallenge(d.toHandler(nil, r), token) -} - // IsNamespaceProject figures out if the request is to a namespace project func (d *Domain) IsNamespaceProject(r *http.Request) bool { if d.isUnconfigured() { @@ -180,6 +165,10 @@ func (d *Domain) EnsureCertificate() (*tls.Certificate, error) { // ServeFileHTTP returns true if something was served, false if not. func (d *Domain) ServeFileHTTP(w http.ResponseWriter, r *http.Request) bool { if d.isUnconfigured() || !d.HasProject(r) { + // TODO: this seems to be wrong: + // as we should rather return false, + // and fallback to `ServeNotFoundHTTP` + // to handle this case httperrors.Serve404(w) return true } diff --git a/internal/domain/domain_test.go b/internal/domain/domain_test.go index 8b369075..a43d3c9a 100644 --- a/internal/domain/domain_test.go +++ b/internal/domain/domain_test.go @@ -11,16 +11,17 @@ import ( "github.com/stretchr/testify/require" + "gitlab.com/gitlab-org/gitlab-pages/internal/serving" "gitlab.com/gitlab-org/gitlab-pages/internal/testhelpers" ) type stubbedResolver struct { - project *Project + project *serving.LookupPath subpath string err error } -func (resolver *stubbedResolver) Resolve(*http.Request) (*Project, string, error) { +func (resolver *stubbedResolver) Resolve(*http.Request) (*serving.LookupPath, string, error) { return resolver.project, resolver.subpath, resolver.err } @@ -42,8 +43,12 @@ func TestIsHTTPSOnly(t *testing.T) { { name: "Custom domain with HTTPS-only enabled", domain: &Domain{ - Location: "group/project", - Resolver: &stubbedResolver{project: &Project{IsHTTPSOnly: true}}, + Resolver: &stubbedResolver{ + project: &serving.LookupPath{ + Path: "group/project/public", + IsHTTPSOnly: true, + }, + }, }, url: "http://custom-domain", expected: true, @@ -51,17 +56,19 @@ func TestIsHTTPSOnly(t *testing.T) { { name: "Custom domain with HTTPS-only disabled", domain: &Domain{ - Location: "group/project", - Resolver: &stubbedResolver{project: &Project{IsHTTPSOnly: false}}, + Resolver: &stubbedResolver{ + project: &serving.LookupPath{ + Path: "group/project/public", + IsHTTPSOnly: false, + }, + }, }, url: "http://custom-domain", expected: false, }, { - name: "Unknown project", - domain: &Domain{ - Location: "group/project", - }, + name: "Unknown project", + domain: &Domain{}, url: "http://test-domain/project", expected: false, }, @@ -106,17 +113,13 @@ func TestPredefined404ServeHTTP(t *testing.T) { cleanup := setUpTests(t) defer cleanup() - testDomain := &Domain{ - Location: "group", - } + testDomain := &Domain{} testhelpers.AssertHTTP404(t, serveFileOrNotFound(testDomain), "GET", "http://group.test.io/not-existing-file", nil, "The page you're looking for could not be found") } func TestGroupCertificate(t *testing.T) { - testGroup := &Domain{ - Location: "group", - } + testGroup := &Domain{} tls, err := testGroup.EnsureCertificate() require.Nil(t, tls) @@ -125,8 +128,7 @@ func TestGroupCertificate(t *testing.T) { func TestDomainNoCertificate(t *testing.T) { testDomain := &Domain{ - Name: "test.domain.com", - Location: "group/project2", + Name: "test.domain.com", } tls, err := testDomain.EnsureCertificate() diff --git a/internal/domain/handler.go b/internal/domain/handler.go deleted file mode 100644 index 55697700..00000000 --- a/internal/domain/handler.go +++ /dev/null @@ -1,42 +0,0 @@ -package domain - -import "net/http" - -type handler struct { - writer http.ResponseWriter - request *http.Request - project *Project - subpath string -} - -func (h *handler) Writer() http.ResponseWriter { - return h.writer -} - -func (h *handler) Request() *http.Request { - return h.request -} - -func (h *handler) LookupPath() string { - return h.project.LookupPath -} - -func (h *handler) Subpath() string { - return h.subpath -} - -func (h *handler) IsNamespaceProject() bool { - return h.project.IsNamespaceProject -} - -func (h *handler) IsHTTPSOnly() bool { - return h.project.IsHTTPSOnly -} - -func (h *handler) HasAccessControl() bool { - return h.project.HasAccessControl -} - -func (h *handler) ProjectID() uint64 { - return h.project.ID -} diff --git a/internal/domain/resolver.go b/internal/domain/resolver.go index 5bde31ec..0de66ad5 100644 --- a/internal/domain/resolver.go +++ b/internal/domain/resolver.go @@ -1,10 +1,14 @@ package domain -import "net/http" +import ( + "net/http" + + "gitlab.com/gitlab-org/gitlab-pages/internal/serving" +) // Resolver represents an interface responsible for resolving a project // per-request type Resolver interface { // Resolve returns a project with a file path and an error if it occured - Resolve(*http.Request) (*Project, string, error) + Resolve(*http.Request) (*serving.LookupPath, string, error) } diff --git a/internal/serving/disk.go b/internal/serving/disk.go deleted file mode 100644 index b569986f..00000000 --- a/internal/serving/disk.go +++ /dev/null @@ -1,19 +0,0 @@ -package serving - -import "gitlab.com/gitlab-org/gitlab-pages/internal/serving/disk" - -type diskServing struct { - disk *disk.Serving -} - -func (d *diskServing) ServeFileHTTP(h Handler) bool { - return d.disk.ServeFileHTTP(h) -} - -func (d *diskServing) ServeNotFoundHTTP(h Handler) { - d.disk.ServeNotFoundHTTP(h) -} - -func (d *diskServing) HasAcmeChallenge(h Handler, token string) bool { - return d.disk.HasAcmeChallenge(h, token) -} diff --git a/internal/serving/disk/handler.go b/internal/serving/disk/handler.go deleted file mode 100644 index fbbf9ce3..00000000 --- a/internal/serving/disk/handler.go +++ /dev/null @@ -1,11 +0,0 @@ -package disk - -import "net/http" - -type handler interface { - Writer() http.ResponseWriter - Request() *http.Request - LookupPath() string - Subpath() string - HasAccessControl() bool -} diff --git a/internal/serving/disk/reader.go b/internal/serving/disk/reader.go index 1fc30da7..b52b5cff 100644 --- a/internal/serving/disk/reader.go +++ b/internal/serving/disk/reader.go @@ -9,23 +9,24 @@ import ( "strconv" "strings" "time" + + "gitlab.com/gitlab-org/gitlab-pages/internal/serving" ) // Reader is a disk access driver type Reader struct { - Location string } -func (reader *Reader) tryFile(h handler) error { - fullPath, err := reader.resolvePath(h.LookupPath(), h.Subpath()) +func (reader *Reader) tryFile(h serving.Handler) error { + fullPath, err := reader.resolvePath(h.LookupPath.Path, h.SubPath) - request := h.Request() + request := h.Request host := request.Host urlPath := request.URL.Path if locationError, _ := err.(*locationDirectoryError); locationError != nil { if endsWithSlash(urlPath) { - fullPath, err = reader.resolvePath(h.LookupPath(), h.Subpath(), "index.html") + fullPath, err = reader.resolvePath(h.LookupPath.Path, h.SubPath, "index.html") } else { // Concat Host with URL.Path redirectPath := "//" + host + "/" @@ -33,29 +34,29 @@ func (reader *Reader) tryFile(h handler) error { // Ensure that there's always "/" at end redirectPath = strings.TrimSuffix(redirectPath, "/") + "/" - http.Redirect(h.Writer(), h.Request(), redirectPath, 302) + http.Redirect(h.Writer, h.Request, redirectPath, 302) return nil } } if locationError, _ := err.(*locationFileNoExtensionError); locationError != nil { - fullPath, err = reader.resolvePath(h.LookupPath(), strings.TrimSuffix(h.Subpath(), "/")+".html") + fullPath, err = reader.resolvePath(h.LookupPath.Path, strings.TrimSuffix(h.SubPath, "/")+".html") } if err != nil { return err } - return reader.serveFile(h.Writer(), h.Request(), fullPath, h.HasAccessControl()) + return reader.serveFile(h.Writer, h.Request, fullPath, h.LookupPath.HasAccessControl) } -func (reader *Reader) tryNotFound(h handler) error { - page404, err := reader.resolvePath(h.LookupPath(), "404.html") +func (reader *Reader) tryNotFound(h serving.Handler) error { + page404, err := reader.resolvePath(h.LookupPath.Path, "404.html") if err != nil { return err } - err = reader.serveCustomFile(h.Writer(), h.Request(), http.StatusNotFound, page404) + err = reader.serveCustomFile(h.Writer, h.Request, http.StatusNotFound, page404) if err != nil { return err } @@ -64,9 +65,7 @@ func (reader *Reader) tryNotFound(h handler) error { // Resolve the HTTP request to a path on disk, converting requests for // directories to requests for index.html inside the directory if appropriate. -func (reader *Reader) resolvePath(lookupPath string, subPath ...string) (string, error) { - publicPath := filepath.Join(reader.Location, lookupPath, "public") - +func (reader *Reader) resolvePath(publicPath string, subPath ...string) (string, error) { // Don't use filepath.Join as cleans the path, // where we want to traverse full path as supplied by user // (including ..) diff --git a/internal/serving/disk/serving.go b/internal/serving/disk/serving.go index 78b1b572..db184d3c 100644 --- a/internal/serving/disk/serving.go +++ b/internal/serving/disk/serving.go @@ -2,17 +2,17 @@ package disk import ( "gitlab.com/gitlab-org/gitlab-pages/internal/httperrors" + "gitlab.com/gitlab-org/gitlab-pages/internal/serving" ) // Serving describes a disk access serving type Serving struct { - Domain string // TODO it is not used but might be handy - *Reader + Reader } // ServeFileHTTP serves a file from disk and returns true. It returns false // when a file could not been found. -func (s *Serving) ServeFileHTTP(h handler) bool { +func (s *Serving) ServeFileHTTP(h serving.Handler) bool { if s.tryFile(h) == nil { return true } @@ -21,27 +21,17 @@ func (s *Serving) ServeFileHTTP(h handler) bool { } // ServeNotFoundHTTP tries to read a custom 404 page -func (s *Serving) ServeNotFoundHTTP(h handler) { +func (s *Serving) ServeNotFoundHTTP(h serving.Handler) { if s.tryNotFound(h) == nil { return } // Generic 404 - httperrors.Serve404(h.Writer()) + httperrors.Serve404(h.Writer) } -// HasAcmeChallenge checks if the ACME challenge is present on the disk -func (s *Serving) HasAcmeChallenge(h handler, token string) bool { - _, err := s.resolvePath(h.LookupPath(), ".well-known/acme-challenge", token) - // there is an acme challenge on disk - if err == nil { - return true - } - - _, err = s.resolvePath(h.LookupPath(), ".well-known/acme-challenge", token, "index.html") - if err == nil { - return true - } - - return false +// New returns a serving instance that is capable of reading files +// from the disk +func New() serving.Serving { + return &Serving{} } diff --git a/internal/serving/handler.go b/internal/serving/handler.go index 2a9969b7..446c9843 100644 --- a/internal/serving/handler.go +++ b/internal/serving/handler.go @@ -2,15 +2,13 @@ package serving import "net/http" -// Handler interface represent an interface that is needed to fullfil the -// serving request -type Handler interface { - Writer() http.ResponseWriter - Request() *http.Request - LookupPath() string - Subpath() string - IsNamespaceProject() bool - IsHTTPSOnly() bool - HasAccessControl() bool - ProjectID() uint64 +type Handler struct { + Writer http.ResponseWriter + Request *http.Request + + LookupPath *LookupPath + + // parsed representation of Request.URI + // that is part of LookupPath.Prefix + SubPath string } diff --git a/internal/domain/project.go b/internal/serving/lookup_path.go index 9ea7306f..77ac45e8 100644 --- a/internal/domain/project.go +++ b/internal/serving/lookup_path.go @@ -1,8 +1,9 @@ -package domain +package serving // Project holds a domain / project configuration -type Project struct { - LookupPath string +type LookupPath struct { + Location string + Path string IsNamespaceProject bool IsHTTPSOnly bool HasAccessControl bool diff --git a/internal/serving/serving.go b/internal/serving/serving.go index c6a39241..6fde8216 100644 --- a/internal/serving/serving.go +++ b/internal/serving/serving.go @@ -1,23 +1,7 @@ package serving -import ( - "gitlab.com/gitlab-org/gitlab-pages/internal/serving/disk" -) - // Serving is an interface used to define a serving driver type Serving interface { ServeFileHTTP(Handler) bool ServeNotFoundHTTP(Handler) - HasAcmeChallenge(handler Handler, token string) bool -} - -// NewDiskServing returns a serving instance that is capable of reading files -// from the disk -func NewDiskServing(domain, location string) Serving { - return &diskServing{ - disk: &disk.Serving{ - Domain: domain, - Reader: &disk.Reader{Location: location}, - }, - } } diff --git a/internal/source/disk/custom.go b/internal/source/disk/custom.go index 0cf443b0..a7c89700 100644 --- a/internal/source/disk/custom.go +++ b/internal/source/disk/custom.go @@ -3,17 +3,20 @@ package disk import ( "net/http" - "gitlab.com/gitlab-org/gitlab-pages/internal/domain" + "gitlab.com/gitlab-org/gitlab-pages/internal/serving" ) type customProjectResolver struct { config *domainConfig + + path string } // TODO tests -func (p *customProjectResolver) Resolve(r *http.Request) (*domain.Project, string, error) { - project := &domain.Project{ - LookupPath: "/", +func (p *customProjectResolver) Resolve(r *http.Request) (*serving.LookupPath, string, error) { + project := &serving.LookupPath{ + Location: "/", + Path: p.path, IsNamespaceProject: false, IsHTTPSOnly: p.config.HTTPSOnly, HasAccessControl: p.config.AccessControl, diff --git a/internal/source/disk/domain_test.go b/internal/source/disk/domain_test.go index 4140241e..ba4fb161 100644 --- a/internal/source/disk/domain_test.go +++ b/internal/source/disk/domain_test.go @@ -27,7 +27,6 @@ func serveFileOrNotFound(domain *domain.Domain) http.HandlerFunc { func testGroupServeHTTPHost(t *testing.T, host string) { testGroup := &domain.Domain{ - Location: "group", Resolver: &Group{ name: "group", projects: map[string]*projectConfig{ @@ -81,9 +80,9 @@ func TestDomainServeHTTP(t *testing.T) { defer cleanup() testDomain := &domain.Domain{ - Name: "test.domain.com", - Location: "group/project2", + Name: "test.domain.com", Resolver: &customProjectResolver{ + path: "group/project2/public", config: &domainConfig{}, }, } @@ -109,7 +108,6 @@ func TestIsHTTPSOnly(t *testing.T) { { name: "Default group domain with HTTPS-only enabled", domain: &domain.Domain{ - Location: "group/project", Resolver: &Group{ name: "group", projects: projects{"test-domain": &projectConfig{HTTPSOnly: true}}, @@ -121,7 +119,6 @@ func TestIsHTTPSOnly(t *testing.T) { { name: "Default group domain with HTTPS-only disabled", domain: &domain.Domain{ - Location: "group/project", Resolver: &Group{ name: "group", projects: projects{"test-domain": &projectConfig{HTTPSOnly: false}}, @@ -133,7 +130,6 @@ func TestIsHTTPSOnly(t *testing.T) { { name: "Case-insensitive default group domain with HTTPS-only enabled", domain: &domain.Domain{ - Location: "group/project", Resolver: &Group{ name: "group", projects: projects{"test-domain": &projectConfig{HTTPSOnly: true}}, @@ -145,7 +141,6 @@ func TestIsHTTPSOnly(t *testing.T) { { name: "Other group domain with HTTPS-only enabled", domain: &domain.Domain{ - Location: "group/project", Resolver: &Group{ name: "group", projects: projects{"project": &projectConfig{HTTPSOnly: true}}, @@ -157,7 +152,6 @@ func TestIsHTTPSOnly(t *testing.T) { { name: "Other group domain with HTTPS-only disabled", domain: &domain.Domain{ - Location: "group/project", Resolver: &Group{ name: "group", projects: projects{"project": &projectConfig{HTTPSOnly: false}}, @@ -167,10 +161,8 @@ func TestIsHTTPSOnly(t *testing.T) { expected: false, }, { - name: "Unknown project", - domain: &domain.Domain{ - Location: "group/project", - }, + name: "Unknown project", + domain: &domain.Domain{}, url: "http://test-domain/project", expected: false, }, @@ -216,7 +208,6 @@ func TestGroupServeHTTPGzip(t *testing.T) { defer cleanup() testGroup := &domain.Domain{ - Location: "group", Resolver: &Group{ name: "group", projects: map[string]*projectConfig{ @@ -283,7 +274,6 @@ func TestGroup404ServeHTTP(t *testing.T) { defer cleanup() testGroup := &domain.Domain{ - Location: "group.404", Resolver: &Group{ name: "group.404", projects: map[string]*projectConfig{ @@ -312,8 +302,8 @@ func TestDomain404ServeHTTP(t *testing.T) { defer cleanup() testDomain := &domain.Domain{ - Location: "group.404/domain.404", Resolver: &customProjectResolver{ + path: "group.404/domain.404/public", config: &domainConfig{Domain: "domain.404.com"}, }, } @@ -326,17 +316,13 @@ func TestPredefined404ServeHTTP(t *testing.T) { cleanup := setUpTests(t) defer cleanup() - testDomain := &domain.Domain{ - Location: "group", - } + testDomain := &domain.Domain{} testhelpers.AssertHTTP404(t, serveFileOrNotFound(testDomain), "GET", "http://group.test.io/not-existing-file", nil, "The page you're looking for could not be found") } func TestGroupCertificate(t *testing.T) { - testGroup := &domain.Domain{ - Location: "group", - } + testGroup := &domain.Domain{} tls, err := testGroup.EnsureCertificate() require.Nil(t, tls) @@ -345,8 +331,8 @@ func TestGroupCertificate(t *testing.T) { func TestDomainNoCertificate(t *testing.T) { testDomain := &domain.Domain{ - Location: "group/project2", Resolver: &customProjectResolver{ + path: "group/project2/public", config: &domainConfig{Domain: "test.domain.com"}, }, } @@ -362,11 +348,12 @@ func TestDomainNoCertificate(t *testing.T) { func TestDomainCertificate(t *testing.T) { testDomain := &domain.Domain{ - Location: "group/project2", Name: "test.domain.com", CertificateCert: fixture.Certificate, CertificateKey: fixture.Key, - Resolver: &customProjectResolver{}, + Resolver: &customProjectResolver{ + path: "group/project2/public", + }, } tls, err := testDomain.EnsureCertificate() @@ -379,7 +366,6 @@ func TestCacheControlHeaders(t *testing.T) { defer cleanup() testGroup := &domain.Domain{ - Location: "group", Resolver: &Group{ name: "group", projects: map[string]*projectConfig{ diff --git a/internal/source/disk/group.go b/internal/source/disk/group.go index efa3fce5..df093926 100644 --- a/internal/source/disk/group.go +++ b/internal/source/disk/group.go @@ -3,10 +3,11 @@ package disk import ( "net/http" "path" + "path/filepath" "strings" - "gitlab.com/gitlab-org/gitlab-pages/internal/domain" "gitlab.com/gitlab-org/gitlab-pages/internal/host" + "gitlab.com/gitlab-org/gitlab-pages/internal/serving" ) const ( @@ -52,14 +53,14 @@ func (g *Group) digProjectWithSubpath(parentPath string, keys []string) (*projec // Look up a project inside the domain based on the host and path. Returns the // project and its name (if applicable) -func (g *Group) getProjectConfigWithSubpath(r *http.Request) (*projectConfig, string, string) { +func (g *Group) getProjectConfigWithSubpath(r *http.Request) (*projectConfig, string, string, string) { // Check for a project specified in the URL: http://group.gitlab.io/projectA // If present, these projects shadow the group domain. split := strings.SplitN(r.URL.Path, "/", maxProjectDepth) if len(split) >= 2 { projectConfig, projectPath, urlPath := g.digProjectWithSubpath("", split[1:]) if projectConfig != nil { - return projectConfig, projectPath, urlPath + return projectConfig, "/" + projectPath, projectPath, urlPath } } @@ -67,24 +68,26 @@ func (g *Group) getProjectConfigWithSubpath(r *http.Request) (*projectConfig, st // return the group project if it exists. if host := host.FromRequest(r); host != "" { if groupProject := g.projects[host]; groupProject != nil { - return groupProject, host, strings.Join(split[1:], "/") + // TODOHERE: the location here should be "/", so we return "" + return groupProject, "/", host, strings.Join(split[1:], "/") } } - return nil, "", "" + return nil, "", "", "" } // Resolve tries to find project and its config recursively for a given request // to a group domain -func (g *Group) Resolve(r *http.Request) (*domain.Project, string, error) { - projectConfig, projectPath, subPath := g.getProjectConfigWithSubpath(r) +func (g *Group) Resolve(r *http.Request) (*serving.LookupPath, string, error) { + projectConfig, location, projectPath, subPath := g.getProjectConfigWithSubpath(r) if projectConfig == nil { return nil, "", nil // it is not an error when project does not exist } - project := &domain.Project{ - LookupPath: projectPath, + project := &serving.LookupPath{ + Location: location, + Path: filepath.Join(g.name, projectPath, "public"), IsNamespaceProject: projectConfig.NamespaceProject, IsHTTPSOnly: projectConfig.HTTPSOnly, HasAccessControl: projectConfig.AccessControl, diff --git a/internal/source/disk/map.go b/internal/source/disk/map.go index 09902241..3fb7bd4a 100644 --- a/internal/source/disk/map.go +++ b/internal/source/disk/map.go @@ -22,13 +22,14 @@ type Map map[string]*domain.Domain type domainsUpdater func(Map) func (dm Map) updateDomainMap(domainName string, domain *domain.Domain) { - if old, ok := dm[domainName]; ok { - log.WithFields(log.Fields{ - "domain_name": domainName, - "new_location": domain.Location, - "old_location": old.Location, - }).Error("Duplicate domain") - } + // TODOHERE: + // if old, ok := dm[domainName]; ok { + // log.WithFields(log.Fields{ + // "domain_name": domainName, + // "new_location": domain.Location, + // "old_location": old.Location, + // }).Error("Duplicate domain") + // } dm[domainName] = domain } @@ -38,8 +39,10 @@ func (dm Map) addDomain(rootDomain, groupName, projectName string, config *domai Name: strings.ToLower(config.Domain), CertificateCert: config.Certificate, CertificateKey: config.Key, - Location: filepath.Join(groupName, projectName), - Resolver: &customProjectResolver{config: config}, + Resolver: &customProjectResolver{ + config: config, + path: filepath.Join(groupName, projectName, "public"), + }, } dm.updateDomainMap(newDomain.Name, newDomain) @@ -58,7 +61,6 @@ func (dm Map) updateGroupDomain(rootDomain, groupName, projectPath string, https groupDomain = &domain.Domain{ Name: domainName, - Location: groupName, Resolver: groupResolver, } } |