Обработка http.Request на Go

Подскажите, пожалуйста. Для роута во всех мануалах написан один и тот же код.

http.HandleFunc("/", hendler)     // отдаем функции hendler
http.HandleFunc("/admin/", hendlerCMS)     // отдаем функции hendlerCMS

Так вот, когда запрос http://domain/admin/, то выполняется две функции: и hendler, и hendlerCMS. Как же этого избежать?

2 ответа

Как всегда забыл про то, что у браузеров есть еще запрос на /favicon.ico, который заводит обрабочик на главную страницу. Сделав специальный обработчик

http.HandleFunc("/favicon.ico", favicon)

или если вы пользуетесь google app engine в файле app.yaml

- url: /favicon.ico
  static_files: static/images/favicon.ico
  upload: static/images/favicon.ico

все будет, как написано в мануале. Обработка будет происходить от длинного паттерна к короткому.


Вы можете написать свои собственные обработчики, которые будут использовать другой алгоритм соответствия, нежели простое сопоставление, например, регулярные выражения. За основу можно взять код обработчиков из исходников Go. Например:

type Match struct {
    regexp *regexp.Regexp
    handler http.Handler
}

type RegExpHandler struct {
    matches []*Match
}

func (reh *RegExpHandler) Handler(regexp *regexp.Regexp, handler http.Handler) {
    reh.matches = append(reh.matches, &Match{regexp, handler})
}

func (reh *RegExpHandler) HandleFunc(regexp *regexp.Regexp, handler func(http.ResponseWriter, *http.Request)) {
    reh.matches = append(reh.matches, &Match{regexp, http.HandlerFunc(handler)})
}

func (reh *RegExpHandler) ServeHTTP(writer http.ResponseWriter, reader *http.Request) {
    for _, match := range reh.matches {
        if match.regexp.MatchString(reader.URL.Path) {
            match.handler.ServeHTTP(writer, reader)
            return
        }
    }
    http.NotFound(writer, reader)
}

licensed under cc by-sa 3.0 with attribution.