diff options
author | lyric <tiannianshou@gmail.com> | 2018-05-17 05:13:22 +0300 |
---|---|---|
committer | lyric <tiannianshou@gmail.com> | 2018-05-17 05:13:22 +0300 |
commit | 7c7e18faddc54ea614f135fcef8bc05649fa9452 (patch) | |
tree | e726fde3ee6835973b4ce9224dc16abdc75bc902 | |
parent | 23a9229ef11190057188f4615a519ca6c9f693c4 (diff) |
add echo middleware
-rw-r--r-- | README.md | 83 | ||||
-rw-r--r-- | session.go | 90 | ||||
-rw-r--r-- | session_test.go | 80 |
3 files changed, 251 insertions, 2 deletions
@@ -1,2 +1,81 @@ -# echo-session -Session middleware for Echo. +# Session middleware for [Echo](https://github.com/labstack/echo) + +[![ReportCard][reportcard-image]][reportcard-url] [![GoDoc][godoc-image]][godoc-url] [![License][license-image]][license-url] + +## Quick Start + +### Download and install + +```bash +$ go get -u -v github.com/go-session/echo-session +``` + +### Create file `server.go` + +```go +package main + +import ( + "fmt" + "net/http" + + "github.com/go-session/echo-session" + "github.com/labstack/echo" + "gopkg.in/session.v2" +) + +func main() { + e := echo.New() + + e.Use(echosession.New( + session.SetCookieName("session_id"), + session.SetSign([]byte("sign")), + )) + + e.GET("/", func(ctx echo.Context) error { + store := echosession.FromContext(ctx) + store.Set("foo", "bar") + err := store.Save() + if err != nil { + return err + } + return ctx.Redirect(302, "/foo") + }) + + e.GET("/foo", func(ctx echo.Context) error { + store := echosession.FromContext(ctx) + foo, ok := store.Get("foo") + if !ok { + return ctx.String(http.StatusNotFound, "not found") + } + return ctx.String(http.StatusOK, fmt.Sprintf("foo:%s", foo)) + }) + + e.Logger.Fatal(e.Start(":8080")) +} +``` + +### Build and run + +```bash +$ go build server.go +$ ./server +``` + +### Open in your web browser + +<http://localhost:8080> + + foo:bar + + +## MIT License + + Copyright (c) 2018 Lyric + +[reportcard-url]: https://goreportcard.com/report/github.com/go-session/echo-session +[reportcard-image]: https://goreportcard.com/badge/github.com/go-session/echo-session +[godoc-url]: https://godoc.org/github.com/go-session/echo-session +[godoc-image]: https://godoc.org/github.com/go-session/echo-session?status.svg +[license-url]: http://opensource.org/licenses/MIT +[license-image]: https://img.shields.io/npm/l/express.svg
\ No newline at end of file diff --git a/session.go b/session.go new file mode 100644 index 0000000..ea5bbc7 --- /dev/null +++ b/session.go @@ -0,0 +1,90 @@ +package echosession + +import ( + "context" + "sync" + + "github.com/labstack/echo" + "gopkg.in/session.v2" +) + +type ( + // Skipper defines a function to skip middleware. Returning true skips processing + // the middleware. + Skipper func(c echo.Context) bool + + // Config defines the config for Session middleware. + Config struct { + // Skipper defines a function to skip middleware. + Skipper Skipper + // StoreKey keys stored in the context + StoreKey string + } +) + +var ( + // DefaultConfig is the default Recover middleware config. + DefaultConfig = Config{ + Skipper: func(_ echo.Context) bool { return false }, + StoreKey: "github.com/go-session/echo-session", + } + + once sync.Once + internalManager *session.Manager + storeKey string +) + +// get a session manager +func manager(opt ...session.Option) *session.Manager { + once.Do(func() { + internalManager = session.NewManager(opt...) + }) + return internalManager +} + +// New create a session middleware +func New(opt ...session.Option) echo.MiddlewareFunc { + return NewWithConfig(DefaultConfig, opt...) +} + +// NewWithConfig create a session middleware +func NewWithConfig(config Config, opt ...session.Option) echo.MiddlewareFunc { + if config.Skipper == nil { + config.Skipper = DefaultConfig.Skipper + } + + storeKey = config.StoreKey + if storeKey == "" { + storeKey = DefaultConfig.StoreKey + } + + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + if config.Skipper(c) { + return next(c) + } + + store, err := manager(opt...).Start(context.Background(), c.Response(), c.Request()) + if err != nil { + return err + } + c.Set(storeKey, store) + return next(c) + } + } +} + +// FromContext get session storage from context +func FromContext(ctx echo.Context) session.Store { + return ctx.Get(storeKey).(session.Store) +} + +// Destroy a session +func Destroy(ctx echo.Context) error { + return manager().Destroy(context.Background(), ctx.Response(), ctx.Request()) +} + +// Refresh a session and return to session storage +func Refresh(ctx echo.Context) (session.Store, error) { + return manager().Refresh(context.Background(), ctx.Response(), ctx.Request()) +} diff --git a/session_test.go b/session_test.go new file mode 100644 index 0000000..9aea1c6 --- /dev/null +++ b/session_test.go @@ -0,0 +1,80 @@ +package echosession + +import ( + "fmt" + "io/ioutil" + "net/http" + "net/http/httptest" + "testing" + + "github.com/labstack/echo" + "gopkg.in/session.v2" +) + +func TestSession(t *testing.T) { + cookieName := "test_echo_session" + + e := echo.New() + e.Use(New( + session.SetCookieName(cookieName), + session.SetSign([]byte("sign")), + )) + + e.GET("/", func(ctx echo.Context) error { + store := FromContext(ctx) + if ctx.QueryParam("login") == "1" { + foo, ok := store.Get("foo") + fmt.Fprintf(ctx.Response(), "%s:%v", foo, ok) + return nil + } + + store.Set("foo", "bar") + err := store.Save() + if err != nil { + t.Error(err) + return nil + } + fmt.Fprint(ctx.Response(), "ok") + return nil + }) + + w := httptest.NewRecorder() + req, err := http.NewRequest("GET", "/", nil) + if err != nil { + t.Error(err) + return + } + e.ServeHTTP(w, req) + + res := w.Result() + cookie := res.Cookies()[0] + if cookie.Name != cookieName { + t.Error("Not expected value:", cookie.Name) + return + } + + buf, _ := ioutil.ReadAll(res.Body) + res.Body.Close() + if string(buf) != "ok" { + t.Error("Not expected value:", string(buf)) + return + } + + req, err = http.NewRequest("GET", "/?login=1", nil) + if err != nil { + t.Error(err) + return + } + req.AddCookie(cookie) + + w = httptest.NewRecorder() + e.ServeHTTP(w, req) + + res = w.Result() + buf, _ = ioutil.ReadAll(res.Body) + res.Body.Close() + if string(buf) != "bar:true" { + t.Error("Not expected value:", string(buf)) + return + } +} |