路由http请求时,奇怪的Go正则表达式不匹配

时间:2013-05-17 20:24:20

标签: regex go

我通过Go Web服务器提供Web内容,并使用正则表达式将处理程序与请求路径进行匹配。我注意到一个非常奇怪的行为,我已经将其稀释到下面的测试代码中。 基本上,任何8个字母/数字组合都意味着被处理程序捕获,而其他特定请求路径意味着被其他处理程序捕获。如果字母序列以小写字母'c'结尾,则在第8个字母/数字路径的情况下,第一个处理程序拾取匹配,这很有效。最后的任何其他字母都可以正常工作。

以下代码可以粘贴到文件中并运行。它将在localhost上发布:8080。我已经提供了一些请求链接来演示这个问题。

package main

import (
    "fmt"
    "net/http" 
    "regexp"
) 

// This is the handler when passing a string of 8 characters ([])
func runTest(w http.ResponseWriter, r *http.Request) {
    path := r.URL.Path[1:]
    fmt.Fprintf(w, path)
} 

func runTest2(w http.ResponseWriter, r *http.Request) {
    path := "Reg ex for: .[(css|jpg|png|js|ttf|ico)]$" 
    fmt.Fprintf(w, path)
} 

func runTest3(w http.ResponseWriter, r *http.Request) {
    path := "Reg ex for: /all$" 
    fmt.Fprintf(w, path)
} 

// Regular expression handler
type route struct {
    pattern *regexp.Regexp
    handler http.Handler
}

type RegexpHandler struct {
    routes []*route
}

func (h *RegexpHandler) Handler(pattern *regexp.Regexp, handler http.Handler) {
    h.routes = append(h.routes, &route{pattern, handler})
}

func (h *RegexpHandler) HandleFunc(pattern *regexp.Regexp, handler func(http.ResponseWriter, *http.Request)) {
    h.routes = append(h.routes, &route{pattern, http.HandlerFunc(handler)})
}

func (h *RegexpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    for _, route := range h.routes {
        if route.pattern.MatchString(r.URL.Path) {
            route.handler.ServeHTTP(w, r)
            return
        }
    }
    http.NotFound(w, r)

}

func main() {
    handler := &RegexpHandler{} 
     handler.HandleFunc(regexp.MustCompile(`.[(css|jpg|png|js|ttf|ico)]$`), runTest2)
     handler.HandleFunc(regexp.MustCompile("^/all$"), runTest3) 
    handler.HandleFunc(regexp.MustCompile("^/[A-Z0-9a-z]{8}$"), runTest)  
    http.ListenAndServe(":8080", handler)
}

第二个处理程序(runTest3)获取此请求:

http://localhost:8080/all

此请求被第三个处理程序(runTest)拾取,该处理程序打印出url的路径部分:

http://localhost:8080/yr22FBMD.

然而,这个请求被第一个处理程序拾取(注意它以小写c结尾):

http://localhost:8080/yr22FBMc

有什么想法吗?这非常奇怪!

1 个答案:

答案 0 :(得分:10)

runTest2中的括号内有扩展名。这使得它成为一个角色类,所以你的正则表达式是“匹配任何一行'(''c','s','|','j','p','g','n','t ','f','i','o'或')'作为最后一个字符。

你只需要删除sqaure括号,我认为你的意思是在开始时逃避这段时间。

"\.(css|jpg|png|js|ttf|ico)$"