Obtaining the Underlying Socket in Go's net/http Response
Go's net/http package provides a convenient framework for building HTTP servers. However, there may be situations where you require access to the underlying socket of the response stream. This article addresses that need by exploring various approaches to retrieve the socket connection.
Before Go 1.13
Prior to Go 1.13, obtaining the underlying socket required more elaborate techniques. Here are two approaches:
Event-Based Tracking (TCP Connections Only):
For connections over TCP ports, you can leverage the net.Listener.ConnState event handler to track active connections and their associated sockets. This information can be stored in a global map for later retrieval.
<code class="go">var conns = make(map[string]net.Conn) func ConnStateEvent(conn net.Conn, event http.ConnState) { if event == http.StateActive { conns[conn.RemoteAddr().String()] = conn } else if event == http.StateHijacked || event == http.StateClosed { delete(conns, conn.RemoteAddr().String()) } } func GetConn(r *http.Request) (net.Conn) { return conns[r.RemoteAddr] }</code>
Listener Overriding (Unix Sockets):
Unix sockets require a more intricate approach as they lack unique identifiers for each connection. One solution is to override the net.Listener.Accept method to assign unique strings to each connection and use these as keys for storing socket information.
<code class="go">func NewConnSaveListener(wrap net.Listener) (net.Listener) { return connSaveListener{wrap} } func (self connSaveListener) Accept() (net.Conn, error) { conn, err := self.Listener.Accept() ptrStr := fmt.Sprintf("%d", &conn) conns[ptrStr] = conn return remoteAddrPtrConn{conn, ptrStr}, err } func GetConn(r *http.Request) (net.Conn) { return conns[r.RemoteAddr] }</code>
Go 1.13 and Beyond
With the release of Go 1.13, a more straightforward solution is available:
Context-Based Storage:
Beginning with Go 1.13, net.Conn can be stored in the context of the HTTP request. This provides a clean and efficient way to access the socket connection.
<code class="go">type contextKey struct { key string } var ConnContextKey = &contextKey{"http-conn"} func SaveConnInContext(ctx context.Context, c net.Conn) (context.Context) { return context.WithValue(ctx, ConnContextKey, c) } func GetConn(r *http.Request) (net.Conn) { return r.Context().Value(ConnContextKey).(net.Conn) }</code>
By understanding these techniques, you can effectively retrieve the underlying socket in your net/http response handlers, enabling custom operations and platform-specific functionality.
The above is the detailed content of How Do I Access the Underlying Socket in Go\'s net/http Response?. For more information, please follow other related articles on the PHP Chinese website!