diff options
Diffstat (limited to 'internal')
-rw-r--r-- | internal/domain/domain.go | 48 | ||||
-rw-r--r-- | internal/domain/domain_test.go | 9 | ||||
-rw-r--r-- | internal/domain/resolver.go | 8 | ||||
-rw-r--r-- | internal/serving/disk/serving.go | 16 | ||||
-rw-r--r-- | internal/serving/handler.go | 3 | ||||
-rw-r--r-- | internal/serving/request.go | 35 | ||||
-rw-r--r-- | internal/serving/serverless/function.go | 8 | ||||
-rw-r--r-- | internal/serving/serverless/function_test.go | 6 | ||||
-rw-r--r-- | internal/serving/serverless/serverless.go | 29 | ||||
-rw-r--r-- | internal/serving/serverless/serverless_test.go | 24 | ||||
-rw-r--r-- | internal/source/disk/custom.go | 9 | ||||
-rw-r--r-- | internal/source/disk/group.go | 13 | ||||
-rw-r--r-- | internal/source/gitlab/api/lookup_path.go | 32 | ||||
-rw-r--r-- | internal/source/gitlab/factory/lookup.go | 22 | ||||
-rw-r--r-- | internal/source/gitlab/factory/serving.go | 34 | ||||
-rw-r--r-- | internal/source/gitlab/gitlab.go | 30 | ||||
-rw-r--r-- | internal/source/gitlab/gitlab_test.go | 46 |
17 files changed, 260 insertions, 112 deletions
diff --git a/internal/domain/domain.go b/internal/domain/domain.go index 28eb3196..af238668 100644 --- a/internal/domain/domain.go +++ b/internal/domain/domain.go @@ -8,7 +8,6 @@ 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. @@ -19,8 +18,6 @@ type Domain struct { Resolver Resolver - serving serving.Serving - certificate *tls.Certificate certificateError error certificateOnce sync.Once @@ -39,42 +36,23 @@ func (d *Domain) isUnconfigured() bool { return d.Resolver == nil } -func (d *Domain) resolve(r *http.Request) (*serving.LookupPath, string) { - lookupPath, subpath, _ := d.Resolver.Resolve(r) - +func (d *Domain) resolve(r *http.Request) *serving.Request { // Current implementation does not return errors in any case - if lookupPath == nil { - return nil, "" - } + request, _ := d.Resolver.Resolve(r) - return lookupPath, subpath + return request } -// GetLookupPath returns a project details based on the request +// GetLookupPath returns a project details based on the request. If LookupPath +// is nil it means that a project does not exist. func (d *Domain) GetLookupPath(r *http.Request) *serving.LookupPath { - lookupPath, _ := d.resolve(r) + request := d.resolve(r) - return lookupPath -} - -// Serving returns domain serving driver -func (d *Domain) Serving() serving.Serving { - if d.serving == nil { - d.serving = disk.New() + if request == nil { + return nil } - return d.serving -} - -func (d *Domain) toHandler(w http.ResponseWriter, r *http.Request) serving.Handler { - project, subpath := d.resolve(r) - - return serving.Handler{ - Writer: w, - Request: r, - LookupPath: project, - SubPath: subpath, - } + return d.resolve(r).LookupPath } // IsHTTPSOnly figures out if the request should be handled with HTTPS @@ -168,7 +146,9 @@ func (d *Domain) ServeFileHTTP(w http.ResponseWriter, r *http.Request) bool { return true } - return d.Serving().ServeFileHTTP(d.toHandler(w, r)) + request := d.resolve(r) + + return request.ServeFileHTTP(w, r) } // ServeNotFoundHTTP serves the not found pages from the projects. @@ -178,5 +158,7 @@ func (d *Domain) ServeNotFoundHTTP(w http.ResponseWriter, r *http.Request) { return } - d.Serving().ServeNotFoundHTTP(d.toHandler(w, r)) + request := d.resolve(r) + + request.ServeNotFoundHTTP(w, r) } diff --git a/internal/domain/domain_test.go b/internal/domain/domain_test.go index a43d3c9a..aa95eb95 100644 --- a/internal/domain/domain_test.go +++ b/internal/domain/domain_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitlab-pages/internal/serving" + "gitlab.com/gitlab-org/gitlab-pages/internal/serving/disk" "gitlab.com/gitlab-org/gitlab-pages/internal/testhelpers" ) @@ -21,8 +22,12 @@ type stubbedResolver struct { err error } -func (resolver *stubbedResolver) Resolve(*http.Request) (*serving.LookupPath, string, error) { - return resolver.project, resolver.subpath, resolver.err +func (resolver *stubbedResolver) Resolve(*http.Request) (*serving.Request, error) { + return &serving.Request{ + Serving: disk.New(), + LookupPath: resolver.project, + SubPath: resolver.subpath, + }, resolver.err } func serveFileOrNotFound(domain *Domain) http.HandlerFunc { diff --git a/internal/domain/resolver.go b/internal/domain/resolver.go index 6bc10f8c..4b93baed 100644 --- a/internal/domain/resolver.go +++ b/internal/domain/resolver.go @@ -6,9 +6,9 @@ import ( "gitlab.com/gitlab-org/gitlab-pages/internal/serving" ) -// Resolver represents an interface responsible for resolving a project -// per-request +// Resolver represents an interface responsible for resolving a pages serving +// request for each HTTP request type Resolver interface { - // Resolve returns a project with a file path and an error if it occurred - Resolve(*http.Request) (*serving.LookupPath, string, error) + // Resolve returns a serving request and an error if it occurred + Resolve(*http.Request) (*serving.Request, error) } diff --git a/internal/serving/disk/serving.go b/internal/serving/disk/serving.go index db184d3c..430aa95f 100644 --- a/internal/serving/disk/serving.go +++ b/internal/serving/disk/serving.go @@ -5,14 +5,16 @@ import ( "gitlab.com/gitlab-org/gitlab-pages/internal/serving" ) -// Serving describes a disk access serving -type Serving struct { +var disk *Disk + +// Disk describes a disk access serving +type Disk struct { 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 serving.Handler) bool { +func (s *Disk) ServeFileHTTP(h serving.Handler) bool { if s.tryFile(h) == nil { return true } @@ -21,7 +23,7 @@ func (s *Serving) ServeFileHTTP(h serving.Handler) bool { } // ServeNotFoundHTTP tries to read a custom 404 page -func (s *Serving) ServeNotFoundHTTP(h serving.Handler) { +func (s *Disk) ServeNotFoundHTTP(h serving.Handler) { if s.tryNotFound(h) == nil { return } @@ -33,5 +35,9 @@ func (s *Serving) ServeNotFoundHTTP(h serving.Handler) { // New returns a serving instance that is capable of reading files // from the disk func New() serving.Serving { - return &Serving{} + if disk == nil { + disk = &Disk{} + } + + return disk } diff --git a/internal/serving/handler.go b/internal/serving/handler.go index 99c4ca2f..a0d66ecb 100644 --- a/internal/serving/handler.go +++ b/internal/serving/handler.go @@ -8,6 +8,5 @@ type Handler struct { Writer http.ResponseWriter Request *http.Request LookupPath *LookupPath - // Parsed representation of Request.URI that is part of LookupPath.Prefix - SubPath string + SubPath string } diff --git a/internal/serving/request.go b/internal/serving/request.go new file mode 100644 index 00000000..019939d6 --- /dev/null +++ b/internal/serving/request.go @@ -0,0 +1,35 @@ +package serving + +import "net/http" + +// Request is a type that aggregates a serving itself, project lookup path and +// a request subpath based on an incoming request to serve page. +type Request struct { + Serving Serving // Serving choosen to serve this request + LookupPath *LookupPath // LookupPath contains pages project details + SubPath string // Subpath is a URL path subcomponent for this request +} + +// ServeFileHTTP forwards serving request handler to the serving itself +func (s Request) ServeFileHTTP(w http.ResponseWriter, r *http.Request) bool { + handler := Handler{ + Writer: w, + Request: r, + LookupPath: s.LookupPath, + SubPath: s.SubPath, + } + + return s.Serving.ServeFileHTTP(handler) +} + +// ServeNotFoundHTTP forwards serving request handler to the serving itself +func (s Request) ServeNotFoundHTTP(w http.ResponseWriter, r *http.Request) { + handler := Handler{ + Writer: w, + Request: r, + LookupPath: s.LookupPath, + SubPath: s.SubPath, + } + + s.Serving.ServeNotFoundHTTP(handler) +} diff --git a/internal/serving/serverless/function.go b/internal/serving/serverless/function.go index 20d4ec2c..c5d3d179 100644 --- a/internal/serving/serverless/function.go +++ b/internal/serving/serverless/function.go @@ -5,14 +5,14 @@ import "strings" // Function represents a Knative service that is going to be invoked by the // proxied request type Function struct { - Name string // Name is a function name, it includes a "service name" component too - Namespace string // Namespace is a kubernetes namespace this function has been deployed to - BaseDomain string // BaseDomain is a cluster base domain, used to route requests to apropriate service + Name string // Name is a function name, it includes a "service name" component too + Domain string // Domain is a cluster base domain, used to route requests to apropriate service + Namespace string // Namespace is a kubernetes namespace this function has been deployed to } // Host returns a function address that we are going to expose in the `Host:` // header to make it possible to route a proxied request to appropriate service // in a Knative cluster func (f Function) Host() string { - return strings.Join([]string{f.Name, f.Namespace, f.BaseDomain}, ".") + return strings.Join([]string{f.Name, f.Namespace, f.Domain}, ".") } diff --git a/internal/serving/serverless/function_test.go b/internal/serving/serverless/function_test.go index 65d84eb7..39f86025 100644 --- a/internal/serving/serverless/function_test.go +++ b/internal/serving/serverless/function_test.go @@ -8,9 +8,9 @@ import ( func TestFunctionHost(t *testing.T) { function := Function{ - Name: "my-func", - Namespace: "my-namespace-123", - BaseDomain: "knative.example.com", + Name: "my-func", + Domain: "knative.example.com", + Namespace: "my-namespace-123", } require.Equal(t, "my-func.my-namespace-123.knative.example.com", function.Host()) diff --git a/internal/serving/serverless/serverless.go b/internal/serving/serverless/serverless.go index a73affeb..bec6db16 100644 --- a/internal/serving/serverless/serverless.go +++ b/internal/serving/serverless/serverless.go @@ -1,10 +1,12 @@ package serverless import ( + "errors" "net/http/httputil" "gitlab.com/gitlab-org/gitlab-pages/internal/httperrors" "gitlab.com/gitlab-org/gitlab-pages/internal/serving" + "gitlab.com/gitlab-org/gitlab-pages/internal/source/gitlab/api" "gitlab.com/gitlab-org/gitlab-pages/metrics" ) @@ -14,6 +16,33 @@ type Serverless struct { proxy *httputil.ReverseProxy } +// NewFromAPISource returns a serverless serving instance built from GitLab API +// response +func NewFromAPISource(config api.Serverless) (serving.Serving, error) { + function := Function(config.Function) + + if len(function.Name) == 0 { + return nil, errors.New("incomplete serverless serving config") + } + + certs, err := NewClusterCerts( + config.Cluster.CertificateCert, + config.Cluster.CertificateKey, + ) + if err != nil { + return nil, err + } + + cluster := Cluster{ + Name: config.Cluster.Hostname, + Address: config.Cluster.Address, + Port: config.Cluster.Port, + Certs: certs, + } + + return New(function, cluster), nil +} + // New returns a new serving instance func New(function Function, cluster Cluster) serving.Serving { proxy := httputil.ReverseProxy{ diff --git a/internal/serving/serverless/serverless_test.go b/internal/serving/serverless/serverless_test.go index c330cbda..2dd933cc 100644 --- a/internal/serving/serverless/serverless_test.go +++ b/internal/serving/serverless/serverless_test.go @@ -40,9 +40,9 @@ func TestServeFileHTTP(t *testing.T) { withTestCluster(t, fixture.Certificate, fixture.Key, func(mux *http.ServeMux, server *url.URL, certs *Certs) { serverless := New( Function{ - Name: "my-func", - Namespace: "my-namespace-123", - BaseDomain: "knative.example.com", + Name: "my-func", + Namespace: "my-namespace-123", + Domain: "knative.example.com", }, Cluster{ Name: "knative.gitlab-example.com", @@ -76,9 +76,9 @@ func TestServeFileHTTP(t *testing.T) { withTestCluster(t, fixture.Certificate, fixture.Key, func(mux *http.ServeMux, server *url.URL, certs *Certs) { serverless := New( Function{ - Name: "my-func", - Namespace: "my-namespace-123", - BaseDomain: "knative.example.com", + Name: "my-func", + Namespace: "my-namespace-123", + Domain: "knative.example.com", }, Cluster{ Name: "knative.invalid-gitlab-example.com", @@ -111,9 +111,9 @@ func TestServeFileHTTP(t *testing.T) { withTestCluster(t, fixture.Certificate, fixture.Key, func(mux *http.ServeMux, server *url.URL, certs *Certs) { serverless := New( Function{ - Name: "my-func", - Namespace: "my-namespace-123", - BaseDomain: "knative.example.com", + Name: "my-func", + Namespace: "my-namespace-123", + Domain: "knative.example.com", }, Cluster{ Name: "knative.gitlab-example.com", @@ -147,9 +147,9 @@ func TestServeFileHTTP(t *testing.T) { withTestCluster(t, fixture.Certificate, fixture.Key, func(mux *http.ServeMux, server *url.URL, certs *Certs) { serverless := New( Function{ - Name: "my-func", - Namespace: "my-namespace-123", - BaseDomain: "knative.example.com", + Name: "my-func", + Namespace: "my-namespace-123", + Domain: "knative.example.com", }, Cluster{ Name: "knative.gitlab-example.com", diff --git a/internal/source/disk/custom.go b/internal/source/disk/custom.go index cc4f3f4c..2668ed81 100644 --- a/internal/source/disk/custom.go +++ b/internal/source/disk/custom.go @@ -4,6 +4,7 @@ import ( "net/http" "gitlab.com/gitlab-org/gitlab-pages/internal/serving" + "gitlab.com/gitlab-org/gitlab-pages/internal/serving/disk" ) type customProjectResolver struct { @@ -12,7 +13,7 @@ type customProjectResolver struct { path string } -func (p *customProjectResolver) Resolve(r *http.Request) (*serving.LookupPath, string, error) { +func (p *customProjectResolver) Resolve(r *http.Request) (*serving.Request, error) { lookupPath := &serving.LookupPath{ Prefix: "/", Path: p.path, @@ -22,5 +23,9 @@ func (p *customProjectResolver) Resolve(r *http.Request) (*serving.LookupPath, s ProjectID: p.config.ID, } - return lookupPath, r.URL.Path, nil + return &serving.Request{ + Serving: disk.New(), + LookupPath: lookupPath, + SubPath: r.URL.Path, + }, nil } diff --git a/internal/source/disk/group.go b/internal/source/disk/group.go index 9f466bc4..e0365bbd 100644 --- a/internal/source/disk/group.go +++ b/internal/source/disk/group.go @@ -8,6 +8,7 @@ import ( "gitlab.com/gitlab-org/gitlab-pages/internal/host" "gitlab.com/gitlab-org/gitlab-pages/internal/serving" + "gitlab.com/gitlab-org/gitlab-pages/internal/serving/disk" ) const ( @@ -77,11 +78,13 @@ func (g *Group) getProjectConfigWithSubpath(r *http.Request) (*projectConfig, st // Resolve tries to find project and its config recursively for a given request // to a group domain -func (g *Group) Resolve(r *http.Request) (*serving.LookupPath, string, error) { +func (g *Group) Resolve(r *http.Request) (*serving.Request, error) { projectConfig, prefix, projectPath, subPath := g.getProjectConfigWithSubpath(r) if projectConfig == nil { - return nil, "", nil // it is not an error when project does not exist + // it is not an error when project does not exist, in that case + // serving.Request.LookupPath is nil. + return &serving.Request{Serving: disk.New()}, nil } lookupPath := &serving.LookupPath{ @@ -93,5 +96,9 @@ func (g *Group) Resolve(r *http.Request) (*serving.LookupPath, string, error) { ProjectID: projectConfig.ID, } - return lookupPath, subPath, nil + return &serving.Request{ + Serving: disk.New(), + LookupPath: lookupPath, + SubPath: subPath, + }, nil } diff --git a/internal/source/gitlab/api/lookup_path.go b/internal/source/gitlab/api/lookup_path.go index b0407638..de200e37 100644 --- a/internal/source/gitlab/api/lookup_path.go +++ b/internal/source/gitlab/api/lookup_path.go @@ -6,8 +6,32 @@ type LookupPath struct { AccessControl bool `json:"access_control,omitempty"` HTTPSOnly bool `json:"https_only,omitempty"` Prefix string `json:"prefix,omitempty"` - Source struct { - Type string `json:"type,omitempty"` - Path string `json:"path,omitempty"` - } + Source Source `json:"source,omitempty"` +} + +// Source describes GitLab Page serving variant +type Source struct { + Type string `json:"type,omitempty"` + Path string `json:"path,omitempty"` + Serverless Serverless `json:"serverless,omitempty"` +} + +// Serverless describeg serverless serving configuration +type Serverless struct { + Function function `json:"function,omitempty"` + Cluster cluster `json:"cluster,omitempty"` +} + +type function struct { + Name string `json:"name,omitempty"` + Domain string `json:"domain,omitempty"` + Namespace string `json:"namespace,omitempty"` +} + +type cluster struct { + Address string `json:"address,omitempty"` + Port string `json:"port,omitempty"` + Hostname string `json:"hostname,omitempty"` + CertificateCert string `json:"cert,omitempty"` + CertificateKey string `json:"key,omitempty"` } diff --git a/internal/source/gitlab/factory/lookup.go b/internal/source/gitlab/factory/lookup.go new file mode 100644 index 00000000..71bb24bc --- /dev/null +++ b/internal/source/gitlab/factory/lookup.go @@ -0,0 +1,22 @@ +package factory + +import ( + "strings" + + "gitlab.com/gitlab-org/gitlab-pages/internal/serving" + "gitlab.com/gitlab-org/gitlab-pages/internal/source/gitlab/api" +) + +// LookupPath fabricates a serving LookupPath based on the API LookupPath +// `size` argument is DEPRECATED, see +// https://gitlab.com/gitlab-org/gitlab-pages/issues/272 +func LookupPath(size int, lookup api.LookupPath) *serving.LookupPath { + return &serving.LookupPath{ + Prefix: lookup.Prefix, + Path: strings.TrimPrefix(lookup.Source.Path, "/"), + IsNamespaceProject: (lookup.Prefix == "/" && size > 1), + IsHTTPSOnly: lookup.HTTPSOnly, + HasAccessControl: lookup.AccessControl, + ProjectID: uint64(lookup.ProjectID), + } +} diff --git a/internal/source/gitlab/factory/serving.go b/internal/source/gitlab/factory/serving.go new file mode 100644 index 00000000..22b99bc1 --- /dev/null +++ b/internal/source/gitlab/factory/serving.go @@ -0,0 +1,34 @@ +package factory + +import ( + "gitlab.com/gitlab-org/gitlab-pages/internal/serving" + "gitlab.com/gitlab-org/gitlab-pages/internal/serving/disk" + "gitlab.com/gitlab-org/gitlab-pages/internal/serving/serverless" + "gitlab.com/gitlab-org/gitlab-pages/internal/source/gitlab/api" +) + +// Serving fabricates serving based on the GitLab API response +func Serving(lookup api.LookupPath) serving.Serving { + source := lookup.Source + + switch source.Type { + case "file": + return disk.New() + case "serverless": + serving, err := serverless.NewFromAPISource(source.Serverless) + if err != nil { + break + } + + return serving + } + + return DefaultServing() +} + +// DefaultServing returns a serving that we will use as a default one, for +// example to show an error, if API response does not allow us to properly +// fabricate a serving +func DefaultServing() serving.Serving { + return disk.New() +} diff --git a/internal/source/gitlab/gitlab.go b/internal/source/gitlab/gitlab.go index cce70733..67198232 100644 --- a/internal/source/gitlab/gitlab.go +++ b/internal/source/gitlab/gitlab.go @@ -13,6 +13,7 @@ import ( "gitlab.com/gitlab-org/gitlab-pages/internal/source/gitlab/api" "gitlab.com/gitlab-org/gitlab-pages/internal/source/gitlab/cache" "gitlab.com/gitlab-org/gitlab-pages/internal/source/gitlab/client" + "gitlab.com/gitlab-org/gitlab-pages/internal/source/gitlab/factory" ) // Gitlab source represent a new domains configuration source. We fetch all the @@ -45,6 +46,8 @@ func (g *Gitlab) GetDomain(name string) (*domain.Domain, error) { return nil, nil } + // TODO introduce a second-level cache for domains, invalidate using etags + // from first-level cache domain := domain.Domain{ Name: name, CertificateCert: lookup.Domain.Certificate, @@ -55,40 +58,37 @@ func (g *Gitlab) GetDomain(name string) (*domain.Domain, error) { return &domain, nil } -// Resolve is supposed to get the serving lookup path based on the request from -// the GitLab source -func (g *Gitlab) Resolve(r *http.Request) (*serving.LookupPath, string, error) { +// Resolve is supposed to return the serving request containing lookup path, +// subpath for a given lookup and the serving itself created based on a request +// from GitLab pages domains source +func (g *Gitlab) Resolve(r *http.Request) (*serving.Request, error) { host := request.GetHostWithoutPort(r) response := g.client.Resolve(r.Context(), host) if response.Error != nil { - return nil, "", response.Error + return nil, response.Error } urlPath := path.Clean(r.URL.Path) + size := len(response.Domain.LookupPaths) for _, lookup := range response.Domain.LookupPaths { isSubPath := strings.HasPrefix(urlPath, lookup.Prefix) isRootPath := urlPath == path.Clean(lookup.Prefix) if isSubPath || isRootPath { - lookupPath := &serving.LookupPath{ - Prefix: lookup.Prefix, - Path: strings.TrimPrefix(lookup.Source.Path, "/"), - IsNamespaceProject: (lookup.Prefix == "/" && len(response.Domain.LookupPaths) > 1), - IsHTTPSOnly: lookup.HTTPSOnly, - HasAccessControl: lookup.AccessControl, - ProjectID: uint64(lookup.ProjectID), - } - subPath := "" if isSubPath { subPath = strings.TrimPrefix(urlPath, lookup.Prefix) } - return lookupPath, subPath, nil + return &serving.Request{ + Serving: factory.Serving(lookup), + LookupPath: factory.LookupPath(size, lookup), + SubPath: subPath}, nil } } - return nil, "", errors.New("could not match lookup path") + return &serving.Request{Serving: factory.DefaultServing()}, + errors.New("could not match lookup path") } diff --git a/internal/source/gitlab/gitlab_test.go b/internal/source/gitlab/gitlab_test.go index 0e855f10..e6f194ee 100644 --- a/internal/source/gitlab/gitlab_test.go +++ b/internal/source/gitlab/gitlab_test.go @@ -39,62 +39,62 @@ func TestResolve(t *testing.T) { target := "https://test.gitlab.io:443/my/pages/project/" request := httptest.NewRequest("GET", target, nil) - lookup, subpath, err := source.Resolve(request) + response, err := source.Resolve(request) require.NoError(t, err) - require.Equal(t, "/my/pages/project/", lookup.Prefix) - require.Equal(t, "some/path/to/project/", lookup.Path) - require.Equal(t, "", subpath) - require.False(t, lookup.IsNamespaceProject) + require.Equal(t, "/my/pages/project/", response.LookupPath.Prefix) + require.Equal(t, "some/path/to/project/", response.LookupPath.Path) + require.Equal(t, "", response.SubPath) + require.False(t, response.LookupPath.IsNamespaceProject) }) t.Run("when requesting a nested group project with full path", func(t *testing.T) { target := "https://test.gitlab.io:443/my/pages/project/path/index.html" request := httptest.NewRequest("GET", target, nil) - lookup, subpath, err := source.Resolve(request) + response, err := source.Resolve(request) require.NoError(t, err) - require.Equal(t, "/my/pages/project/", lookup.Prefix) - require.Equal(t, "some/path/to/project/", lookup.Path) - require.Equal(t, "path/index.html", subpath) - require.False(t, lookup.IsNamespaceProject) + require.Equal(t, "/my/pages/project/", response.LookupPath.Prefix) + require.Equal(t, "some/path/to/project/", response.LookupPath.Path) + require.Equal(t, "path/index.html", response.SubPath) + require.False(t, response.LookupPath.IsNamespaceProject) }) t.Run("when requesting the group root project with root path", func(t *testing.T) { target := "https://test.gitlab.io:443/" request := httptest.NewRequest("GET", target, nil) - lookup, subpath, err := source.Resolve(request) + response, err := source.Resolve(request) require.NoError(t, err) - require.Equal(t, "/", lookup.Prefix) - require.Equal(t, "some/path/to/project-3/", lookup.Path) - require.Equal(t, "", subpath) - require.True(t, lookup.IsNamespaceProject) + require.Equal(t, "/", response.LookupPath.Prefix) + require.Equal(t, "some/path/to/project-3/", response.LookupPath.Path) + require.Equal(t, "", response.SubPath) + require.True(t, response.LookupPath.IsNamespaceProject) }) t.Run("when requesting the group root project with full path", func(t *testing.T) { target := "https://test.gitlab.io:443/path/to/index.html" request := httptest.NewRequest("GET", target, nil) - lookup, subpath, err := source.Resolve(request) + response, err := source.Resolve(request) require.NoError(t, err) - require.Equal(t, "/", lookup.Prefix) - require.Equal(t, "path/to/index.html", subpath) - require.Equal(t, "some/path/to/project-3/", lookup.Path) - require.True(t, lookup.IsNamespaceProject) + require.Equal(t, "/", response.LookupPath.Prefix) + require.Equal(t, "path/to/index.html", response.SubPath) + require.Equal(t, "some/path/to/project-3/", response.LookupPath.Path) + require.True(t, response.LookupPath.IsNamespaceProject) }) t.Run("when request path has not been sanitized", func(t *testing.T) { target := "https://test.gitlab.io:443/something/../something/../my/pages/project/index.html" request := httptest.NewRequest("GET", target, nil) - lookup, subpath, err := source.Resolve(request) + response, err := source.Resolve(request) require.NoError(t, err) - require.Equal(t, "/my/pages/project/", lookup.Prefix) - require.Equal(t, "index.html", subpath) + require.Equal(t, "/my/pages/project/", response.LookupPath.Prefix) + require.Equal(t, "index.html", response.SubPath) }) } |