Использование gorilla/mux для расширения возможностей маршрутизации HTTP-сервера Go.

Go

图片

Сегодня в этой статье мы будем писать для нашего предыдущегоHTTPНа сервере добавлена ​​функция комплексной маршрутизации и группового управления маршрутизацией. В предыдущей статье "Глубокое погружение в написание HTTP-серверов в Go"подробно об использованииnet/httpРеализованные методы регистрации маршрутизации, мониторинга сетевых подключений, обработки запросов и безопасного отключения сервисов очень удобны в использовании. ноnet/httpОдна вещь, которую он делает не очень хорошо, это то, что он не предоставляет что-то вродеURLСложные функции маршрутизации, такие как анализ фрагментов и привязка параметров маршрутизации. хорошая вещьGoВ сообществе очень популяренgorilla/muxпакет, обеспечивающий поддержку сложных функций маршрутизации. В сегодняшней статье мы рассмотрим, как использоватьgorilla/muxпакет для создания именованных параметров,GET/POSTМаршруты, которые обрабатывают, группируют префиксы и ограничивают доступ к доменным именам.

Установитьgorilla/muxСумка

мы писали раньшеHTTPКорень кода службы, установите пакет с GitHub с помощью команды go get следующим образом:

go get  github.com/gorilla/mux

существует"Глубокое погружение в написание HTTP-серверов в Go«Мы представили, что вызовы функций регистрации маршрута, сопоставления и окончательной обработки выполняютсяServeMux(сервисный мультиплексор) для завершения, и мы также определяем наш собственный мультиплексор для замены стандартногоDefaultServeMux. такой жеgorilla/muxПакет также предоставляет нам мультиплексор. Этот мультиплексор имеет множество функций для улучшения записиWebэффективность применения, но и со стандартомhttp.ServeMuxсовместимый.

использоватьgorilla/muxСумка

Создать маршрутизатор

Маршрутизатор можно создать так

router := mux.NewRouter()

вернетmux.Routerпример,mux.RouterСопоставьте входящие запросы со списком зарегистрированных маршрутов и сопоставьтеURLили другие условия, соответствующие обработчику вызова маршрута. Основные особенности:

  • Может основываться на хосте URL, пути, префиксе пути,Headerзаголовок, значение запроса,HTTPметод для сопоставления маршрутов или используйте пользовательский сопоставитель.
  • Хост URL, путь и значения запроса могут быть переменными с необязательными регулярными выражениями.
  • Маршруты можно использовать в качестве дочерних маршрутов, и они будут пытаться сопоставить дочерние маршруты только в том случае, если совпадает родительский маршрут. Это полезно для определения групп маршрутизации, которые могут совместно использовать хосты, префиксы пути или другие общие атрибуты.
  • Он реализует интерфейс http.Handler и поэтому совместим со стандартнымhttp.ServeMuxПолностью совместим.

Зарегистрировать обработчик маршрута

Заменяем кастомный сервисный мультиплексор в предыдущей программе на созданный вышеmux.Routerи зарегистрируйте для него обработчик маршрута.

type helloHandler struct{}
func (*helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello World")
}
func WelcomeHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Welcome!")
}

func main() {
	router := mux.NewRouter()
	router.Handle("/", &helloHandler{})
  router.HandleFunc("/welcome", WelcomeHandler)
  ......
}

Ранее мы использовалиhttp.Hanle,http.HandleFuncЗарегистрируйте обработчик, здесь он напрямую заменяется наrouter.Hanleа такжеrouter.HanleFuncВот именно, это очень удобно.

Определение маршрута с именованными параметрами

использоватьmux.RouterСамым большим преимуществом является то, что вы можете запроситьURLФрагменты извлекаются из , и передаются в обработчик маршрута как именованные параметры для использования.

Далее регистрируем обработчик маршрута для нашей программы, чтобы сервер мог его обработатьURLза/names/Gorge/countries/NewZealandзапрос:

router.HandleFunc("/names/{name}/countries/{country}", func(writer http.ResponseWriter, request *http.Request) {
			......
})

Далее в функции обработчика используйтеmux.Vars()функции от этихURLПолучить данные по сегментам. Функция начинается сhttp.Requestв качестве параметра и вернутьURLСегменты являются именованными ключами, а извлеченные данные представляют собой словарь значений.

func(writer http.ResponseWriter, request *http.Request) {
		vars := mux.Vars(request)
		name := vars["name"]
		country := vars["country"]
		fmt.Fprintf(writer, "This guy named %s, was coming from %s .", name, country)
})

Пусть сервер использует созданный нами роутер

Эта настройка проста, если не настроенаhttp.Serverобъект, используяhttp.ListenAndServe(":8000", router), при использовании самоопределяемого объекта `http.Server:

server := &http.Server{
	Addr:    ":8080",
	Handler: router,
}

Это и мы передаем мультиплексор пользовательского сервиса вhttp.ServerНет никакой разницы.

После преобразования, которое мы написали ранееHTTPЗатем сервер может динамически формировать ответ на основе определенного URL-адреса. ключевое слово ответhttp02Доступен полный исходный код

разноеgorilla/muxОбщие функции маршрутизаторов

Установите HTTP-метод маршрута

Ограничить обработчик маршрутов только обработкой указанногоHTTPзапрос метода:

router.HandleFunc("/books/{title}", CreateBook).Methods("POST")
router.HandleFunc("/books/{title}", ReadBook).Methods("GET")
router.HandleFunc("/books/{title}", UpdateBook).Methods("PUT")
router.HandleFunc("/books/{title}", DeleteBook).Methods("DELETE")

Выше приведена группа, которая может реагировать на конкретныеHTTPметодRESTfulстиль маршрутизации интерфейса.

Установить доменное имя маршрута

Ограничьте обработчик маршрута только обработкой запросов на доступ к указанному доменному имени и маршруту:

router.HandleFunc("/books/{title}", BookHandler).Host("www.mybookstore.com")

Ограничить схемы HTTP

Сделать обработчик запроса отзывчивымHTTPПрограмма ограниченаhttpилиhttps.

router.HandleFunc("/secure", SecureHandler).Schemes("https")
router.HandleFunc("/insecure", InsecureHandler).Schemes("http")

Установить префиксы пути и подмаршруты

bookrouter := router.PathPrefix("/books").Subrouter()
bookrouter.HandleFunc("/", AllBooks)
bookrouter.HandleFunc("/{title}", GetBook)

использоватьgorilla/muxулучшить нашHTTPсервер

Далее мы используемgorilla/muxк тому, что мы писали ранееHTTPСделать некоторые улучшения на сервере, прежде чем все наши программы были размещеныmain.go, сейчас наша программа еще очень маленькая, так что не будем сильно усложнять директорию проекта, сначала сделаем простое разделение обязанностей через файлы, и создадим два новых файлаrouter.goа такжеhandler.goОни соответственно используются для хранения логики регистрации маршрута и функции процессора, соответствующей маршруту.Пример содержимого двух файлов следующий.

handler.go:

package main

import (
	"fmt"
	"github.com/gorilla/mux"
	"net/http"
)

type HelloHandler struct{}

func (*HelloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello World")
}

func ShowVisitorInfo(writer http.ResponseWriter, request *http.Request) {
	vars := mux.Vars(request)
	name := vars["name"]
	country := vars["country"]
	fmt.Fprintf(writer, "This guy named %s, was coming from %s .", name, country)
}

router.go:

package main

import (
	"github.com/gorilla/mux"
)

func RegisterRoutes(r *mux.Router) {
	indexRouter := r.PathPrefix("/index").Subrouter()
	indexRouter.Handle("/", &HelloHandler{})

	userRouter := r.PathPrefix("/user").Subrouter()
	userRouter.HandleFunc("/names/{name}/countries/{country}", ShowVisitorInfo)
}

существуетrouter.goВ мы делим маршруты наindexа такжеuserДве группы соответственно определяют маршруты в двух группах маршрутизации. Инкапсулируйте эту часть в экспортируемую функциюRegisterRoutesдля вызова. Таким образом, даже если программу, зарегистрированную маршрутом, в будущем нужно поместить в отдельный каталог, ее можно будет вызывать извне.

После окончания нашегоmain.goстанет очень лаконичным:

func main() {
   //mux := http.NewServeMux()
   //mux.Handle("/", &helloHandler{})
   muxRouter := mux.NewRouter()

   RegisterRoutes(muxRouter)

   server := &http.Server{
      Addr:    ":8080",
      Handler: muxRouter,
   }

   ......
   err := server.ListenAndServe()
   ......
}

Обратите внимание на ответ на общедоступный номерgo-http-02Получите полный пример кода в этой статье.

Предыдущий обзор:Глубокое погружение в написание HTTP-серверов в Go

Если вам понравилась моя статья, пожалуйста, помогите переслать ее и поставьте лайк Если у вас возникнут какие-либо проблемы в процессе практики, вы можете оставить мне сообщение ниже.

图片