duanba3707 2015-08-29 13:09
浏览 39
已采纳

使用Negroni时,可以仅在每个请求中全局使用自定义HTTP处理程序吗?

To make sure error results are handled correctly across all requests I'm implementing a custom handler as described in http://blog.golang.org/error-handling-and-go. So instead of only accepting the w http.ResponseWriter, r *http.Request params the handler optionally returns an error.

I'm using Negroni and wondered whether I can set it up once to wrap all requests into handler or if it will always have to be set up on a per-request basis as done for / and /foo in the following example?

type handler func(w http.ResponseWriter, r *http.Request) error

// ServeHTTP checks for error results and handles them globally
func (fn handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if err := fn(w, r); err != nil {
        http.Error(w, err, http.StatusInternalServerError)
    }
}

// Index matches the `handler` type and returns an error
func Index(w http.ResponseWriter, r *http.Request) error {
    return errors.New("something went wrong")
}

func main() {
    router := mux.NewRouter()
    // note how `Index` is wrapped into `handler`. Is there a way to 
    // make this global? Or will the handler(fn) pattern be required 
    // for every request?
    router.Handle("/", handler(Index)).Methods("GET")
    router.Handle("/foo", handler(Index)).Methods("GET")

    n := negroni.New(
        negroni.NewRecovery(),
        negroni.NewLogger(),
        negroni.Wrap(router),
    )

    port := os.Getenv("PORT")
    n.Run(":" + port)
}
  • 写回答

1条回答 默认 最新

  • duanpu1111 2015-08-30 01:27
    关注

    You can write a wrapper around r.Handle if you want. You can't do it globally with Negroni as not all middleware you use assumes your handler type.

    e.g.

    // Named to make the example clear.
    func wrap(r *mux.Router, pattern string, h handler) *mux.Route {
        return r.Handle(pattern, h)
    }
    
    func index(w http.ResponseWriter, r *http.Request) error {
        io.WriteString(w, "Hello")
        return nil
    }
    
    func main() {
        r := mux.NewRouter()
        wrap(r, "/", index)
    
        http.ListenAndServe(":8000", r)
    }
    

    I'd argue that this is not much better than just explicitly type-casting your handlers (which is clear, if a little repetitive), or turning your handler type into a struct. The latter you can later extend to contain thread-safe fields (your DB pool, app config, etc) that you can then explicitly pass alongside each handler).

    In reality your current router code is still clear and easy to read, and makes it obvious (to others) what type underpins your handlers.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 请问一下这个运行结果是怎么来的
  • ¥15 这个复选框什么作用?
  • ¥15 单通道放大电路的工作原理
  • ¥30 YOLO检测微调结果p为1
  • ¥20 求快手直播间榜单匿名采集ID用户名简单能学会的
  • ¥15 DS18B20内部ADC模数转换器
  • ¥15 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下