首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在请求完成后,Negroni继续调用其他处理程序。

在请求完成后,Negroni继续调用其他处理程序。
EN

Stack Overflow用户
提问于 2018-05-03 00:19:49
回答 1查看 987关注 0票数 1

我在Go中的web应用程序(使用大猩猩、muxnegroni)有大约20个处理程序,根据应用中间件的功能分为三组。具体地说:

  • 第1组:静态请求(根本没有中间件) 获取/favicon.ico GET /files GET / /files/index.html GET //files//files
  • 组2:只应该有CORS中间件的请求,没有身份验证: 获取/获取/login POST /login GET /auth-配置GET /服务状态
  • 第3组:应用CORS和身份验证中间件的请求: 获取/articles POST /articles PUT / /articles/etc修补程序/文章/etc

这是我设置HTTP服务器的代码:

代码语言:javascript
复制
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).ServeHTTP被多次调用。例如,如果我请求GET /favicon.ico,那么staticHandler函数将被正确调用并调用WriteHeader(200),但在此之后,它将调用下一个mux.Router,该mux.Router调用在终端中打印警告的下一个mux.Router,因为头被写入了两次(http: multiple response.WriteHeader calls)。

如果是针对不存在的路由,则会调用大猩猩默认NotFoundHandler 3次(每个mux.Router一次)。

如何让Negroni在请求完成后停止调用其他处理程序?

...and --如果我配置错了Negroni实例,为什么它不在初始化时执行检查来警告我配置无效?

我的理解是,negroni.UseUseFunc用于设置中间件(对每个请求都调用这些中间件),而UseHandler用于设置终端处理程序(每个请求只调用一个,或者返回到404)。如果我正确地理解了这种情况,那么出于某种原因,它将我的终端处理程序作为中间件对待。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-05-03 02:56:41

来自UseHandler文档(https://godoc.org/github.com/urfave/negroni#Negroni.UseHandler)

UseHandler将一个http.Handler添加到中间件堆栈中。处理程序按添加到Negroni.的顺序进行调用。

所以你在这里看到的似乎是预期的行为。

您基本上是在创建不同的negroni实例并将它们链接起来,因此您的最后一个negroniStack本身就是一个中间件,它将执行您添加的其他中间件。

我相信您想要做的是使用实际的路由器创建路由,然后向每个路由添加适当的中间件(使用negroni)。

如果您查看从文档链接的示例,这就是它们在该部分(https://github.com/urfave/negroni#route-specific-middleware)中所做的工作。

代码语言:javascript
复制
router.PathPrefix("/admin").Handler(negroni.New(
   Middleware1,
   Middleware2,
   negroni.Wrap(adminRoutes),
))

确保它们不是嵌套negroni实例,而是只创建一个应用于所需路由的实例。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50145256

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档