Подстановочные знаки в шаблоне для http.HandleFunc



при регистрации обработчиков в Go (язык) есть ли способ указать подстановочные знаки в шаблоне?



например:



http.HandleFunc("/groups/*/people", peopleInGroupHandler)


здесь * может быть любая допустимая строка URL. Или это единственное решение, чтобы соответствовать /groups и выяснить остальное из обработчика (peopleInGroupHandler) func?

970   5  

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), и он также утверждает, что нужно меньше памяти.

https://github.com/julienschmidt/go-http-routing-benchmark

вы можете проверить, как 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/

Beego, ответ на все вопросы веб-сервера Golang. Wetalk-это блог-сайт, построенный на Beego.

Comments

    Ничего не найдено.