英文:
Go Context with http.server
问题
为了测试我正在编写的服务器,我希望能够在测试框架中启动和停止它。
为了做到这一点,我希望能够将context包与http.Server结构体集成在一起。当我调用Done
函数并且ctx.Done()
通道返回某个值时,我希望能够停止服务器。
我希望做的是修改http.Server.Serve()方法,接受一个context.Context并在每次for循环迭代时检查它是否完成,像这样:
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:
}
... 其余部分与原始代码相同
然而,如果我想在for循环内添加该检查,我似乎需要重写很多方法,因为该方法调用其他私有方法(如http.server.srv),而这些私有方法又调用其他私有方法......
我还注意到,当监听器的Accept()方法返回错误时,for循环将停止。
然而,我似乎找不到一种方法来使监听器的accept方法输出错误,而不需要访问其私有方法。
如果我不得不复制粘贴一半的http库代码才能让服务器使用context包停止,那么我似乎在做一些非常愚蠢和错误的事情。
我知道有很多解决方案可以支持ServeHTTP函数的上下文取消,但这不是我所说的。我想将上下文传递给整个服务器,而不仅仅是每个传入的请求。
这是否完全不可能?
英文:
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?
答案1
得分: 1
使用httptest.Server在测试中创建一个可以启动和停止的服务器。
如果你直接使用http.Server,你可以通过关闭net.Listener来中断Serve循环。当net.Listener被关闭时,任何被阻塞的Accept操作都会被解除阻塞并返回错误。如果Accept返回一个永久性错误,Serve函数也会返回。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论