Home >Backend Development >Golang >How Can I Access the Underlying Socket of a net/http Response in Go?

How Can I Access the Underlying Socket of a net/http Response in Go?

DDD
DDDOriginal
2024-11-07 10:36:03385browse

How Can I Access the Underlying Socket of a net/http Response in Go?

Retrieving the Underlying Socket of a net/http Response

In the realm of network programming with Go's net/http package, sometimes we may need to directly access the underlying network connection(net.Conn).

Problem Statement

A developer is trying to serve files using net/http, but encounters a problem: needing access to the underlying socket of http.ResponseWriter in the handler function ( net.Conn) to make platform-specific system calls.

Workaround

In Go 1.13 and above, net.Conn can be stored in the request context by following these steps:

  • Use the SaveConnInContext function to save net .Conn is saved to the request context.
  • Retrieve net.Conn from the request using the GetConn function.

Prior to this release, there were two alternatives:

Use the remote address string

For listening on a TCP port For servers, net.Conn.RemoteAddr().String() is unique for each connection and can be used as the key to the global connection map.

Override net.Listener.Accept()

For servers listening on UNIX sockets, we can override net.Listener.Accept() to Use the file descriptor to return a more unique value.

Code Example

Go 1.13 and above

<code class="go">// SaveConnInContext stores the net.Conn in the request context.
func SaveConnInContext(ctx context.Context, c net.Conn) context.Context {
  return context.WithValue(ctx, ConnContextKey, c)
}

// GetConn retrieves the net.Conn from the request context.
func GetConn(r *http.Request) net.Conn {
  return r.Context().Value(ConnContextKey).(net.Conn)
}</code>

for TCP connections

<code class="go">// ConnStateEvent handles connection state events.
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())
  }
}

// GetConn retrieves the net.Conn from a map using the remote address as a key.
func GetConn(r *http.Request) net.Conn {
  return conns[r.RemoteAddr]
}</code>

for UNIX connections

<code class="go">// NewUnixListener creates a new UNIX listener with a modified Accept() method.
func NewUnixListener(path string) (net.Listener, error) {
  // ... (setup code)

  l, err := net.Listen("unix", path)
  if err != nil {
    return nil, err
  }

  return NewConnSaveListener(l), nil
}

// NewConnSaveListener wraps a listener and overrides the Accept() method.
func NewConnSaveListener(wrap net.Listener) net.Listener {
  return connSaveListener{wrap}
}

// remoteAddrPtrConn overrides the RemoteAddr() method to return a unique value.
type remoteAddrPtrConn struct {
  net.Conn
  ptrStr string
}

func (self remoteAddrPtrConn) RemoteAddr() net.Addr {
  return remoteAddrPtr{self.ptrStr}
}

// remoteAddrPtr implements the net.Addr interface.
type remoteAddrPtr struct {
  ptrStr string
}

func (remoteAddrPtr) Network() string {
  return ""
}

func (self remoteAddrPtr) String() string {
  return self.ptrStr
}

// Accept overrides the default Accept() method to store the net.Conn in a map.
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
}</code>

Through these methods, developers can easily access the underlying socket of http.ResponseWriter, opening up a range of possibilities for their custom network handling.

The above is the detailed content of How Can I Access the Underlying Socket of a net/http Response in Go?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn