2

私はGo Webサーバーを介してWebコンテンツを提供しており、正規表現を使用してハンドラーをリクエストパスに一致させています。以下のこのテスト コードに希釈した非常に奇妙な動作に気付きました。基本的に、8 つの文字と数字の組み合わせはハンドラーによってキャッチされることを意図しており、その他の特定の要求パスは他のハンドラーによってキャッチされることを意図しています。これは、8 文字/数字のパスの場合、文字シーケンスが小文字の「c」で終わる場合、最初のハンドラーによって一致が取得されるため、うまく機能します。最後の他の文字は正常に機能します。

以下のコードは、ファイルに貼り付けて実行できます。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)
}

このリクエストは、2 番目のハンドラ (runTest3) によって取得されます。

http://localhost:8080/all

このリクエストは、URL のパス部分を出力する 3 番目のハンドラー (runTest) によって取得されます。

http://localhost:8080/yr22FBMD.

ただし、このリクエストは最初のハンドラーによって取得されます (小文字の c で終わることに注意してください)。

http://localhost:8080/yr22FBMc

何か案は?これは非常に奇妙です!

4

1 に答える 1

10

runTest2 の括弧内に拡張機能があります。これにより文字クラスになるため、正規表現は「「(」「c」、「s」、「|」、「j」、「p」、「g」、「n」、「t」の任意の行に一致します'、'f'、'i'、'o'、または ')' を最後の文字として使用します。

角かっこを削除するだけで、最初のピリオドをエスケープするつもりだと思います。

"\.(css|jpg|png|js|ttf|ico)$"
于 2013-05-17T20:38:56.180 に答える