Comments (7)
Unfortunately, I believe this is a bug with Echo which will affect anyone who wants to use the new net/http request.Context()
and request.WithContext()
functions (like SCS uses under the hood).
For example, here's a more generalized example, with no SCS stuff in it:
package main
import (
"context"
"net/http"
"github.com/labstack/echo"
"github.com/labstack/echo/engine/standard"
)
func fooMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), "foo", "bar")
next.ServeHTTP(w, r.WithContext(ctx))
})
}
func main() {
e := echo.New()
e.Use(standard.WrapMiddleware(fooMiddleware))
e.GET("/", func(c echo.Context) error {
foo, ok := c.Request().(*standard.Request).Request.Context().Value("foo").(string)
if !ok {
return c.String(http.StatusInternalServerError, "could not find foo")
}
return c.String(http.StatusOK, foo)
})
e.Run(standard.New(":1323"))
}
You would expect the handler to output a 200 status and the content "bar"
, but it throws an error instead. It looks like, at some point, Echo loses the data which the middleware has been stored in the (net/http) request context.
I've opened an issue on the Echo repository: labstack/echo#685
from scs.
@alexedwards Thanks for your work!
from scs.
@cxjava You're welcome.
There's no changes that need to be made to SCS on this (just Echo), so I'll close this.
from scs.
@alexedwards I try to use this one into echo v3. For the example 1, works fine, the result as expected. But for the example 2, I can't get the expected message result Hello world!
from path /put
. I know there are some external work and code I need to do, Can you give me any suggestions?
package main
import (
"context"
"net/http"
"github.com/labstack/echo"
)
func fooMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), "foo", "bar")
next.ServeHTTP(w, r.WithContext(ctx))
})
}
func main() {
e := echo.New()
e.Use(echo.WrapMiddleware(fooMiddleware))
e.GET("/", func(c echo.Context) error {
foo, ok := c.Request().Context().Value("foo").(string)
if !ok {
return c.String(http.StatusInternalServerError, "could not find foo")
}
return c.String(http.StatusOK, foo)
})
e.Start(":1323")
}
package main
import (
"log"
"net/http"
"github.com/alexedwards/scs/engine/cookiestore"
"github.com/alexedwards/scs/session"
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
)
// HMAC authentication key (hexadecimal representation of 32 random bytes)
var hmacKey = []byte("f71dc7e58abab014ddad2652475056f185164d262869c8931b239de52711ba87")
// AES encryption key (hexadecimal representation of 16 random bytes)
var blockKey = []byte("911182cec2f206986c8c82440adb7d17")
func main() {
// Create a new keyset using your authentication and encryption secret keys.
keyset, err := cookiestore.NewKeyset(hmacKey, blockKey)
if err != nil {
log.Fatal(err)
}
// Create a new CookieStore instance using the keyset.
engine := cookiestore.New(keyset)
sessionManager := session.Manage(engine)
e := echo.New()
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.Use(echo.WrapMiddleware(sessionManager))
e.GET("/put", func(c echo.Context) error {
err := session.PutString(c.Request(), "message", "Hello world!")
if err != nil {
http.Error(c.Response().Writer(), err.Error(), 500)
}
return c.String(http.StatusOK, "put")
})
e.GET("/get", func(c echo.Context) error {
msg, err := session.GetString(c.Request(), "message")
if err != nil {
http.Error(c.Response().Writer(), err.Error(), 500)
}
return c.String(http.StatusOK, "result "+msg)
})
e.Start(":1323")
}
from scs.
@cxjava Did you solve the problem? I also want to integrate echo v3 and SCS.
from scs.
@dxvgef no...
from scs.
Sorry for the (very) slow reply.
This is happening because the session cookie is never being written by the SCS middleware. I think the session cookie isn't being written because Echo's WrapMiddleware doesn't actually pass the underlying http.ResponseWriter onwards -- it passes it's own c.Response() object instead. So the session manager's Write method is never being called.
func WrapMiddleware(m func(http.Handler) http.Handler) MiddlewareFunc {
return func(next HandlerFunc) HandlerFunc {
return func(c Context) (err error) {
m(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
c.SetRequest(r)
err = next(c)
})).ServeHTTP(c.Response(), c.Request())
return
}
}
}
The only 'fix' I can see is to call session.Save
manually in your handlers which modify the session data, like so:
e.GET("/put", func(c echo.Context) error {
err := session.PutString(c.Request(), "message", "Hello world!")
if err != nil {
log.Println(err.Error())
}
err = session.Save(c.Response(), c.Request())
if err != nil {
log.Println(err.Error())
}
return c.String(http.StatusOK, "put")
})
This essentially writes the session data and cookie, instead of relying on the middleware to do it.
from scs.
Related Issues (20)
- Let's go examples HOT 1
- constant panicing with chi v5 and pgxpool HOT 1
- Add a method to modify the deadline of the sessionData HOT 6
- NATs HOT 1
- Ignore GobCodec.Decode errors? HOT 3
- Possible to tag a new version? HOT 2
- Manually Set Token / Session ID? HOT 4
- Add example using gin
- Expose CtxStore interface to allow custom implementation HOT 1
- How to recover from corrupt session data? (or how to Destroy without loading the session) HOT 2
- Fails using ListenAndServeTLS HOT 1
- Sqlite3store error constraint failed: NOT NULL constraint failed: sessions.expiry (1299) HOT 4
- manage all session HOT 1
- Redis example is using a different Redis library HOT 8
- Custom names for sessions tables HOT 3
- support partitioned CHIPS cookies HOT 2
- pgxstore expects a *pgxpool.Pool instead of a *sql.DB HOT 5
- Flush / streaming HOT 2
- *scs.sessionResponseWriter does not implement http.Hijacker HOT 3
- Support Turso and libsql HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from scs.