pip compatible server to serve Python packages out of GitHub
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

121 lines
2.5 KiB

package web
import (
"fmt"
"net/http"
"regexp"
"strings"
)
type regexpPattern struct {
re *regexp.Regexp
names []string
}
func (p regexpPattern) Prefix() string {
prefix, _ := p.re.LiteralPrefix()
return prefix
}
func (p regexpPattern) Match(r *http.Request, c *C) bool {
matches := p.re.FindStringSubmatch(r.URL.Path)
if matches == nil {
return false
}
if c.UrlParams == nil && len(matches) > 0 {
c.UrlParams = make(map[string]string, len(matches)-1)
}
for i := 1; i < len(matches); i++ {
c.UrlParams[p.names[i]] = matches[i]
}
return true
}
func parseRegexpPattern(re *regexp.Regexp) regexpPattern {
rnames := re.SubexpNames()
// We have to make our own copy since package regexp forbids us
// from scribbling over the slice returned by SubexpNames().
names := make([]string, len(rnames))
for i, rname := range rnames {
if rname == "" {
rname = fmt.Sprintf("$%d", i)
}
names[i] = rname
}
return regexpPattern{
re: re,
names: names,
}
}
type stringPattern struct {
raw string
pats []string
literals []string
isPrefix bool
}
func (s stringPattern) Prefix() string {
return s.literals[0]
}
func (s stringPattern) Match(r *http.Request, c *C) bool {
path := r.URL.Path
matches := make([]string, len(s.pats))
for i := 0; i < len(s.pats); i++ {
if !strings.HasPrefix(path, s.literals[i]) {
return false
}
path = path[len(s.literals[i]):]
m := strings.IndexRune(path, '/')
if m == -1 {
m = len(path)
}
if m == 0 {
// Empty strings are not matches, otherwise routes like
// "/:foo" would match the path "/"
return false
}
matches[i] = path[:m]
path = path[m:]
}
// There's exactly one more literal than pat.
if s.isPrefix {
if strings.HasPrefix(path, s.literals[len(s.pats)]) {
return false
}
} else {
if path != s.literals[len(s.pats)] {
return false
}
}
if c.UrlParams == nil && len(matches) > 0 {
c.UrlParams = make(map[string]string, len(matches)-1)
}
for i, match := range matches {
c.UrlParams[s.pats[i]] = match
}
return true
}
func parseStringPattern(s string, isPrefix bool) stringPattern {
matches := patternRe.FindAllStringSubmatchIndex(s, -1)
pats := make([]string, len(matches))
literals := make([]string, len(matches)+1)
n := 0
for i, match := range matches {
a, b := match[2], match[3]
literals[i] = s[n : a-1] // Need to leave off the colon
pats[i] = s[a:b]
n = b
}
literals[len(matches)] = s[n:]
return stringPattern{
raw: s,
pats: pats,
literals: literals,
isPrefix: isPrefix,
}
}