Skip to content

Double Responses and one without any Response #1908

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
3 tasks done
ghost opened this issue Jul 5, 2021 · 9 comments
Closed
3 tasks done

Double Responses and one without any Response #1908

ghost opened this issue Jul 5, 2021 · 9 comments

Comments

@ghost
Copy link

ghost commented Jul 5, 2021

Issue Description

Currently we are facing a issue were two requests get combined in one Response. One Response keeps empty and the other one holds 2 Responses.
It often occurs when you submit 2 Request at the same time to echo from the same session and host. Then somehow the Requests gets combined.

Has someone a Idea why that occurs.

Checklist

  • Dependencies installed
  • No typos
  • Searched existing issues and docs

Some Implementation Stuff:

we just used the standard Stuff from echo nothing special.
The Middleware we have is just a one wo stores data into redis back and forth.

Version/commit

github.com/labstack/echo/v4 v4.3.0

Code

I can't really post any code, because I don't know what could issue something like that. As a side note we already gone thorugh the code and checked for potentially variables or poitners who are sett incorrectly. We also save all the Data for a User in the Echo Object with c.Set and c.Get

@aldas
Copy link
Contributor

aldas commented Jul 5, 2021

The Middleware we have is just a one wo stores data into redis back and forth.

You are not using any of the Echo own middlewares?

Are you passing Echo context to your services/functions from handler and do work in different goroutines? For example: after request is completed echo.Context is put back pool and reused for next requests and if you pass context to different coroutine with longer lifecycle you are in trouble.

@ghost
Copy link
Author

ghost commented Jul 5, 2021

Could something like this be a problem?

type AuthMiddleware struct {
	ctx                 echo.Context
	OauthConfig *oauth2.Config
	sess                *sessions.Session
}

// Create AuthMiddleware
func NewAuthMiddleware() *AuthMiddleware {
	return &AuthMiddleware{}
}

// Init created AuthMiddleware
func (c *AuthMiddleware) Init(next echo.HandlerFunc) echo.HandlerFunc {
	return func(ctx echo.Context) error {
		c.ctx = ctx
                //Returns session struct
		c.sess = helper.GetSessionObject(&ctx)

               //Do more Auth Stuff in different functions

		return next(ctx)
	}
}

@aldas
Copy link
Contributor

aldas commented Jul 5, 2021

Yes, I think so. When http.Server handles request it creates new coroutine for Echo to execute ServeHTTP on. Now in Echo handler chain you are passing echo.Contex into AuthMiddleware instance that is accessed from different coroutines started by http.Server. See how Echo pools/reuses context object for each request

echo/echo.go

Lines 625 to 652 in f20820c

func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Acquire context
c := e.pool.Get().(*context)
c.Reset(r, w)
h := NotFoundHandler
if e.premiddleware == nil {
e.findRouter(r.Host).Find(r.Method, GetPath(r), c)
h = c.Handler()
h = applyMiddleware(h, e.middleware...)
} else {
h = func(c Context) error {
e.findRouter(r.Host).Find(r.Method, GetPath(r), c)
h := c.Handler()
h = applyMiddleware(h, e.middleware...)
return h(c)
}
h = applyMiddleware(h, e.premiddleware...)
}
// Execute chain
if err := h(c); err != nil {
e.HTTPErrorHandler(err, c)
}
// Release context
e.pool.Put(c)
}

on line 627 we get context from pool for this coroutine and on line 651 we put it back to pool. Between those lines that context must only be accessed in that coroutine. But if you set context to AuthMiddleware object instance you are creating data race as multiple request can access that context from there.

You should never let echo.Context to get out of handler function and coroutine executing handler.

@ghost
Copy link
Author

ghost commented Jul 5, 2021

ok thanks. let me go through my code base and I look if my double Response are going away. 👍

@aldas
Copy link
Contributor

aldas commented Jul 5, 2021

just to be sure - you are not using timeout middleware?

@ghost
Copy link
Author

ghost commented Jul 6, 2021

no we don't :)

@ghost
Copy link
Author

ghost commented Jul 12, 2021

so we gone through our code and fixed the midllewares who are exposing the ctx from Echo to a Middleware Context.

Maybe as a suggestion, you wanna add a hint to the docs? or was there already one?

@ghost
Copy link
Author

ghost commented Jul 12, 2021

From my site this would be done 👍 . Thanks :)

@aldas
Copy link
Contributor

aldas commented Jul 12, 2021

Ok, I'll close this issue for now and I created TODO in echo documentation repo.

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

No branches or pull requests

1 participant