diff options
author | Tuomo Ala-Vannesluoma <tuomoav@gmail.com> | 2018-09-30 15:05:27 +0300 |
---|---|---|
committer | Tuomo Ala-Vannesluoma <tuomoav@gmail.com> | 2018-09-30 15:05:27 +0300 |
commit | c69313b2ed71fbecd8acca283954dc3cfe424acb (patch) | |
tree | 63c4e2cbc80c82bcb7cd6181e13c2b2f3b6992a3 /internal | |
parent | cee3464d6fe99efebac5f8d1b569f1301babdade (diff) | |
parent | d07b803b6f8519566940843e389a6c2d73424a76 (diff) |
Merge commit 'd07b803b6f8519566940843e389a6c2d73424a76' into auth
Diffstat (limited to 'internal')
-rw-r--r-- | internal/domain/domain.go | 82 | ||||
-rw-r--r-- | internal/domain/domain_test.go | 30 |
2 files changed, 64 insertions, 48 deletions
diff --git a/internal/domain/domain.go b/internal/domain/domain.go index 4ac43100..a402d9e0 100644 --- a/internal/domain/domain.go +++ b/internal/domain/domain.go @@ -101,15 +101,25 @@ func setContentType(w http.ResponseWriter, fullPath string) { } } +func getHost(r *http.Request) string { + host := strings.ToLower(r.Host) + + if splitHost, _, err := net.SplitHostPort(host); err == nil { + host = splitHost + } + + return host +} + // Look up a project inside the domain based on the host and path. Returns the // project and its name (if applicable) -func (d *D) getProject(r *http.Request) (*project, string) { +func (d *D) getProjectWithSubpath(r *http.Request) (*project, 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, "/", 3) if len(split) >= 2 { if project := d.projects[split[1]]; project != nil { - return project, split[1] + return project, split[1], strings.Join(split[2:], "/") } } @@ -117,21 +127,11 @@ func (d *D) getProject(r *http.Request) (*project, string) { // return the group project if it exists. if host := getHost(r); host != "" { if groupProject := d.projects[host]; groupProject != nil { - return groupProject, host + return groupProject, host, strings.Join(split[1:], "/") } } - return nil, "" -} - -func getHost(r *http.Request) string { - host := strings.ToLower(r.Host) - - if splitHost, _, err := net.SplitHostPort(host); err == nil { - host = splitHost - } - - return host + return nil, "", "" } // IsHTTPSOnly figures out if the request should be handled with HTTPS @@ -147,7 +147,7 @@ func (d *D) IsHTTPSOnly(r *http.Request) bool { } // Check projects served under the group domain, including the default one - if project, _ := d.getProject(r); project != nil { + if project, _, _ := d.getProjectWithSubpath(r); project != nil { return project.HTTPSOnly } @@ -166,7 +166,7 @@ func (d *D) IsAccessControlEnabled(r *http.Request) bool { } // Check projects served under the group domain, including the default one - if project, _ := d.getProject(r); project != nil { + if project, _, _ := d.getProjectWithSubpath(r); project != nil { return project.AccessControl } @@ -186,7 +186,7 @@ func (d *D) IsNamespaceProject(r *http.Request) bool { } // Check projects served under the group domain, including the default one - if project, _ := d.getProject(r); project != nil { + if project, _, _ := d.getProjectWithSubpath(r); project != nil { return project.NamespaceProject } @@ -203,9 +203,7 @@ func (d *D) GetID(r *http.Request) uint64 { return d.config.ID } - project, _ := d.getProject(r) - - if project != nil { + if project, _, _ := d.getProjectWithSubpath(r); project != nil { return project.ID } @@ -222,9 +220,7 @@ func (d *D) HasProject(r *http.Request) bool { return true } - project, _ := d.getProject(r) - - if project != nil { + if project, _, _ := d.getProjectWithSubpath(r); project != nil { return true } @@ -337,20 +333,18 @@ func (d *D) tryNotFound(w http.ResponseWriter, r *http.Request, projectName stri return nil } -func (d *D) tryFile(w http.ResponseWriter, r *http.Request, projectName, pathSuffix string, subPath ...string) error { +func (d *D) tryFile(w http.ResponseWriter, r *http.Request, projectName string, subPath ...string) error { fullPath, err := d.resolvePath(projectName, subPath...) - if locationError, _ := err.(*locationDirectoryError); locationError != nil { if endsWithSlash(r.URL.Path) { fullPath, err = d.resolvePath(projectName, filepath.Join(subPath...), "index.html") } else { + // Concat Host with URL.Path redirectPath := "//" + r.Host + "/" - if pathSuffix != "" { - redirectPath += pathSuffix + "/" - } - if locationError.RelativePath != "" { - redirectPath += strings.TrimPrefix(locationError.RelativePath, "/") + "/" - } + redirectPath += strings.TrimPrefix(r.URL.Path, "/") + + // Ensure that there's always "/" at end + redirectPath = strings.TrimSuffix(redirectPath, "/") + "/" http.Redirect(w, r, redirectPath, 302) return nil } @@ -364,16 +358,13 @@ func (d *D) tryFile(w http.ResponseWriter, r *http.Request, projectName, pathSuf } func (d *D) serveFileFromGroup(w http.ResponseWriter, r *http.Request) bool { - // The Path always contains "/" at the beginning - split := strings.SplitN(r.URL.Path, "/", 3) - - // Try to serve file for http://group.example.com/subpath/... => /group/subpath/... - if len(split) >= 2 && d.tryFile(w, r, split[1], split[1], split[2:]...) == nil { + project, projectName, subPath := d.getProjectWithSubpath(r) + if project == nil { + httperrors.Serve404(w) return true } - // Try to serve file for http://group.example.com/... => /group/group.example.com/... - if r.Host != "" && d.tryFile(w, r, strings.ToLower(r.Host), "", r.URL.Path) == nil { + if d.tryFile(w, r, projectName, subPath) == nil { return true } @@ -382,25 +373,24 @@ func (d *D) serveFileFromGroup(w http.ResponseWriter, r *http.Request) bool { func (d *D) serveNotFoundFromGroup(w http.ResponseWriter, r *http.Request) { // The Path always contains "/" at the beginning - split := strings.SplitN(r.URL.Path, "/", 3) - - // Try serving not found page for http://group.example.com/subpath/ => /group/subpath/404.html - if len(split) >= 2 && d.tryNotFound(w, r, split[1]) == nil { + project, projectName, _ := d.getProjectWithSubpath(r) + if project == nil { + httperrors.Serve404(w) return } - // Try serving not found page for http://group.example.com/ => /group/group.example.com/404.html - if r.Host != "" && d.tryNotFound(w, r, strings.ToLower(r.Host)) == nil { + // Try serving custom not-found page + if d.tryNotFound(w, r, projectName) == nil { return } - // Serve generic not found + // Generic 404 httperrors.Serve404(w) } func (d *D) serveFileFromConfig(w http.ResponseWriter, r *http.Request) bool { // Try to serve file for http://host/... => /group/project/... - if d.tryFile(w, r, d.projectName, "", r.URL.Path) == nil { + if d.tryFile(w, r, d.projectName, r.URL.Path) == nil { return true } diff --git a/internal/domain/domain_test.go b/internal/domain/domain_test.go index 4c08aee5..de780197 100644 --- a/internal/domain/domain_test.go +++ b/internal/domain/domain_test.go @@ -31,6 +31,12 @@ func TestGroupServeHTTP(t *testing.T) { testGroup := &D{ group: "group", projectName: "", + projects: map[string]*project{ + "group.test.io": &project{}, + "group.gitlab-example.com": &project{}, + "project": &project{}, + "project2": &project{}, + }, } assert.HTTPBodyContains(t, serveFileOrNotFound(testGroup), "GET", "http://group.test.io/", nil, "main-dir") @@ -205,6 +211,12 @@ func TestGroupServeHTTPGzip(t *testing.T) { testGroup := &D{ group: "group", projectName: "", + projects: map[string]*project{ + "group.test.io": &project{}, + "group.gitlab-example.com": &project{}, + "project": &project{}, + "project2": &project{}, + }, } testSet := []struct { @@ -268,15 +280,24 @@ func TestGroup404ServeHTTP(t *testing.T) { testGroup := &D{ group: "group.404", projectName: "", + projects: map[string]*project{ + "domain.404": &project{}, + "group.404.test.io": &project{}, + "project.404": &project{}, + "project.404.symlink": &project{}, + "project.no.404": &project{}, + }, } testHTTP404(t, serveFileOrNotFound(testGroup), "GET", "http://group.404.test.io/project.404/not/existing-file", nil, "Custom 404 project page") testHTTP404(t, serveFileOrNotFound(testGroup), "GET", "http://group.404.test.io/project.404/", nil, "Custom 404 project page") - testHTTP404(t, serveFileOrNotFound(testGroup), "GET", "http://group.404.test.io/project.no.404/not/existing-file", nil, "Custom 404 group page") testHTTP404(t, serveFileOrNotFound(testGroup), "GET", "http://group.404.test.io/not/existing-file", nil, "Custom 404 group page") testHTTP404(t, serveFileOrNotFound(testGroup), "GET", "http://group.404.test.io/not-existing-file", nil, "Custom 404 group page") testHTTP404(t, serveFileOrNotFound(testGroup), "GET", "http://group.404.test.io/", nil, "Custom 404 group page") assert.HTTPBodyNotContains(t, serveFileOrNotFound(testGroup), "GET", "http://group.404.test.io/project.404.symlink/not/existing-file", nil, "Custom 404 project page") + + // Ensure the namespace project's custom 404.html is not used by projects + testHTTP404(t, serveFileOrNotFound(testGroup), "GET", "http://group.404.test.io/project.no.404/not/existing-file", nil, "The page you're looking for could not be found.") } func TestDomain404ServeHTTP(t *testing.T) { @@ -350,7 +371,12 @@ func TestDomainCertificate(t *testing.T) { } func TestCacheControlHeaders(t *testing.T) { - testGroup := &D{group: "group"} + testGroup := &D{ + group: "group", + projects: map[string]*project{ + "group.test.io": &project{}, + }, + } w := httptest.NewRecorder() req, err := http.NewRequest("GET", "http://group.test.io/", nil) require.NoError(t, err) |