Skip to content

middleware/websocket: Conn.Param always returns "" (route params are never captured), and on epoll and io_uring Conn.IP and Conn.RemoteAddr return "" and nil #721

Description

@FumingPower3925

Summary

In middleware/websocket:

  • Conn.Param always returns "", on every engine, because the route params are never captured.
  • On epoll and io_uring, Conn.IP() returns "" and Conn.RemoteAddr() returns nil.

#714 guessed that Conn.Param "is very likely affected" by the query aliasing. The audit it called for found that the real defect is different: Param is never captured at all. Neither defect is a view retention.

Mechanism

  • Param. Conn.Param reads c.params (middleware/websocket/conn.go:950 at 9f4d89b). Nothing in the package assigns params: setupConn (websocket.go:308-322) sets only headers and query, and git log -S'ws.params' finds no commit that ever did. This has been the case since the middleware landed in v1.3.4 (feat: v1.3.4 realtime middleware (WebSocket + SSE + Protobuf) #229).
  • IP and RemoteAddr. Both read c.conn (conn.go:880-925). Only the hijack path sets it (newConn, used by the std engine). The engine path builds its Conn with newEngineConn (conn.go:135-157), which has no net.Conn, and the peer address that c.RemoteAddr() holds on the Context (context_request.go:654) is not captured.

Reproduction

The evidence test is TestC714EvidenceParamAndIP, kept with the #714 evidence. The route is GET /ws/:room, and the handler reports c.Param("room"), c.IP() and c.RemoteAddr() for an upgrade to /ws/lobby.

engine Param("room") IP() RemoteAddr()
std "" 127.0.0.1 127.0.0.1:<port>
epoll "" "" <nil>
io_uring "" "" <nil>

Docker linux/arm64 (--cpus 4), kernel 7.0.12-linuxkit, memlock 8 MiB, go test -race.

Fix direction

Capture the route params and the peer address at upgrade, next to captureQuery. Clone every string, for the reason #714 gives: on the native engines a param value is a view of the receive buffer, and the Conn outlives the request. Keep the peer address as a string for IP(), and return a net.Addr built from it for RemoteAddr(), so the engine path answers what the hijack path does.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingmiddlewareMiddleware implementation

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions