-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Description
Issue Description
Using echo an asynchronous web server is developed. It accepts request body synchronously; spawns a go routine to process the request data and concurrently returns 200 OK to client
The flow could be imagined to be as below
- Request received at web server, echo sends a context
cto custom middleware - Custom middleware parses the
http.Requestfrom echo contextc, basically extracting the headers, body, etc - Custom middleware populates these details into echo context store by using the
c.Set("myKey", "myValue")method - At this point
--> A go routine is spawned to process this data set inside echo context store
--> Return from middleware by setting a static response -c.String(200, "Accepted") - Within the handler function, when we try to do
c.Get("myKey"), we receivenilfor keys set during step3
Shouldn't we receive myValue during step 5?
We are suspecting the context might be getting Reset here. We are thinking to clone the data inside echo Context c into either a custom context (which implements echo.Context) or maybe use AcquireContext / ReleaseContext utility functions to find a workaround
Any suggestions on a safer way to deal with this?
Working code to debug
type AuthData struct {
Agent string
TxnID string
}
func createAuthData(c echo.Context) AuthData {
return AuthData{
Agent: c.Request().UserAgent(),
TxnID: c.Request().Header.Get("X-TXN-ID"),
}
}
func extractionMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
c.Set("myAuthData", createAuthData(c))
go func() {
_ = next(c)
}()
return c.String(http.StatusOK, "Accepted")
}
}
func main() {
router := echo.New()
router.Use(extractionMiddleware)
router.GET("/record_stats/", StreamPush)
}
func StreamPush(c echo.Context) error {
if ad := c.Get("myAuthData"); ad == nil {
fmt.Print("context is nil")
} else {
fmt.Printf("performing further action for %s (%s)", ad.(AuthData).Agent, ad.(AuthData).TxnID)
// push AuthData to downstream service for processing
}
return nil
}Expected behaviour
In the StreamPush HandlerFunc, we extract AuthData from echo Context and proceed with our further logic to parse the data, which is the else block
Actual behaviour
While most of the times we do not see any issue. But in roughly 2-3% of requests (during high traffic on our platform) we could see the context is nil getting logged
Steps to reproduce
Run some load onto your webserver using vegeta or any other load test tool
Version/commit
v3.3.10