Подстановочные знаки в шаблоне для http.HandleFunc
при регистрации обработчиков в Go (язык) есть ли способ указать подстановочные знаки в шаблоне?
например:
http.HandleFunc("/groups/*/people", peopleInGroupHandler)
здесь * может быть любая допустимая строка URL. Или это единственное решение, чтобы соответствовать /groups и выяснить остальное из обработчика (peopleInGroupHandler) func?
5 ответов:
шаблоны для http.Обработчик и http.HandleFunc не являются регулярными выражениями или глобусами. Нет способа указать подстановочные знаки. Они задокументированы здесь.
тем не менее, это не слишком трудно создать свой собственный обработчик, который может использовать регулярные выражения или любой другой вид рисунка вы хотите. Вот тот, который использует регулярные выражения (скомпилированные, но не проверенные):
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 } } // no pattern matched; send 404 response http.NotFound(w, r) }
С 2011 года, теперь вы можете (2014+) найти другие решения.
Например,пакета мультиплексирования веб-горилла инструментарий предоставляет все виды маршрутизации:
- сопоставление шаблонов по пути запроса, с дополнительными регулярными выражениями.
- сопоставление URL-адрес узла и схема, метод запроса, заголовка и запроса значений.
- сопоставление на основе пользовательских функций.
- использование суб-маршрутизаторов для легкого вложенного маршрутизирующий.
его можно легко интегрировать к любому BYOR (принесите ваш собственный маршрутизатор) архив http,как Негрони.
вот пример из статьи "горилла против Пэта против маршрута: мультиплексор разборки":
package main import ( "github.com/gorilla/mux" "log" "net/http" ) func main() { rtr := mux.NewRouter() rtr.HandleFunc("/user/{name:[a-z]+}/profile", profile).Methods("GET") http.Handle("/", rtr) log.Println("Listening...") http.ListenAndServe(":3000", nil) } func profile(w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) name := params["name"] w.Write([]byte("Hello " + name)) }иногда лучше просто не использовать еще один "волшебный" пакет, а понять, что происходит под капотом
в этом случае "магия" определяется в "
gorilla/mux/regexp.go", и здесь.
Идея состоит в том, чтобы извлечь именованные переменные, собрать регулярное выражение для сопоставления, создать "обратный" шаблон для построения URL-адресов и скомпилировать регулярные выражения для проверки значений переменных, используемых в создании URL-адресов.
Я просто хотел добавить
julienschmidt/httprouter, который просто ведет себя какnet/httpно с дополнительным параметром для url-значений и поддержкой методов запроса:https://github.com/julienschmidt/httprouter
package main import ( "fmt" "github.com/julienschmidt/httprouter" "net/http" "log" ) func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { fmt.Fprint(w, "Welcome!\n") } func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name")) } func main() { router := httprouter.New() router.GET("/", Index) router.GET("/hello/:name", Hello) log.Fatal(http.ListenAndServe(":8080", router)) }Он также кажется немного более популярным, чем
gorilla/mux(По на GitHub), и он также утверждает, что нужно меньше памяти.
вы можете проверить, как violetear обрабатывает динамические + подстановочные шаблоны (подстановочные знаки), это просто для дополнения, например:
uuid := `[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}` router.AddRegex(":uuid") router.HandleFunc("/test/:uuid/:uuid", handleUUID, "GET,HEAD")в этом случае, запрос может иметь 2 разных
UUIDSдля динамического / подстановочного знака это может применяться:
http://api.violetear.org/command/ping/127.0.0.1 \______/\___/\________/ | | | static | dynamicрегулярное выражение может использоваться для соответствия IP:
router.AddRegex(":ip", `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`) router.HandleFunc("/command/ping/:ip", ipHandler, "GET")или просто просто поймать все позволяет
GETиHEADметоды только:router.HandleFunc("/command/ping/*", anyHandler, "GET, HEAD")больше примеров вы можете найти здесь:https://violetear.org/post/how-it-works/
Comments