kataras / iris

The fastest HTTP/2 Go Web Framework. New, modern and easy to learn. Fast development with Code you control. Unbeatable cost-performance ratio :rocket:
https://www.iris-go.com
BSD 3-Clause "New" or "Revised" License
25.11k stars 2.48k forks source link

[BUG] When using both HTTP services and WebSocket in Iris, the responseWriter for HTTP requests can be used concurrently #2479

Open DOLLook opened 1 month ago

DOLLook commented 1 month ago

Describe the bug When using both HTTP services and WebSocket in Iris, the responseWriter for HTTP requests can be used concurrently, leading to various strange issues with HTTP responses. For example, responses for different requests might get written into the same request, causing unexpected behavior. Seriously, in some case, like write requestid in the response header, it will write the header concurrently and make the program crashed.

To Reproduce Steps to reproduce the behavior:

  1. app:=iris.New()
  2. app.UseRouter(requestid.New())
  3. app.Get("/hello", func(ctx iris.Context) { // do something ctx.Next() })
  4. _websocketServer = websocket.New(websocket.DefaultGorillaUpgrader, serverEvents)
  5. app.Get("/websocket", websocket.Handler(_websocketServer))
  6. app.Run(iris.Addr(host))

Desktop (please complete the following information):

iris.Version

Additional context Initially, I noticed that sometimes the context obtained through websocket.GetContext(conn) was the context from a regular HTTP request. Then, I found the #1856 issue, which reported that the websocket might retrieve the wrong context. This problem was solved by adding a manualRelease field to the context. However, in my test , this issue still persists.

To tackle this, I attempted to isolate the context pools used by HTTP and websocket by having them operate under two separate instances of the iris app, like httpApp:=iris.New() for http service, wsApp:=iris.New() for websocket service. and run them in one program. After doing so, the problem of retrieving incorrect contexts did not occur anymore. Yet, under high concurrency, HTTP requests started experiencing response mix-ups.

Further investigation led me to discover that the responseWriter within the context is retrieved from a global cache pool. When I modified the global cache to have an independent responseWriter pool for each instance of the iris app, all problems were resolved.