go package “net/http” 无法直接使用 unix 域套接字侦听的服务,会提示,不支持的协议。
方案
1 2 3 4 5 6 7 8 9
| func fakeDial(proto, addr string) (conn net.Conn, err error) { return net.Dial("unix", sock) }
tr := &http.Transport{ Dial: fakeDial, } client := &http.Client{Transport: tr} resp, err := client.Get("http://unix/test")
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| package main
import ( "fmt" "io" "net" "net/http" "os" )
func dieIf(err error) { if err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) os.Exit(1) } }
const sock = "/tmp/dummy.sock"
func server() { l, err := net.Listen("unix", sock) dieIf(err) srv := &http.Server{ Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "hello: %v\n", r.RequestURI) }), } srv.Serve(l) }
func fakeDial(proto, addr string) (conn net.Conn, err error) { return net.Dial("unix", sock) }
func main() { defer os.Remove(sock) go server() time.Sleep(time.Second) tr := &http.Transport{ Dial: fakeDial, } client := &http.Client{Transport: tr} resp, err := client.Get("http://unix/test") dieIf(err) io.Copy(os.Stdout, resp.Body) resp.Body.Close() }
|
playground
警告,你所有的 client.Get/.Post 调用必须是有效的 url( http://xxxx.xxx/path 不是 unix://… ),域名无关紧要,因为它不会用于连接。
reference
sockets - Go net/http unix 域套接字连接
Go net/http unix domain socket connection
Go:Unix 域套接字
golang 中基于 http 和 unix socket 的通信代码实现(服务端基于 gin 框架)