func (s *Server) doServe(listener net.Listener, readyCb func(addr string)) error { cb := NewConnBag() proxy := http.HandlerFunc( func(w http.ResponseWriter, req *http.Request) { c := cb.Withdraw(req.RemoteAddr) context.Set(req, "conn", c) s.handler.ServeHTTP(w, req) context.Clear(req) }) s.httpServer = http.Server{Handler: proxy, ConnState: func(c net.Conn, state http.ConnState) { wconn, ok := c.(listeners.WrapConn) if !ok { panic("Should be of type WrapConn") } wconn.OnState(state) switch state { case http.StateActive: cb.Put(wconn) case http.StateClosed: // When go server encounters abnormal request, it // will transit to StateClosed directly without // the handler being invoked, hence the connection // will not be withdrawed. Purge it in such case. cb.Purge(c.RemoteAddr().String()) } }, ErrorLog: log.AsStdLogger(), } firstListener := listeners.NewDefaultListener(listener) firstListenerPtr := &firstListener s.listeners = []*net.Listener{firstListenerPtr} for _, li := range s.listenerGenerators { newlis := li(*firstListenerPtr) s.listeners = append(s.listeners, &newlis) firstListenerPtr = &newlis } s.Addr = (*firstListenerPtr).Addr() addrStr := s.Addr.String() s.httpServer.Addr = addrStr if readyCb != nil { readyCb(addrStr) } return s.httpServer.Serve(*firstListenerPtr) }
func (s *Server) Serve(listener net.Listener, readyCb func(addr string)) error { l := listeners.NewDefaultListener(listener) for _, wrap := range s.listenerGenerators { l = wrap(l) } if readyCb != nil { readyCb(l.Addr().String()) } return s.httpServer.Serve(l) }