Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-pages.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Trzcinski <ayufan@ayufan.eu>2016-02-11 20:25:30 +0300
committerKamil Trzcinski <ayufan@ayufan.eu>2016-02-11 20:25:30 +0300
commita5548d71b72b050df4d708953120af5f16dde39b (patch)
treeb4afde6c7168dfa127fbf8402acd79c6bc6a8ff1
parent9bc5a5ff0b4bbbf8ef2fab821bc974909d276982 (diff)
Added more behavior tests
-rw-r--r--.gitignore1
-rw-r--r--domain.go26
-rw-r--r--domain_test.go117
-rw-r--r--domains_test.go36
-rw-r--r--main.go7
-rw-r--r--shared/pages/README.md1
-rw-r--r--shared/pages/group/group.test.io/public/index.html1
-rw-r--r--shared/pages/group/group.test.io/public/project2/index.html1
-rw-r--r--shared/pages/group/project/public/index.html1
-rw-r--r--shared/pages/group/project/public/subdir/index.html1
-rw-r--r--shared/pages/group/project2/public/index.html1
-rw-r--r--shared/pages/group/project2/public/subdir/index.html1
12 files changed, 185 insertions, 9 deletions
diff --git a/.gitignore b/.gitignore
index bfa6a22a..a89eb3c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
# Created by .ignore support plugin (hsz.mobi)
+shared/pages/.update
diff --git a/domain.go b/domain.go
index 0a75e21e..f9f3d3ac 100644
--- a/domain.go
+++ b/domain.go
@@ -10,10 +10,11 @@ import (
)
type domain struct {
- Group string
- Project string
- Config *domainConfig
- certificate *tls.Certificate
+ Group string
+ Project string
+ Config *domainConfig
+ certificate *tls.Certificate
+ certificateError error
}
func (d *domain) notFound(w http.ResponseWriter, r *http.Request) {
@@ -23,8 +24,13 @@ func (d *domain) notFound(w http.ResponseWriter, r *http.Request) {
func (d *domain) tryFile(w http.ResponseWriter, r *http.Request, projectName, subPath string) bool {
publicPath := filepath.Join(*pagesRoot, d.Group, projectName, "public")
fullPath := filepath.Join(publicPath, subPath)
- fullPath = filepath.Clean(fullPath)
- if !strings.HasPrefix(fullPath, publicPath) {
+ fullPath, err := filepath.EvalSymlinks(fullPath)
+ if err != nil {
+ return false
+ }
+
+ if !strings.HasPrefix(fullPath, publicPath+"/") && fullPath != publicPath {
+ println("The", fullPath, "should be in", publicPath)
return false
}
@@ -59,6 +65,7 @@ func (d *domain) tryFile(w http.ResponseWriter, r *http.Request, projectName, su
return false
}
+ println("Serving", fullPath, "for", r.URL.Path)
http.ServeContent(w, r, filepath.Base(file.Name()), fi.ModTime(), file)
return true
}
@@ -77,7 +84,7 @@ func (d *domain) serveFromGroup(w http.ResponseWriter, r *http.Request) {
}
}
- if d.tryFile(w, r, strings.ToLower(r.Host), r.URL.Path) {
+ if r.Host != "" && d.tryFile(w, r, strings.ToLower(r.Host), r.URL.Path) {
return
}
@@ -97,12 +104,13 @@ func (d *domain) ensureCertificate() (*tls.Certificate, error) {
return nil, errors.New("tls certificates can be loaded only for pages with configuration")
}
- if d.certificate != nil {
- return d.certificate, nil
+ if d.certificate != nil || d.certificateError != nil {
+ return d.certificate, d.certificateError
}
tls, err := tls.X509KeyPair([]byte(d.Config.Certificate), []byte(d.Config.Key))
if err != nil {
+ d.certificateError = err
return nil, err
}
diff --git a/domain_test.go b/domain_test.go
new file mode 100644
index 00000000..dac9b2a1
--- /dev/null
+++ b/domain_test.go
@@ -0,0 +1,117 @@
+package main
+
+import (
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func TestGroupServeHTTP(t *testing.T) {
+ testGroup := &domain{
+ Group: "group",
+ Project: "",
+ }
+
+ assert.HTTPBodyContains(t, testGroup.ServeHTTP, "GET", "http://group.test.io/", nil, "main-dir")
+ assert.HTTPBodyContains(t, testGroup.ServeHTTP, "GET", "http://group.test.io/index.html", nil, "main-dir")
+ assert.HTTPRedirect(t, testGroup.ServeHTTP, "GET", "http://group.test.io/project", nil)
+ assert.HTTPBodyContains(t, testGroup.ServeHTTP, "GET", "http://group.test.io/project/", nil, "project-subdir")
+ assert.HTTPBodyContains(t, testGroup.ServeHTTP, "GET", "http://group.test.io/project/index.html", nil, "project-subdir")
+ assert.HTTPRedirect(t, testGroup.ServeHTTP, "GET", "http://group.test.io/project/subdir", nil)
+ assert.HTTPBodyContains(t, testGroup.ServeHTTP, "GET", "http://group.test.io/project/subdir/", nil, "project-subsubdir")
+ assert.HTTPBodyContains(t, testGroup.ServeHTTP, "GET", "http://group.test.io/project2/", nil, "project2-main")
+ assert.HTTPBodyContains(t, testGroup.ServeHTTP, "GET", "http://group.test.io/project2/index.html", nil, "project2-main")
+ assert.HTTPError(t, testGroup.ServeHTTP, "GET", "http://group.test.io/symlink", nil)
+ assert.HTTPError(t, testGroup.ServeHTTP, "GET", "http://group.test.io/symlink/index.html", nil)
+ assert.HTTPError(t, testGroup.ServeHTTP, "GET", "http://group.test.io/symlink/subdir/", nil)
+ assert.HTTPError(t, testGroup.ServeHTTP, "GET", "http://group.test.io/project/fifo", nil)
+ assert.HTTPError(t, testGroup.ServeHTTP, "GET", "http://group.test.io/not-existing-file", nil)
+}
+
+func TestDomainServeHTTP(t *testing.T) {
+ testDomain := &domain{
+ Group: "group",
+ Project: "project2",
+ Config: &domainConfig{
+ Domain: "test.domain.com",
+ },
+ }
+
+ assert.HTTPBodyContains(t, testDomain.ServeHTTP, "GET", "/index.html", nil, "project2-main")
+ assert.HTTPRedirect(t, testDomain.ServeHTTP, "GET", "/subdir", nil)
+ assert.HTTPBodyContains(t, testDomain.ServeHTTP, "GET", "/subdir/", nil, "project2-subdir")
+ assert.HTTPError(t, testDomain.ServeHTTP, "GET", "/not-existing-file", nil)
+}
+
+func TestGroupCertificate(t *testing.T) {
+ testGroup := &domain{
+ Group: "group",
+ Project: "",
+ }
+
+ tls, err := testGroup.ensureCertificate()
+ assert.Nil(t, tls)
+ assert.Error(t, err)
+}
+
+func TestDomainNoCertificate(t *testing.T) {
+ testDomain := &domain{
+ Group: "group",
+ Project: "project2",
+ Config: &domainConfig{
+ Domain: "test.domain.com",
+ },
+ }
+
+ tls, err := testDomain.ensureCertificate()
+ assert.Nil(t, tls)
+ assert.Error(t, err)
+
+ _, err2 := testDomain.ensureCertificate()
+ assert.Error(t, err)
+ assert.Equal(t, err, err2)
+}
+
+func TestDomainCertificate(t *testing.T) {
+ testDomain := &domain{
+ Group: "group",
+ Project: "project2",
+ Config: &domainConfig{
+ Domain: "test.domain.com",
+ Certificate: `-----BEGIN CERTIFICATE-----
+MIICWDCCAcGgAwIBAgIJAMyzCfoGEwVNMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTYwMjExMTcxNzM2WhcNMjYwMjA4MTcxNzM2WjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+gQC2ZSzGIlv2zRsELkmEA1JcvIdsFv80b0NbBftewDAQRuyPlhGNifFx6v7+3O1F
+5+f+So43N0QbdrHu11K+ZuXNc6hUy0ofG/eRqXniGZEn8paUdQ98sWsbWelBDNeg
+WX4FQomynjyxbG+3IuJR5UHoLWhrJ9+pbPrT915eObbaTQIDAQABo1AwTjAdBgNV
+HQ4EFgQUGAhDu+gfckg4IkHRCQWBn4ltKV4wHwYDVR0jBBgwFoAUGAhDu+gfckg4
+IkHRCQWBn4ltKV4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAaGx5U
+JRW5HC9dXADLf9OnmJRqWi3VNXEXWFk5XgHKc1z7KIBWMsdj+1gzm5ltRO7hkHw9
+bx6jQKZBRiUxyqTFw9Ywrk1fYFAxk8hxuqVYcGdonImJarHZTdVMBRWut9+EZBVm
+77eYbz2zASNpy++QIg85YgQum9uqREClHRBsxQ==
+-----END CERTIFICATE-----`,
+ Key: `-----BEGIN PRIVATE KEY-----
+MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALZlLMYiW/bNGwQu
+SYQDUly8h2wW/zRvQ1sF+17AMBBG7I+WEY2J8XHq/v7c7UXn5/5Kjjc3RBt2se7X
+Ur5m5c1zqFTLSh8b95GpeeIZkSfylpR1D3yxaxtZ6UEM16BZfgVCibKePLFsb7ci
+4lHlQegtaGsn36ls+tP3Xl45ttpNAgMBAAECgYAAqZFmDs3isY/9jeV6c0CjUZP0
+UokOubC27eihyXTjOj61rsfVicC0tzPB3S+HZ3YyODcYAD1hFCdFRMbqJhmDiewK
+5GfATdNQeNARCfJdjYn57NKaXm7rc4C3so1YfxTL6k9QGJgTcybXiClQPDrhkZt3
+YLIeeJbY3OppLqjzgQJBAN5AzwyUqX5eQIUncQKcFY0PIjfFTku62brT7hq+TlqY
+1B6n3GUtIX+tyYg1qusy4KUUSzMslXJubHsxKanGqZ0CQQDSFwzK7KEYoZol5OMX
+mRsavc3iXmmEkkNRdNb1R4UqrlasPeeIeO1CfoD2RPcQhZCwFtR8xS8u6X9ncfC4
+qyxxAkAhpQvy6ppR7/Cyd4sLCxfUF8NlT/APVMTbHHQCBmcUHeiWj3C0vEVC78r/
+XKh4HGaXdt//ajNhdEflykZ1VgadAkB6Zh934mEA3rXWOgHsb7EQ5WAb8HF9YVGD
+FZVfFaoJ8cRhWTeZlQp14Qn1cLyYjZh8XvCxOJiCtlsZw5JBpMihAkBA6ltWb+aZ
+EBjC8ZRwZE+cAzmxaYPSs2J7JhS7X7H7Ax7ShhvHI4br3nqf00H4LkvtcHkn5d9G
+MwE1w2r4Deww
+-----END PRIVATE KEY-----`,
+ },
+ }
+
+ tls, err := testDomain.ensureCertificate()
+ assert.NotNil(t, tls)
+ assert.NoError(t, err)
+}
diff --git a/domains_test.go b/domains_test.go
index 5c16aa14..ae849f46 100644
--- a/domains_test.go
+++ b/domains_test.go
@@ -4,8 +4,14 @@ import (
"testing"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/assert"
+ "time"
+ "io/ioutil"
+ "crypto/rand"
+ "os"
)
+const updateFile = "shared/pages/.update"
+
func TestReadProjects(t *testing.T) {
*pagesDomain = "test.io"
@@ -33,3 +39,33 @@ func TestReadProjects(t *testing.T) {
assert.Contains(t, expectedDomains, actual)
}
}
+
+func writeRandomTimestamp() {
+ b := make([]byte, 10)
+ rand.Read(b)
+ ioutil.WriteFile(updateFile, b, 0600)
+}
+
+func TestWatchDomains(t *testing.T) {
+ update := make(chan domains)
+ go watchDomains(func(domains domains) {
+ update <- domains
+ }, time.Microsecond)
+
+ defer os.Remove(updateFile)
+
+ domains := <-update
+ assert.NotNil(t, domains, "if the domains are fetched on start")
+
+ writeRandomTimestamp()
+ domains = <-update
+ assert.NotNil(t, domains, "if the domains are updated after the creation")
+
+ writeRandomTimestamp()
+ domains = <-update
+ assert.NotNil(t, domains, "if the domains are updated after the timestamp change")
+
+ os.Remove(updateFile)
+ domains = <-update
+ assert.NotNil(t, domains, "if the domains are updated after the timestamp removal")
+}
diff --git a/main.go b/main.go
index a1e41ad4..0dc90b31 100644
--- a/main.go
+++ b/main.go
@@ -9,6 +9,7 @@ import (
"strings"
"sync"
"time"
+ "path/filepath"
)
// VERSION stores the information about the semantic version of application
@@ -109,6 +110,12 @@ func main() {
fmt.Printf("URL: https://gitlab.com/gitlab-org/gitlab-pages")
flag.Parse()
+ fullPath, err := filepath.EvalSymlinks(*pagesRoot)
+ if err != nil {
+ log.Fatalln(err)
+ }
+ *pagesRoot = fullPath
+
// Listen for HTTP
if *listenHTTP != "" {
wg.Add(1)
diff --git a/shared/pages/README.md b/shared/pages/README.md
new file mode 100644
index 00000000..afd6db1c
--- /dev/null
+++ b/shared/pages/README.md
@@ -0,0 +1 @@
+We use that folder to store example files for various pages.
diff --git a/shared/pages/group/group.test.io/public/index.html b/shared/pages/group/group.test.io/public/index.html
new file mode 100644
index 00000000..8da4d196
--- /dev/null
+++ b/shared/pages/group/group.test.io/public/index.html
@@ -0,0 +1 @@
+main-dir
diff --git a/shared/pages/group/group.test.io/public/project2/index.html b/shared/pages/group/group.test.io/public/project2/index.html
new file mode 100644
index 00000000..a47d5768
--- /dev/null
+++ b/shared/pages/group/group.test.io/public/project2/index.html
@@ -0,0 +1 @@
+project2-main
diff --git a/shared/pages/group/project/public/index.html b/shared/pages/group/project/public/index.html
new file mode 100644
index 00000000..4ea0a6ae
--- /dev/null
+++ b/shared/pages/group/project/public/index.html
@@ -0,0 +1 @@
+project-subdir
diff --git a/shared/pages/group/project/public/subdir/index.html b/shared/pages/group/project/public/subdir/index.html
new file mode 100644
index 00000000..c4815ba3
--- /dev/null
+++ b/shared/pages/group/project/public/subdir/index.html
@@ -0,0 +1 @@
+project-subsubdir
diff --git a/shared/pages/group/project2/public/index.html b/shared/pages/group/project2/public/index.html
new file mode 100644
index 00000000..a47d5768
--- /dev/null
+++ b/shared/pages/group/project2/public/index.html
@@ -0,0 +1 @@
+project2-main
diff --git a/shared/pages/group/project2/public/subdir/index.html b/shared/pages/group/project2/public/subdir/index.html
new file mode 100644
index 00000000..ffcfa0b4
--- /dev/null
+++ b/shared/pages/group/project2/public/subdir/index.html
@@ -0,0 +1 @@
+project2-subdir