75 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			75 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package restful
 | |
| 
 | |
| // Copyright 2013 Ernest Micklei. All rights reserved.
 | |
| // Use of this source code is governed by a license
 | |
| // that can be found in the LICENSE file.
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"fmt"
 | |
| 	"regexp"
 | |
| 	"strings"
 | |
| )
 | |
| 
 | |
| // PathExpression holds a compiled path expression (RegExp) needed to match against
 | |
| // Http request paths and to extract path parameter values.
 | |
| type pathExpression struct {
 | |
| 	LiteralCount int      // the number of literal characters (means those not resulting from template variable substitution)
 | |
| 	VarNames     []string // the names of parameters (enclosed by {}) in the path
 | |
| 	VarCount     int      // the number of named parameters (enclosed by {}) in the path
 | |
| 	Matcher      *regexp.Regexp
 | |
| 	Source       string // Path as defined by the RouteBuilder
 | |
| 	tokens       []string
 | |
| }
 | |
| 
 | |
| // NewPathExpression creates a PathExpression from the input URL path.
 | |
| // Returns an error if the path is invalid.
 | |
| func newPathExpression(path string) (*pathExpression, error) {
 | |
| 	expression, literalCount, varNames, varCount, tokens := templateToRegularExpression(path)
 | |
| 	compiled, err := regexp.Compile(expression)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return &pathExpression{literalCount, varNames, varCount, compiled, expression, tokens}, nil
 | |
| }
 | |
| 
 | |
| // http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-370003.7.3
 | |
| func templateToRegularExpression(template string) (expression string, literalCount int, varNames []string, varCount int, tokens []string) {
 | |
| 	var buffer bytes.Buffer
 | |
| 	buffer.WriteString("^")
 | |
| 	//tokens = strings.Split(template, "/")
 | |
| 	tokens = tokenizePath(template)
 | |
| 	for _, each := range tokens {
 | |
| 		if each == "" {
 | |
| 			continue
 | |
| 		}
 | |
| 		buffer.WriteString("/")
 | |
| 		if strings.HasPrefix(each, "{") {
 | |
| 			// check for regular expression in variable
 | |
| 			colon := strings.Index(each, ":")
 | |
| 			var varName string
 | |
| 			if colon != -1 {
 | |
| 				// extract expression
 | |
| 				varName = strings.TrimSpace(each[1:colon])
 | |
| 				paramExpr := strings.TrimSpace(each[colon+1 : len(each)-1])
 | |
| 				if paramExpr == "*" { // special case
 | |
| 					buffer.WriteString("(.*)")
 | |
| 				} else {
 | |
| 					buffer.WriteString(fmt.Sprintf("(%s)", paramExpr)) // between colon and closing moustache
 | |
| 				}
 | |
| 			} else {
 | |
| 				// plain var
 | |
| 				varName = strings.TrimSpace(each[1 : len(each)-1])
 | |
| 				buffer.WriteString("([^/]+?)")
 | |
| 			}
 | |
| 			varNames = append(varNames, varName)
 | |
| 			varCount += 1
 | |
| 		} else {
 | |
| 			literalCount += len(each)
 | |
| 			encoded := each // TODO URI encode
 | |
| 			buffer.WriteString(regexp.QuoteMeta(encoded))
 | |
| 		}
 | |
| 	}
 | |
| 	return strings.TrimRight(buffer.String(), "/") + "(/.*)?$", literalCount, varNames, varCount, tokens
 | |
| }
 | 
