How Can I Access the Underlying Socket of an HTTP Response in Go?

Linda Hamilton
Release: 2024-11-04 22:39:02
Original
589 people have browsed it

How Can I Access the Underlying Socket of an HTTP Response in Go?

Accessing the Underlying Socket of an HTTP Response

In Go, you may encounter situations where you need to access the underlying socket of an HTTP response. Typically, accessing the socket is required when you want to perform platform-specific operations on it, such as TCP_INFO. While there is no straightforward way to obtain the socket directly from the HTTP response, there are several approaches you can explore:

1. Using the Context Key (Go 1.13 ):
Once Go 1.13 is released, it is anticipated to support storing the net.Conn in the Request Context. This provides a clean and straightforward method:

<code class="go">package main

import (
  "net/http"
  "context"
  "net"
  "log"
)

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)
}

func main() {
  http.HandleFunc("/", myHandler)
  server := http.Server{
    Addr: ":8080",
    ConnContext: SaveConnInContext,
  }
  server.ListenAndServe()
}

func myHandler(w http.ResponseWriter, r *http.Request) {
  conn := GetConn(r)
  ...
}</code>
Copy after login

2. Mapping Connection by Remote Address (TCP):
For servers listening on TCP, each connection has a unique net.Conn.RemoteAddr().String() value. This value can be used as a key to a global map of connections:

<code class="go">package main

import (
  "net/http"
  "net"
  "fmt"
  "log"
)

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]
}

func main() {
  http.HandleFunc("/", myHandler)
  server := http.Server{
    Addr: ":8080",
    ConnState: ConnStateEvent,
  }
  server.ListenAndServe()
}

func myHandler(w http.ResponseWriter, r *http.Request) {
  conn := GetConn(r)
  ...
}</code>
Copy after login

3. Overriding Remote Address for UNIX Sockets:
For UNIX sockets, net.Conn.RemoteAddr().String() always returns "@", making it unsuitable for mapping. To overcome this:

  • Override net.Listener.Accept()
  • Use that override to assign a unique string to each connection via net.UnixConn.File()
<code class="go">package main

import (
  "net/http"
  "net"
  "os"
  "golang.org/x/sys/unix"
  "fmt"
  "log"
)

// ... (code omitted for brevity)

func main() {
  http.HandleFunc("/", myHandler)
  listenPath := "/var/run/go_server.sock"
  l, err := NewUnixListener(listenPath)
  if err != nil {
    log.Fatal(err)
  }
  defer os.Remove(listenPath)
  server := http.Server{
    ConnState: ConnStateEvent,
  }
  server.Serve(NewConnSaveListener(l))
}
// ... (code omitted for brevity)</code>
Copy after login

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

source:php.cn
Statement of this Website
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
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!