如何根据请求路径创建自定义超时处理程序?

时间:2017-11-10 08:21:27

标签: go

我写了一个超时中间件。在这个超时中间件中,我创建了一个用于处理 next 处理程序的goroutine,但是在超时发生两秒后,响应返回408超时状态代码,但goroutine在后台运行并执行处理程序链中的下一个处理程序。 那么如何编写正确的超时中间件?

超时中间件

type TimeoutHandler struct {
    Next http.Handler
}

func (handler *TimeoutHandler) ServeHTTP(responseWriter http.ResponseWriter, request *http.Request) {
     /*if nil 'Next' handler.*/
     if handler.Next == nil {
         /*delegate to default serve mux.*/
         handler.Next = http.DefaultServeMux
     }

     /*context with timeout.*/
     requestContext := request.Context()
     timeoutContext, cancelFunction := context.WithTimeout(requestContext, 2*time.Second)
     defer cancelFunction()

     /*request with new context.*/
     request = request.WithContext(timeoutContext)
     chanDone := make(chan bool)

     go func() {
          /*delegate request to `Next` handler*/
          handler.Next.ServeHTTP(responseWriter, request)
          chanDone <- true
     }()

     select {
     case <-timeoutContext.Done():
          /*status 408 request timeout.*/
          responseWriter.WriteHeader(http.StatusRequestTimeout)
     case <-chanDone:
          return
    }
}

这些是我遇到的问题:

  1. 超时后,无论如何都会运行下一个处理程序。
  2. 如果我在超时中间件之后使用更多处理程序,则会出现警告:&#34; http:multiple response.WriteHeader calls。&#34;

1 个答案:

答案 0 :(得分:1)

我在论坛中找到了更好的解决方案,我希望这个解决方案可以帮助其他新人。

/**
*
*/
type TimeoutHandler struct {
    Next http.Handler
}

/**
 *
 */
func (h *TimeoutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    /*nil 'Next' handler.*/
    if h.Next == nil {
        /*delegate to default serve mux.*/
        h.Next = http.DefaultServeMux
    }

    /*delegate request to new timeout handler.*/
    timeoutHandler := http.TimeoutHandler(h.Next, 4 * time.Second, `Request Timeout.`)
    timeoutHandler.ServeHTTP(w, r)
}