Skip to content

Commit

Permalink
Allow using subpath as a variable in repo
Browse files Browse the repository at this point in the history
  • Loading branch information
AlmogBaku committed Aug 20, 2018
1 parent 682d637 commit e7077b8
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 10 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,5 +120,10 @@ paths:
<td>required if ambiguous</td>
<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>
</tr>
<tr>
<th scope="row"><code>wildcard</code></th>
<td>optional</td>
<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>
</tr>
</tbody>
</table>
44 changes: 34 additions & 10 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"strings"

"gopkg.in/yaml.v2"
"regexp"
)

type handler struct {
Expand All @@ -33,6 +34,7 @@ type handler struct {
}

type pathConfig struct {
wildcard bool
path string
repo string
display string
Expand All @@ -45,6 +47,7 @@ func newHandler(config []byte) (*handler, error) {
CacheAge *int64 `yaml:"cache_max_age,omitempty"`
Paths map[string]struct {
Repo string `yaml:"repo,omitempty"`
Wildcard bool `yaml:"wildcard,omitempty"`
Display string `yaml:"display,omitempty"`
VCS string `yaml:"vcs,omitempty"`
} `yaml:"paths,omitempty"`
Expand All @@ -67,6 +70,7 @@ func newHandler(config []byte) (*handler, error) {
repo: e.Repo,
display: e.Display,
vcs: e.VCS,
wildcard: e.Wildcard,
}
switch {
case e.Display != "":
Expand Down Expand Up @@ -95,7 +99,7 @@ func newHandler(config []byte) (*handler, error) {

func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
current := r.URL.Path
pc, subpath := h.paths.find(current)
pc, subpath, wildcard := h.paths.find(current)
if pc == nil && current == "/" {
h.serveIndex(w, r)
return
Expand All @@ -105,6 +109,11 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}

importPath := h.Host(r) + pc.path
if wildcard != "" {
importPath += "/" + wildcard
}

w.Header().Set("Cache-Control", h.cacheControl)
if err := vanityTmpl.Execute(w, struct {
Import string
Expand All @@ -113,10 +122,10 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
Display string
VCS string
}{
Import: h.Host(r) + pc.path,
Import: importPath,
Subpath: subpath,
Repo: pc.repo,
Display: pc.display,
Repo: strings.Replace(pc.repo, "*", wildcard, -1),
Display: strings.Replace(pc.display, "*", wildcard, -1),
VCS: pc.vcs,
}); err != nil {
http.Error(w, "cannot render the page", http.StatusInternalServerError)
Expand Down Expand Up @@ -184,17 +193,14 @@ func (pset pathConfigSet) Swap(i, j int) {
pset[i], pset[j] = pset[j], pset[i]
}

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

// Slow path, now looking for the longest prefix/shortest subpath i.e.
Expand All @@ -214,12 +220,30 @@ func (pset pathConfigSet) find(path string) (pc *pathConfig, subpath string) {
// route with equal or greater length is NOT a match.
continue
}

if ps.wildcard {
p := ps.path
if !strings.HasSuffix(p, "/") {
p += "/"
}
regex := "^" + strings.Replace(p, "/", "\\/", -1) + "(.+)=?"
r := regexp.MustCompile(regex)
finds := r.FindStringSubmatch(path)
if finds != nil {
parts := strings.SplitN(finds[1], "/", 2)
if len(parts) > 1 {
return &pset[i], parts[1], parts[0]
}
return &pset[i], "", parts[0]
}
}

sSubpath := strings.TrimPrefix(path, ps.path)
if len(sSubpath) < lenShortestSubpath {
subpath = sSubpath
lenShortestSubpath = len(sSubpath)
bestMatchConfig = &pset[i]
}
}
return bestMatchConfig, subpath
return bestMatchConfig, subpath, ""
}
4 changes: 4 additions & 0 deletions vanity.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ paths:

/launchpad:
repo: https://github.com/rakyll/launchpad

/opencensus/:
wildcard: true
repo: https://github.com/rakyll/opencensus-*

0 comments on commit e7077b8

Please sign in to comment.