Skip to content

Commit e7077b8

Browse files
committed
Allow using subpath as a variable in repo
1 parent 682d637 commit e7077b8

File tree

3 files changed

+43
-10
lines changed

3 files changed

+43
-10
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,5 +120,10 @@ paths:
120120
<td>required if ambiguous</td>
121121
<td>If the version control system cannot be inferred (e.g. for Bitbucket or a custom domain), then this specifies the version control system as it would appear in <a href="https://golang.org/cmd/go/#hdr-Remote_import_paths"><code>go-import</code> meta tag</a>. This can be one of <code>git</code>, <code>hg</code>, <code>svn</code>, or <code>bzr</code>.</td>
122122
</tr>
123+
<tr>
124+
<th scope="row"><code>wildcard</code></th>
125+
<td>optional</td>
126+
<td>Boolean. If <code>true</code>, it allows you to use the <code>*</code> placeholder, for the first sub-path inside your <code>repo</code> or <code>display</code></code></td>
127+
</tr>
123128
</tbody>
124129
</table>

handler.go

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"strings"
2525

2626
"gopkg.in/yaml.v2"
27+
"regexp"
2728
)
2829

2930
type handler struct {
@@ -33,6 +34,7 @@ type handler struct {
3334
}
3435

3536
type pathConfig struct {
37+
wildcard bool
3638
path string
3739
repo string
3840
display string
@@ -45,6 +47,7 @@ func newHandler(config []byte) (*handler, error) {
4547
CacheAge *int64 `yaml:"cache_max_age,omitempty"`
4648
Paths map[string]struct {
4749
Repo string `yaml:"repo,omitempty"`
50+
Wildcard bool `yaml:"wildcard,omitempty"`
4851
Display string `yaml:"display,omitempty"`
4952
VCS string `yaml:"vcs,omitempty"`
5053
} `yaml:"paths,omitempty"`
@@ -67,6 +70,7 @@ func newHandler(config []byte) (*handler, error) {
6770
repo: e.Repo,
6871
display: e.Display,
6972
vcs: e.VCS,
73+
wildcard: e.Wildcard,
7074
}
7175
switch {
7276
case e.Display != "":
@@ -95,7 +99,7 @@ func newHandler(config []byte) (*handler, error) {
9599

96100
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
97101
current := r.URL.Path
98-
pc, subpath := h.paths.find(current)
102+
pc, subpath, wildcard := h.paths.find(current)
99103
if pc == nil && current == "/" {
100104
h.serveIndex(w, r)
101105
return
@@ -105,6 +109,11 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
105109
return
106110
}
107111

112+
importPath := h.Host(r) + pc.path
113+
if wildcard != "" {
114+
importPath += "/" + wildcard
115+
}
116+
108117
w.Header().Set("Cache-Control", h.cacheControl)
109118
if err := vanityTmpl.Execute(w, struct {
110119
Import string
@@ -113,10 +122,10 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
113122
Display string
114123
VCS string
115124
}{
116-
Import: h.Host(r) + pc.path,
125+
Import: importPath,
117126
Subpath: subpath,
118-
Repo: pc.repo,
119-
Display: pc.display,
127+
Repo: strings.Replace(pc.repo, "*", wildcard, -1),
128+
Display: strings.Replace(pc.display, "*", wildcard, -1),
120129
VCS: pc.vcs,
121130
}); err != nil {
122131
http.Error(w, "cannot render the page", http.StatusInternalServerError)
@@ -184,17 +193,14 @@ func (pset pathConfigSet) Swap(i, j int) {
184193
pset[i], pset[j] = pset[j], pset[i]
185194
}
186195

187-
func (pset pathConfigSet) find(path string) (pc *pathConfig, subpath string) {
196+
func (pset pathConfigSet) find(path string) (pc *pathConfig, subpath string, wildcard string) {
188197
// Fast path with binary search to retrieve exact matches
189198
// e.g. given pset ["/", "/abc", "/xyz"], path "/def" won't match.
190199
i := sort.Search(len(pset), func(i int) bool {
191200
return pset[i].path >= path
192201
})
193202
if i < len(pset) && pset[i].path == path {
194-
return &pset[i], ""
195-
}
196-
if i > 0 && strings.HasPrefix(path, pset[i-1].path+"/") {
197-
return &pset[i-1], path[len(pset[i-1].path)+1:]
203+
return &pset[i], "", ""
198204
}
199205

200206
// Slow path, now looking for the longest prefix/shortest subpath i.e.
@@ -214,12 +220,30 @@ func (pset pathConfigSet) find(path string) (pc *pathConfig, subpath string) {
214220
// route with equal or greater length is NOT a match.
215221
continue
216222
}
223+
224+
if ps.wildcard {
225+
p := ps.path
226+
if !strings.HasSuffix(p, "/") {
227+
p += "/"
228+
}
229+
regex := "^" + strings.Replace(p, "/", "\\/", -1) + "(.+)=?"
230+
r := regexp.MustCompile(regex)
231+
finds := r.FindStringSubmatch(path)
232+
if finds != nil {
233+
parts := strings.SplitN(finds[1], "/", 2)
234+
if len(parts) > 1 {
235+
return &pset[i], parts[1], parts[0]
236+
}
237+
return &pset[i], "", parts[0]
238+
}
239+
}
240+
217241
sSubpath := strings.TrimPrefix(path, ps.path)
218242
if len(sSubpath) < lenShortestSubpath {
219243
subpath = sSubpath
220244
lenShortestSubpath = len(sSubpath)
221245
bestMatchConfig = &pset[i]
222246
}
223247
}
224-
return bestMatchConfig, subpath
248+
return bestMatchConfig, subpath, ""
225249
}

vanity.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,7 @@ paths:
66

77
/launchpad:
88
repo: https://github.com/rakyll/launchpad
9+
10+
/opencensus/:
11+
wildcard: true
12+
repo: https://github.com/rakyll/opencensus-*

0 commit comments

Comments
 (0)