Мое веб-приложение в Go (использующее Gorilla mux
и negroni
) имеет около 20 обработчиков, разделенных на три группы в зависимости от того, какие функции Middleware следует применять. В частности:
Группа 1: Статические запросы (никакого промежуточного программного обеспечения вообще)
GET /favicon.ico
GET /files
GET /files/index.html
GET /files/favicon.ico
Группа 2: Запросы, которые должны иметь только промежуточное программное обеспечение CORS, без аутентификации:
GET /
GET /login
POST /login
GET /auth-configuration
GET /service-status
Группа 3: Запросы, к которым должны применяться как CORS, так и промежуточное ПО аутентификации:
GET /articles
POST /articles
PUT /articles/etc
PATCH /articles/etc
Это мой код, который устанавливает HTTP-сервер:
func run() {
negroniStack := setUpNegroni()
bindAddr := // ...
http.ListenAndServe(bindAddr, negroniStack)
}
func setUpNegroni() negroni.Negroni {
negroniStack := negroni.Negroni{}
staticNegroni := setUpRoutesAndMiddlewareForStaticRequests()
loginNegroni := setUpRoutesAndMiddlewareForLogin()
serviceNegroni = setUpRoutesAndMiddlewareForService()
negroniStack.UseHandler(&staticNegroni)
negroniStack.UseHandler(&loginNegroni)
negroniStack.UseHandler(&serviceNegroni)
return negroniStack
}
func setUpRoutesAndMiddlewareForStaticRequests() negroni.Negroni {
staticNegroni := negroni.Negroni{}
staticRouter := mux.NewRouter()
staticRouter.PathPrefix("/files").HandlerFunc(staticHandler)
staticRouter.Path("/favicon.ico").HandlerFunc(staticHandler)
staticNegroni.UseHandler(staticRouter)
return staticNegroni
}
func setUpRoutesAndMiddlewareForLogin() negroni.Negroni {
authNegroni := negroni.Negroni{}
corsMiddleware := cors.New(cors.Options{
AllowedMethods: []string{"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE"},
AllowCredentials: true,
OptionsPassthrough: false,
})
authNegroni.Use(corsMiddleware)
authRouter := mux.NewRouter()
authRouter.HandleFunc("/login", HandlePostAuth).Methods("POST")
authRouter.HandleFunc("/login", HandleGetAuth) // GET
authNegroni.UseHandler(authRouter)
return authNegroni
}
func setUpRoutesAndMiddlewareForService() negroni.Negroni {
serviceNegroni := negroni.Negroni{}
corsMiddleware := cors.New(cors.Options{
AllowedMethods: []string{"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE"},
AllowCredentials: true,
OptionsPassthrough: false,
})
serviceNegroni.Use(corsMiddleware)
serviceNegroni.UseFunc(jwtMiddleware)
serviceRouter := mux.NewRouter()
serviceRouter.HandleFunc("/articles", HandleGetArticles).Methods("GET")
serviceRouter.HandleFunc("/articles", HandlePostArticles).Methods("POST")
// etc
serviceNegroni.UseHandler(serviceRouter)
return serviceNegroni
}
Я считаю, что это правильно, основываясь на разделе «Маршрутное промежуточное программное обеспечение» в документации Negroni , где говорится:
Если у вас есть группа маршрутов, для которой требуется выполнение определенного промежуточного программного обеспечения, вы можете просто создать новый экземпляр Negroni и использовать его в качестве обработчика маршрута.
Однако, когда я делаю запросы и использую отладчик, я вижу, что (*Negroni).ServeHTTP
вызывается несколько раз. Например, если я запрашиваю GET /favicon.ico
, то функция staticHandler
вызывается правильно и вызывает WriteHeader(200)
, но после этого она затем вызывает следующий mux.Router
, который вызывает WriteHeader(404)
, который выводит предупреждение в терминал, потому что заголовок был написан дважды (http: multiple response.WriteHeader calls
)
Если это маршрут, который не существует, то по умолчанию Gorilla NotFoundHandler
вызывается 3 раза (по одному на каждый mux.Router
).
Как заставить Negroni прекратить вызывать другие обработчики после того, как запрос был выполнен?
... и если я неправильно настроил свой экземпляр Negroni, почему он не выполняет проверки во время инициализации, чтобы предупредить меня о неверной конфигурации?
Насколько я понимаю, negroni.Use
и UseFunc
предназначены для установки промежуточного программного обеспечения (все они вызываются для каждого запроса), а UseHandler
для настройки обработчика терминала (только 1 вызывается для каждого запроса). или отступление до 404). Если я правильно понимаю ситуацию, то по какой-то причине он обрабатывает мои терминальные обработчики как промежуточное ПО.