diff options
Diffstat (limited to 'vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/regexp.go')
-rw-r--r-- | vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/regexp.go | 317 |
1 files changed, 0 insertions, 317 deletions
diff --git a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/regexp.go b/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/regexp.go deleted file mode 100644 index 06728dd..0000000 --- a/vendor/github.com/fsouza/go-dockerclient/external/github.com/gorilla/mux/regexp.go +++ /dev/null | |||
@@ -1,317 +0,0 @@ | |||
1 | // Copyright 2012 The Gorilla Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package mux | ||
6 | |||
7 | import ( | ||
8 | "bytes" | ||
9 | "fmt" | ||
10 | "net/http" | ||
11 | "net/url" | ||
12 | "regexp" | ||
13 | "strconv" | ||
14 | "strings" | ||
15 | ) | ||
16 | |||
17 | // newRouteRegexp parses a route template and returns a routeRegexp, | ||
18 | // used to match a host, a path or a query string. | ||
19 | // | ||
20 | // It will extract named variables, assemble a regexp to be matched, create | ||
21 | // a "reverse" template to build URLs and compile regexps to validate variable | ||
22 | // values used in URL building. | ||
23 | // | ||
24 | // Previously we accepted only Python-like identifiers for variable | ||
25 | // names ([a-zA-Z_][a-zA-Z0-9_]*), but currently the only restriction is that | ||
26 | // name and pattern can't be empty, and names can't contain a colon. | ||
27 | func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash bool) (*routeRegexp, error) { | ||
28 | // Check if it is well-formed. | ||
29 | idxs, errBraces := braceIndices(tpl) | ||
30 | if errBraces != nil { | ||
31 | return nil, errBraces | ||
32 | } | ||
33 | // Backup the original. | ||
34 | template := tpl | ||
35 | // Now let's parse it. | ||
36 | defaultPattern := "[^/]+" | ||
37 | if matchQuery { | ||
38 | defaultPattern = "[^?&]*" | ||
39 | } else if matchHost { | ||
40 | defaultPattern = "[^.]+" | ||
41 | matchPrefix = false | ||
42 | } | ||
43 | // Only match strict slash if not matching | ||
44 | if matchPrefix || matchHost || matchQuery { | ||
45 | strictSlash = false | ||
46 | } | ||
47 | // Set a flag for strictSlash. | ||
48 | endSlash := false | ||
49 | if strictSlash && strings.HasSuffix(tpl, "/") { | ||
50 | tpl = tpl[:len(tpl)-1] | ||
51 | endSlash = true | ||
52 | } | ||
53 | varsN := make([]string, len(idxs)/2) | ||
54 | varsR := make([]*regexp.Regexp, len(idxs)/2) | ||
55 | pattern := bytes.NewBufferString("") | ||
56 | pattern.WriteByte('^') | ||
57 | reverse := bytes.NewBufferString("") | ||
58 | var end int | ||
59 | var err error | ||
60 | for i := 0; i < len(idxs); i += 2 { | ||
61 | // Set all values we are interested in. | ||
62 | raw := tpl[end:idxs[i]] | ||
63 | end = idxs[i+1] | ||
64 | parts := strings.SplitN(tpl[idxs[i]+1:end-1], ":", 2) | ||
65 | name := parts[0] | ||
66 | patt := defaultPattern | ||
67 | if len(parts) == 2 { | ||
68 | patt = parts[1] | ||
69 | } | ||
70 | // Name or pattern can't be empty. | ||
71 | if name == "" || patt == "" { | ||
72 | return nil, fmt.Errorf("mux: missing name or pattern in %q", | ||
73 | tpl[idxs[i]:end]) | ||
74 | } | ||
75 | // Build the regexp pattern. | ||
76 | varIdx := i / 2 | ||
77 | fmt.Fprintf(pattern, "%s(?P<%s>%s)", regexp.QuoteMeta(raw), varGroupName(varIdx), patt) | ||
78 | // Build the reverse template. | ||
79 | fmt.Fprintf(reverse, "%s%%s", raw) | ||
80 | |||
81 | // Append variable name and compiled pattern. | ||
82 | varsN[varIdx] = name | ||
83 | varsR[varIdx], err = regexp.Compile(fmt.Sprintf("^%s$", patt)) | ||
84 | if err != nil { | ||
85 | return nil, err | ||
86 | } | ||
87 | } | ||
88 | // Add the remaining. | ||
89 | raw := tpl[end:] | ||
90 | pattern.WriteString(regexp.QuoteMeta(raw)) | ||
91 | if strictSlash { | ||
92 | pattern.WriteString("[/]?") | ||
93 | } | ||
94 | if matchQuery { | ||
95 | // Add the default pattern if the query value is empty | ||
96 | if queryVal := strings.SplitN(template, "=", 2)[1]; queryVal == "" { | ||
97 | pattern.WriteString(defaultPattern) | ||
98 | } | ||
99 | } | ||
100 | if !matchPrefix { | ||
101 | pattern.WriteByte('$') | ||
102 | } | ||
103 | reverse.WriteString(raw) | ||
104 | if endSlash { | ||
105 | reverse.WriteByte('/') | ||
106 | } | ||
107 | // Compile full regexp. | ||
108 | reg, errCompile := regexp.Compile(pattern.String()) | ||
109 | if errCompile != nil { | ||
110 | return nil, errCompile | ||
111 | } | ||
112 | // Done! | ||
113 | return &routeRegexp{ | ||
114 | template: template, | ||
115 | matchHost: matchHost, | ||
116 | matchQuery: matchQuery, | ||
117 | strictSlash: strictSlash, | ||
118 | regexp: reg, | ||
119 | reverse: reverse.String(), | ||
120 | varsN: varsN, | ||
121 | varsR: varsR, | ||
122 | }, nil | ||
123 | } | ||
124 | |||
125 | // routeRegexp stores a regexp to match a host or path and information to | ||
126 | // collect and validate route variables. | ||
127 | type routeRegexp struct { | ||
128 | // The unmodified template. | ||
129 | template string | ||
130 | // True for host match, false for path or query string match. | ||
131 | matchHost bool | ||
132 | // True for query string match, false for path and host match. | ||
133 | matchQuery bool | ||
134 | // The strictSlash value defined on the route, but disabled if PathPrefix was used. | ||
135 | strictSlash bool | ||
136 | // Expanded regexp. | ||
137 | regexp *regexp.Regexp | ||
138 | // Reverse template. | ||
139 | reverse string | ||
140 | // Variable names. | ||
141 | varsN []string | ||
142 | // Variable regexps (validators). | ||
143 | varsR []*regexp.Regexp | ||
144 | } | ||
145 | |||
146 | // Match matches the regexp against the URL host or path. | ||
147 | func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool { | ||
148 | if !r.matchHost { | ||
149 | if r.matchQuery { | ||
150 | return r.matchQueryString(req) | ||
151 | } else { | ||
152 | return r.regexp.MatchString(req.URL.Path) | ||
153 | } | ||
154 | } | ||
155 | return r.regexp.MatchString(getHost(req)) | ||
156 | } | ||
157 | |||
158 | // url builds a URL part using the given values. | ||
159 | func (r *routeRegexp) url(values map[string]string) (string, error) { | ||
160 | urlValues := make([]interface{}, len(r.varsN)) | ||
161 | for k, v := range r.varsN { | ||
162 | value, ok := values[v] | ||
163 | if !ok { | ||
164 | return "", fmt.Errorf("mux: missing route variable %q", v) | ||
165 | } | ||
166 | urlValues[k] = value | ||
167 | } | ||
168 | rv := fmt.Sprintf(r.reverse, urlValues...) | ||
169 | if !r.regexp.MatchString(rv) { | ||
170 | // The URL is checked against the full regexp, instead of checking | ||
171 | // individual variables. This is faster but to provide a good error | ||
172 | // message, we check individual regexps if the URL doesn't match. | ||
173 | for k, v := range r.varsN { | ||
174 | if !r.varsR[k].MatchString(values[v]) { | ||
175 | return "", fmt.Errorf( | ||
176 | "mux: variable %q doesn't match, expected %q", values[v], | ||
177 | r.varsR[k].String()) | ||
178 | } | ||
179 | } | ||
180 | } | ||
181 | return rv, nil | ||
182 | } | ||
183 | |||
184 | // getUrlQuery returns a single query parameter from a request URL. | ||
185 | // For a URL with foo=bar&baz=ding, we return only the relevant key | ||
186 | // value pair for the routeRegexp. | ||
187 | func (r *routeRegexp) getUrlQuery(req *http.Request) string { | ||
188 | if !r.matchQuery { | ||
189 | return "" | ||
190 | } | ||
191 | templateKey := strings.SplitN(r.template, "=", 2)[0] | ||
192 | for key, vals := range req.URL.Query() { | ||
193 | if key == templateKey && len(vals) > 0 { | ||
194 | return key + "=" + vals[0] | ||
195 | } | ||
196 | } | ||
197 | return "" | ||
198 | } | ||
199 | |||
200 | func (r *routeRegexp) matchQueryString(req *http.Request) bool { | ||
201 | return r.regexp.MatchString(r.getUrlQuery(req)) | ||
202 | } | ||
203 | |||
204 | // braceIndices returns the first level curly brace indices from a string. | ||
205 | // It returns an error in case of unbalanced braces. | ||
206 | func braceIndices(s string) ([]int, error) { | ||
207 | var level, idx int | ||
208 | idxs := make([]int, 0) | ||
209 | for i := 0; i < len(s); i++ { | ||
210 | switch s[i] { | ||
211 | case '{': | ||
212 | if level++; level == 1 { | ||
213 | idx = i | ||
214 | } | ||
215 | case '}': | ||
216 | if level--; level == 0 { | ||
217 | idxs = append(idxs, idx, i+1) | ||
218 | } else if level < 0 { | ||
219 | return nil, fmt.Errorf("mux: unbalanced braces in %q", s) | ||
220 | } | ||
221 | } | ||
222 | } | ||
223 | if level != 0 { | ||
224 | return nil, fmt.Errorf("mux: unbalanced braces in %q", s) | ||
225 | } | ||
226 | return idxs, nil | ||
227 | } | ||
228 | |||
229 | // varGroupName builds a capturing group name for the indexed variable. | ||
230 | func varGroupName(idx int) string { | ||
231 | return "v" + strconv.Itoa(idx) | ||
232 | } | ||
233 | |||
234 | // ---------------------------------------------------------------------------- | ||
235 | // routeRegexpGroup | ||
236 | // ---------------------------------------------------------------------------- | ||
237 | |||
238 | // routeRegexpGroup groups the route matchers that carry variables. | ||
239 | type routeRegexpGroup struct { | ||
240 | host *routeRegexp | ||
241 | path *routeRegexp | ||
242 | queries []*routeRegexp | ||
243 | } | ||
244 | |||
245 | // setMatch extracts the variables from the URL once a route matches. | ||
246 | func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) { | ||
247 | // Store host variables. | ||
248 | if v.host != nil { | ||
249 | hostVars := v.host.regexp.FindStringSubmatch(getHost(req)) | ||
250 | if hostVars != nil { | ||
251 | subexpNames := v.host.regexp.SubexpNames() | ||
252 | varName := 0 | ||
253 | for i, name := range subexpNames[1:] { | ||
254 | if name != "" && name == varGroupName(varName) { | ||
255 | m.Vars[v.host.varsN[varName]] = hostVars[i+1] | ||
256 | varName++ | ||
257 | } | ||
258 | } | ||
259 | } | ||
260 | } | ||
261 | // Store path variables. | ||
262 | if v.path != nil { | ||
263 | pathVars := v.path.regexp.FindStringSubmatch(req.URL.Path) | ||
264 | if pathVars != nil { | ||
265 | subexpNames := v.path.regexp.SubexpNames() | ||
266 | varName := 0 | ||
267 | for i, name := range subexpNames[1:] { | ||
268 | if name != "" && name == varGroupName(varName) { | ||
269 | m.Vars[v.path.varsN[varName]] = pathVars[i+1] | ||
270 | varName++ | ||
271 | } | ||
272 | } | ||
273 | // Check if we should redirect. | ||
274 | if v.path.strictSlash { | ||
275 | p1 := strings.HasSuffix(req.URL.Path, "/") | ||
276 | p2 := strings.HasSuffix(v.path.template, "/") | ||
277 | if p1 != p2 { | ||
278 | u, _ := url.Parse(req.URL.String()) | ||
279 | if p1 { | ||
280 | u.Path = u.Path[:len(u.Path)-1] | ||
281 | } else { | ||
282 | u.Path += "/" | ||
283 | } | ||
284 | m.Handler = http.RedirectHandler(u.String(), 301) | ||
285 | } | ||
286 | } | ||
287 | } | ||
288 | } | ||
289 | // Store query string variables. | ||
290 | for _, q := range v.queries { | ||
291 | queryVars := q.regexp.FindStringSubmatch(q.getUrlQuery(req)) | ||
292 | if queryVars != nil { | ||
293 | subexpNames := q.regexp.SubexpNames() | ||
294 | varName := 0 | ||
295 | for i, name := range subexpNames[1:] { | ||
296 | if name != "" && name == varGroupName(varName) { | ||
297 | m.Vars[q.varsN[varName]] = queryVars[i+1] | ||
298 | varName++ | ||
299 | } | ||
300 | } | ||
301 | } | ||
302 | } | ||
303 | } | ||
304 | |||
305 | // getHost tries its best to return the request host. | ||
306 | func getHost(r *http.Request) string { | ||
307 | if r.URL.IsAbs() { | ||
308 | return r.URL.Host | ||
309 | } | ||
310 | host := r.Host | ||
311 | // Slice off any port information. | ||
312 | if i := strings.Index(host, ":"); i != -1 { | ||
313 | host = host[:i] | ||
314 | } | ||
315 | return host | ||
316 | |||
317 | } | ||