1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
package gitlab
import (
"context"
"errors"
"net/http"
"path"
"strings"
"gitlab.com/gitlab-org/gitlab-pages/internal/domain"
"gitlab.com/gitlab-org/gitlab-pages/internal/request"
"gitlab.com/gitlab-org/gitlab-pages/internal/serving"
"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 source represent a new domains configuration source. We fetch all the
// information about domains from GitLab instance.
type Gitlab struct {
client api.Resolver
}
// New returns a new instance of gitlab domain source.
func New(config client.Config) (*Gitlab, error) {
client, err := client.NewFromConfig(config)
if err != nil {
return nil, err
}
return &Gitlab{client: cache.NewCache(client)}, nil
}
// GetDomain return a representation of a domain that we have fetched from
// GitLab
func (g *Gitlab) GetDomain(name string) (*domain.Domain, error) {
lookup := g.client.Resolve(context.Background(), name)
if lookup.Error != nil {
return nil, lookup.Error
}
// Domain does not exist
if lookup.Domain == nil {
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,
CertificateKey: lookup.Domain.Key,
Resolver: g,
}
return &domain, nil
}
// 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 &serving.Request{Serving: defaultServing()}, 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 {
subPath := ""
if isSubPath {
subPath = strings.TrimPrefix(urlPath, lookup.Prefix)
}
return &serving.Request{
Serving: fabricateServing(lookup),
LookupPath: fabricateLookupPath(size, lookup),
SubPath: subPath}, nil
}
}
// TODO improve code around default serving, when `disk` serving gets removed
// https://gitlab.com/gitlab-org/gitlab-pages/issues/353
return &serving.Request{Serving: defaultServing()},
errors.New("could not match lookup path")
}
|