我正在写一个具有自我更新功能的http服务器,步骤是:
问题是当服务器调用
os.Exit()
时,客户端将收到EOF
而不是“ok”,我的代码如下:
服务器:
package main
import (
"io"
"net/http"
"os"
)
func replace_self_executable(executable_bytes []byte) {
// ...
}
func handle_self_update(w http.ResponseWriter, r *http.Request) {
executable_bytes, _ := io.ReadAll(r.Body)
replace_self_executable(executable_bytes)
w.Write([]byte(`ok`))
os.Exit(0)
// other stuff
}
func main() {
http.HandleFunc("/self_update", handle_self_update)
http.ListenAndServe(":123", nil)
}
客户:
package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
new_server_binary := []byte{ /*...*/ }
resp, err := http.Post(`http://localhost:123/self_update`, ``, bytes.NewReader(new_server_binary))
if err != nil {
panic(err)
}
result, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(`result`, string(result))
}
我也尝试先刷新并关闭客户端,似乎没有什么区别:
if f, ok := w.(http.Flusher); ok {
f.Flush()
}
r.Body.Close()
如何向客户发送“ok”?
向处理程序外部的例程发出信号(例如通过通道),以便您可以从请求处理程序返回并优雅地关闭服务器:
func handle_self_update(w http.ResponseWriter, r *http.Request) {
executable_bytes, _ := io.ReadAll(r.Body)
replace_self_executable(executable_bytes)
quitChan <- true
w.Write([]byte(`ok`))
}
func main() {
go func() {
_ := <- quitChan
// Graceful shutdown
}
// Start server
}
一个不相关的说明 - 在实施时要非常非常非常小心。允许客户端向您发布将在服务器上运行的新二进制文件是一个巨大的安全漏洞,并且应该具有身份验证、签名验证、校验和验证等层。或者更好的是,让客户端发出更新信号可用,并且让服务器联系已知良好的源来获取更新的二进制文件(并且仍然确认签名和校验和)。