I'd like to extend the http.Server
functionality by performing a graceful shutdown and some other gadgets that I would share across my HTTP services. Currently my code says more or less:
type MyServer struct {
server *http.Server
// ...
}
func (s *MyServer) ListenAndServe() {
// Create listener and pass to s.server.Serve()
}
This works great, but requires exposing all necessary methods and variables of http.Server
manually.
Wrapping most of the methods wouldn't be a big problem, but I can't find a sensible way to expose access to http.Server.ListenAndServeTLS
without actually copying implementation from the source. The last line in the method says srv.Serve(tlsListener)
and I'd love to provide my own Serve
method, so modification of net.Listener
is possible before passing it to http.Server.Serve
.
I started to pencil my wrapper by putting simply:
type MyServer struct {
http.Server
}
func (s *MyServer) Serve(l net.Listener) {
// Wrap l with MyListener, pass to s.Server.Serve()
}
but obviously neither http.ListenAndServe
nor http.ListenAndServeTLS
would start using my implementation of Serve
. And I'd like to ask them to... Is there any way I can tackle the problem or does the design of http.Server
effectively prevent me from solving this?
Hacks welcome: even if I don't use them in production, I'll gain some knowledge.
The http.ListenAndServe*
methods will work on the embedded type. The other way around works:
type MyServer struct {
http.Server
// ...
}
func (s *MyServer) ListenAndServe() error {
// create listener
// s.Server.Serve(s.listener)
}
func (s *MyServer) ListenAndServeTLS() error {
// create listener
// s.Server.Serve(s.tlsListener)
}