saul.shanabrook
saul.shanabrook

Reputation: 3168

Go Context with http.server

In order to test a server that I am writing, I want to be able to start and stop it in the testing framework.

To do so, I am hoping I can integrate the context package in with the http.Server struct. I want to be able to stop the server when I call the Done function and the ctx.Done() channel returns something.

What I would love to do would be to just modify the http.Server.Serve() method, to accept a context.Context and check if it is done, on each iteration of the for loop, like this:

func (srv *server) Serve(ctx context.Context, l net.Listener) error {
    defer l.Close()
    var tempDelay time.Duration // how long to sleep on accept failure
    for {
        select {
        case <-ctx.Done():
            return nil
        default:
        }
        ... rest is same as original

However it seems like if I wanna add that check inside the for loop, I would have to rewrite a lot of the methods, because this method calls other private methods (like http.server.srv), which in turn call other private methods....

I also notice that the for loop will stop when the Accept() method on the listener returns an error.

However, I can't seem to figure out a way to get a listener to output an error from it's accept method without accessing its private methods as well.

It seems like I am doing something very stupid and wrong if I have to copy and paste half the http library just to let the server stop using the context package.

I know there are lots of solutions around for supporting context canceling for the ServeHTTP function, but that isn't what I am talking about. I wanna pass a context to the whole server, not just to each incoming request.

Is this just impossible?

Upvotes: 0

Views: 2061

Answers (1)

Thundercat
Thundercat

Reputation: 120941

Use httptest.Server to create a server that you can start and stop in tests.

If you do use the http.Server directly, you can break the Serve loop by closing the net.Listener. When a net.Listener is closed, any blocked Accept operations are unblocked and return errors. The Serve function returns if Accept returns a permanent error.

Upvotes: 2

Related Questions