From 930b639cc9cd2d2873302f30303378c0e53816a8 Mon Sep 17 00:00:00 2001 From: Wim Date: Sat, 18 Feb 2017 23:00:46 +0100 Subject: Update vendor --- .../labstack/echo/cookbook/auto-tls/server.go | 26 ++++++ .../labstack/echo/cookbook/cors/server.go | 38 +++++++++ .../labstack/echo/cookbook/crud/server.go | 75 +++++++++++++++++ .../echo/cookbook/embed-resources/server.go | 21 +++++ .../echo/cookbook/file-upload/multiple/server.go | 65 +++++++++++++++ .../echo/cookbook/file-upload/single/server.go | 59 +++++++++++++ .../echo/cookbook/google-app-engine/app-engine.go | 17 ++++ .../echo/cookbook/google-app-engine/app-managed.go | 25 ++++++ .../cookbook/google-app-engine/app-standalone.go | 24 ++++++ .../echo/cookbook/google-app-engine/app.go | 4 + .../echo/cookbook/google-app-engine/users.go | 54 ++++++++++++ .../echo/cookbook/google-app-engine/welcome.go | 31 +++++++ .../cookbook/graceful-shutdown/grace/server.go | 20 +++++ .../cookbook/graceful-shutdown/graceful/server.go | 21 +++++ .../labstack/echo/cookbook/hello-world/server.go | 25 ++++++ .../labstack/echo/cookbook/http2/server.go | 42 ++++++++++ .../labstack/echo/cookbook/jsonp/server.go | 35 ++++++++ .../echo/cookbook/jwt/custom-claims/server.go | 86 +++++++++++++++++++ .../echo/cookbook/jwt/map-claims/server.go | 69 +++++++++++++++ .../labstack/echo/cookbook/middleware/server.go | 82 ++++++++++++++++++ .../echo/cookbook/streaming-response/server.go | 45 ++++++++++ .../labstack/echo/cookbook/subdomains/server.go | 78 +++++++++++++++++ .../echo/cookbook/twitter/handler/handler.go | 14 ++++ .../labstack/echo/cookbook/twitter/handler/post.go | 73 ++++++++++++++++ .../labstack/echo/cookbook/twitter/handler/user.go | 97 ++++++++++++++++++++++ .../labstack/echo/cookbook/twitter/model/post.go | 12 +++ .../labstack/echo/cookbook/twitter/model/user.go | 13 +++ .../labstack/echo/cookbook/twitter/server.go | 52 ++++++++++++ .../echo/cookbook/websocket/gorilla/server.go | 47 +++++++++++ .../labstack/echo/cookbook/websocket/net/server.go | 41 +++++++++ 30 files changed, 1291 insertions(+) create mode 100644 vendor/github.com/labstack/echo/cookbook/auto-tls/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/cors/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/crud/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/embed-resources/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/file-upload/multiple/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/file-upload/single/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/google-app-engine/app-engine.go create mode 100644 vendor/github.com/labstack/echo/cookbook/google-app-engine/app-managed.go create mode 100644 vendor/github.com/labstack/echo/cookbook/google-app-engine/app-standalone.go create mode 100644 vendor/github.com/labstack/echo/cookbook/google-app-engine/app.go create mode 100644 vendor/github.com/labstack/echo/cookbook/google-app-engine/users.go create mode 100644 vendor/github.com/labstack/echo/cookbook/google-app-engine/welcome.go create mode 100644 vendor/github.com/labstack/echo/cookbook/graceful-shutdown/grace/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/graceful-shutdown/graceful/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/hello-world/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/http2/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/jsonp/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/jwt/custom-claims/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/jwt/map-claims/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/middleware/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/streaming-response/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/subdomains/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/twitter/handler/handler.go create mode 100644 vendor/github.com/labstack/echo/cookbook/twitter/handler/post.go create mode 100644 vendor/github.com/labstack/echo/cookbook/twitter/handler/user.go create mode 100644 vendor/github.com/labstack/echo/cookbook/twitter/model/post.go create mode 100644 vendor/github.com/labstack/echo/cookbook/twitter/model/user.go create mode 100644 vendor/github.com/labstack/echo/cookbook/twitter/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/websocket/gorilla/server.go create mode 100644 vendor/github.com/labstack/echo/cookbook/websocket/net/server.go (limited to 'vendor/github.com/labstack/echo/cookbook') diff --git a/vendor/github.com/labstack/echo/cookbook/auto-tls/server.go b/vendor/github.com/labstack/echo/cookbook/auto-tls/server.go new file mode 100644 index 00000000..4a8bbdfd --- /dev/null +++ b/vendor/github.com/labstack/echo/cookbook/auto-tls/server.go @@ -0,0 +1,26 @@ +package main + +import ( + "net/http" + + "golang.org/x/crypto/acme/autocert" + + "github.com/labstack/echo" + "github.com/labstack/echo/middleware" +) + +func main() { + e := echo.New() + // e.AutoTLSManager.HostPolicy = autocert.HostWhitelist("") + // Cache certificates + e.AutoTLSManager.Cache = autocert.DirCache("/var/www/.cache") + e.Use(middleware.Recover()) + e.Use(middleware.Logger()) + e.GET("/", func(c echo.Context) error { + return c.HTML(http.StatusOK, ` +

Welcome to Echo!

+

TLS certificates automatically installed from Let's Encrypt :)

+ `) + }) + e.Logger.Fatal(e.StartAutoTLS(":443")) +} diff --git a/vendor/github.com/labstack/echo/cookbook/cors/server.go b/vendor/github.com/labstack/echo/cookbook/cors/server.go new file mode 100644 index 00000000..0cc5c345 --- /dev/null +++ b/vendor/github.com/labstack/echo/cookbook/cors/server.go @@ -0,0 +1,38 @@ +package main + +import ( + "net/http" + + "github.com/labstack/echo" + "github.com/labstack/echo/middleware" +) + +var ( + users = []string{"Joe", "Veer", "Zion"} +) + +func getUsers(c echo.Context) error { + return c.JSON(http.StatusOK, users) +} + +func main() { + e := echo.New() + e.Use(middleware.Logger()) + e.Use(middleware.Recover()) + + // CORS default + // Allows requests from any origin wth GET, HEAD, PUT, POST or DELETE method. + // e.Use(middleware.CORS()) + + // CORS restricted + // Allows requests from any `https://labstack.com` or `https://labstack.net` origin + // wth GET, PUT, POST or DELETE method. + e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ + AllowOrigins: []string{"https://labstack.com", "https://labstack.net"}, + AllowMethods: []string{echo.GET, echo.PUT, echo.POST, echo.DELETE}, + })) + + e.GET("/api/users", getUsers) + + e.Logger.Fatal(e.Start(":1323")) +} diff --git a/vendor/github.com/labstack/echo/cookbook/crud/server.go b/vendor/github.com/labstack/echo/cookbook/crud/server.go new file mode 100644 index 00000000..fbb5c754 --- /dev/null +++ b/vendor/github.com/labstack/echo/cookbook/crud/server.go @@ -0,0 +1,75 @@ +package main + +import ( + "net/http" + "strconv" + + "github.com/labstack/echo" + "github.com/labstack/echo/middleware" +) + +type ( + user struct { + ID int `json:"id"` + Name string `json:"name"` + } +) + +var ( + users = map[int]*user{} + seq = 1 +) + +//---------- +// Handlers +//---------- + +func createUser(c echo.Context) error { + u := &user{ + ID: seq, + } + if err := c.Bind(u); err != nil { + return err + } + users[u.ID] = u + seq++ + return c.JSON(http.StatusCreated, u) +} + +func getUser(c echo.Context) error { + id, _ := strconv.Atoi(c.Param("id")) + return c.JSON(http.StatusOK, users[id]) +} + +func updateUser(c echo.Context) error { + u := new(user) + if err := c.Bind(u); err != nil { + return err + } + id, _ := strconv.Atoi(c.Param("id")) + users[id].Name = u.Name + return c.JSON(http.StatusOK, users[id]) +} + +func deleteUser(c echo.Context) error { + id, _ := strconv.Atoi(c.Param("id")) + delete(users, id) + return c.NoContent(http.StatusNoContent) +} + +func main() { + e := echo.New() + + // Middleware + e.Use(middleware.Logger()) + e.Use(middleware.Recover()) + + // Routes + e.POST("/users", createUser) + e.GET("/users/:id", getUser) + e.PUT("/users/:id", updateUser) + e.DELETE("/users/:id", deleteUser) + + // Start server + e.Logger.Fatal(e.Start(":1323")) +} diff --git a/vendor/github.com/labstack/echo/cookbook/embed-resources/server.go b/vendor/github.com/labstack/echo/cookbook/embed-resources/server.go new file mode 100644 index 00000000..e5b0c3db --- /dev/null +++ b/vendor/github.com/labstack/echo/cookbook/embed-resources/server.go @@ -0,0 +1,21 @@ +package main + +import ( + "net/http" + + rice "github.com/GeertJohan/go.rice" + "github.com/labstack/echo" +) + +func main() { + e := echo.New() + // the file server for rice. "app" is the folder where the files come from. + assetHandler := http.FileServer(rice.MustFindBox("app").HTTPBox()) + // serves the index.html from rice + e.GET("/", echo.WrapHandler(assetHandler)) + + // servers other static files + e.GET("/static/*", echo.WrapHandler(http.StripPrefix("/static/", assetHandler))) + + e.Logger.Fatal(e.Start(":1323")) +} diff --git a/vendor/github.com/labstack/echo/cookbook/file-upload/multiple/server.go b/vendor/github.com/labstack/echo/cookbook/file-upload/multiple/server.go new file mode 100644 index 00000000..cd0f54d3 --- /dev/null +++ b/vendor/github.com/labstack/echo/cookbook/file-upload/multiple/server.go @@ -0,0 +1,65 @@ +package main + +import ( + "fmt" + "io" + "os" + + "net/http" + + "github.com/labstack/echo" + "github.com/labstack/echo/middleware" +) + +func upload(c echo.Context) error { + // Read form fields + name := c.FormValue("name") + email := c.FormValue("email") + + //------------ + // Read files + //------------ + + // Multipart form + form, err := c.MultipartForm() + if err != nil { + return err + } + files := form.File["files"] + + for _, file := range files { + // Source + src, err := file.Open() + if err != nil { + return err + } + defer src.Close() + + // Destination + dst, err := os.Create(file.Filename) + if err != nil { + return err + } + defer dst.Close() + + // Copy + if _, err = io.Copy(dst, src); err != nil { + return err + } + + } + + return c.HTML(http.StatusOK, fmt.Sprintf("

Uploaded successfully %d files with fields name=%s and email=%s.

", len(files), name, email)) +} + +func main() { + e := echo.New() + + e.Use(middleware.Logger()) + e.Use(middleware.Recover()) + + e.Static("/", "public") + e.POST("/upload", upload) + + e.Logger.Fatal(e.Start(":1323")) +} diff --git a/vendor/github.com/labstack/echo/cookbook/file-upload/single/server.go b/vendor/github.com/labstack/echo/cookbook/file-upload/single/server.go new file mode 100644 index 00000000..1b84f220 --- /dev/null +++ b/vendor/github.com/labstack/echo/cookbook/file-upload/single/server.go @@ -0,0 +1,59 @@ +package main + +import ( + "fmt" + "io" + "os" + + "net/http" + + "github.com/labstack/echo" + "github.com/labstack/echo/middleware" +) + +func upload(c echo.Context) error { + // Read form fields + name := c.FormValue("name") + email := c.FormValue("email") + + //----------- + // Read file + //----------- + + // Source + file, err := c.FormFile("file") + if err != nil { + return err + } + src, err := file.Open() + if err != nil { + return err + } + defer src.Close() + + // Destination + dst, err := os.Create(file.Filename) + if err != nil { + return err + } + defer dst.Close() + + // Copy + if _, err = io.Copy(dst, src); err != nil { + return err + } + + return c.HTML(http.StatusOK, fmt.Sprintf("

File %s uploaded successfully with fields name=%s and email=%s.

", file.Filename, name, email)) +} + +func main() { + e := echo.New() + + e.Use(middleware.Logger()) + e.Use(middleware.Recover()) + + e.Static("/", "public") + e.POST("/upload", upload) + + e.Logger.Fatal(e.Start(":1323")) +} diff --git a/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-engine.go b/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-engine.go new file mode 100644 index 00000000..0c1db087 --- /dev/null +++ b/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-engine.go @@ -0,0 +1,17 @@ +// +build appengine + +package main + +import ( + "net/http" + + "github.com/labstack/echo" +) + +func createMux() *echo.Echo { + e := echo.New() + // note: we don't need to provide the middleware or static handlers, that's taken care of by the platform + // app engine has it's own "main" wrapper - we just need to hook echo into the default handler + http.Handle("/", e) + return e +} diff --git a/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-managed.go b/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-managed.go new file mode 100644 index 00000000..7b8eacf8 --- /dev/null +++ b/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-managed.go @@ -0,0 +1,25 @@ +// +build appenginevm + +package main + +import ( + "net/http" + + "github.com/labstack/echo" + "google.golang.org/appengine" +) + +func createMux() *echo.Echo { + e := echo.New() + // note: we don't need to provide the middleware or static handlers + // for the appengine vm version - that's taken care of by the platform + return e +} + +func main() { + // the appengine package provides a convenient method to handle the health-check requests + // and also run the app on the correct port. We just need to add Echo to the default handler + e := echo.New(":8080") + http.Handle("/", e) + appengine.Main() +} diff --git a/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-standalone.go b/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-standalone.go new file mode 100644 index 00000000..c3b44dc0 --- /dev/null +++ b/vendor/github.com/labstack/echo/cookbook/google-app-engine/app-standalone.go @@ -0,0 +1,24 @@ +// +build !appengine,!appenginevm + +package main + +import ( + "github.com/labstack/echo" + "github.com/labstack/echo/middleware" +) + +func createMux() *echo.Echo { + e := echo.New() + + e.Use(middleware.Recover()) + e.Use(middleware.Logger()) + e.Use(middleware.Gzip()) + + e.Static("/", "public") + + return e +} + +func main() { + e.Logger.Fatal(e.Start(":8080")) +} diff --git a/vendor/github.com/labstack/echo/cookbook/google-app-engine/app.go b/vendor/github.com/labstack/echo/cookbook/google-app-engine/app.go new file mode 100644 index 00000000..8d4d97a2 --- /dev/null +++ b/vendor/github.com/labstack/echo/cookbook/google-app-engine/app.go @@ -0,0 +1,4 @@ +package main + +// reference our echo instance and create it early +var e = createMux() diff --git a/vendor/github.com/labstack/echo/cookbook/google-app-engine/users.go b/vendor/github.com/labstack/echo/cookbook/google-app-engine/users.go new file mode 100644 index 00000000..19533e51 --- /dev/null +++ b/vendor/github.com/labstack/echo/cookbook/google-app-engine/users.go @@ -0,0 +1,54 @@ +package main + +import ( + "net/http" + + "github.com/labstack/echo" + "github.com/labstack/echo/middleware" +) + +type ( + user struct { + ID string `json:"id"` + Name string `json:"name"` + } +) + +var ( + users map[string]user +) + +func init() { + users = map[string]user{ + "1": user{ + ID: "1", + Name: "Wreck-It Ralph", + }, + } + + // hook into the echo instance to create an endpoint group + // and add specific middleware to it plus handlers + g := e.Group("/users") + g.Use(middleware.CORS()) + + g.POST("", createUser) + g.GET("", getUsers) + g.GET("/:id", getUser) +} + +func createUser(c echo.Context) error { + u := new(user) + if err := c.Bind(u); err != nil { + return err + } + users[u.ID] = *u + return c.JSON(http.StatusCreated, u) +} + +func getUsers(c echo.Context) error { + return c.JSON(http.StatusOK, users) +} + +func getUser(c echo.Context) error { + return c.JSON(http.StatusOK, users[c.Param("id")]) +} diff --git a/vendor/github.com/labstack/echo/cookbook/google-app-engine/welcome.go b/vendor/github.com/labstack/echo/cookbook/google-app-engine/welcome.go new file mode 100644 index 00000000..2639b209 --- /dev/null +++ b/vendor/github.com/labstack/echo/cookbook/google-app-engine/welcome.go @@ -0,0 +1,31 @@ +package main + +import ( + "html/template" + "io" + "net/http" + + "github.com/labstack/echo" +) + +type ( + Template struct { + templates *template.Template + } +) + +func init() { + t := &Template{ + templates: template.Must(template.ParseFiles("templates/welcome.html")), + } + e.Renderer = t + e.GET("/welcome", welcome) +} + +func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error { + return t.templates.ExecuteTemplate(w, name, data) +} + +func welcome(c echo.Context) error { + return c.Render(http.StatusOK, "welcome", "Joe") +} diff --git a/vendor/github.com/labstack/echo/cookbook/graceful-shutdown/grace/server.go b/vendor/github.com/labstack/echo/cookbook/graceful-shutdown/grace/server.go new file mode 100644 index 00000000..1f9937b0 --- /dev/null +++ b/vendor/github.com/labstack/echo/cookbook/graceful-shutdown/grace/server.go @@ -0,0 +1,20 @@ +package main + +import ( + "net/http" + + "github.com/facebookgo/grace/gracehttp" + "github.com/labstack/echo" +) + +func main() { + // Setup + e := echo.New() + e.GET("/", func(c echo.Context) error { + return c.String(http.StatusOK, "Six sick bricks tick") + }) + e.Server.Addr = ":1323" + + // Serve it like a boss + e.Logger.Fatal(gracehttp.Serve(e.Server)) +} diff --git a/vendor/github.com/labstack/echo/cookbook/graceful-shutdown/graceful/server.go b/vendor/github.com/labstack/echo/cookbook/graceful-shutdown/graceful/server.go new file mode 100644 index 00000000..39e7b634 --- /dev/null +++ b/vendor/github.com/labstack/echo/cookbook/graceful-shutdown/graceful/server.go @@ -0,0 +1,21 @@ +package main + +import ( + "net/http" + "time" + + "github.com/labstack/echo" + "github.com/tylerb/graceful" +) + +func main() { + // Setup + e := echo.New() + e.GET("/", func(c echo.Context) error { + return c.String(http.StatusOK, "Sue sews rose on slow joe crows nose") + }) + e.Server.Addr = ":1323" + + // Serve it like a boss + graceful.ListenAndServe(e.Server, 5*time.Second) +} diff --git a/vendor/github.com/labstack/echo/cookbook/hello-world/server.go b/vendor/github.com/labstack/echo/cookbook/hello-world/server.go new file mode 100644 index 00000000..06e0718b --- /dev/null +++ b/vendor/github.com/labstack/echo/cookbook/hello-world/server.go @@ -0,0 +1,25 @@ +package main + +import ( + "net/http" + + "github.com/labstack/echo" + "github.com/labstack/echo/middleware" +) + +func main() { + // Echo instance + e := echo.New() + + // Middleware + e.Use(middleware.Logger()) + e.Use(middleware.Recover()) + + // Route => handler + e.GET("/", func(c echo.Context) error { + return c.String(http.StatusOK, "Hello, World!\n") + }) + + // Start server + e.Logger.Fatal(e.Start(":1323")) +} diff --git a/vendor/github.com/labstack/echo/cookbook/http2/server.go b/vendor/github.com/labstack/echo/cookbook/http2/server.go new file mode 100644 index 00000000..8db989c4 --- /dev/null +++ b/vendor/github.com/labstack/echo/cookbook/http2/server.go @@ -0,0 +1,42 @@ +package main + +import ( + "fmt" + "net/http" + "time" + + "github.com/labstack/echo" +) + +func request(c echo.Context) error { + req := c.Request() + format := "
Request Information\n\nProtocol: %s\nHost: %s\nRemote Address: %s\nMethod: %s\nPath: %s\n
" + return c.HTML(http.StatusOK, fmt.Sprintf(format, req.Proto, req.Host, req.RemoteAddr, req.Method, req.URL.Path)) +} + +func stream(c echo.Context) error { + res := c.Response() + gone := res.CloseNotify() + res.Header().Set(echo.HeaderContentType, echo.MIMETextHTMLCharsetUTF8) + res.WriteHeader(http.StatusOK) + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + + fmt.Fprint(res, "
Clock Stream\n\n")
+	for {
+		fmt.Fprintf(res, "%v\n", time.Now())
+		res.Flush()
+		select {
+		case <-ticker.C:
+		case <-gone:
+			break
+		}
+	}
+}
+
+func main() {
+	e := echo.New()
+	e.GET("/request", request)
+	e.GET("/stream", stream)
+	e.Logger.Fatal(e.StartTLS(":1323", "cert.pem", "key.pem"))
+}
diff --git a/vendor/github.com/labstack/echo/cookbook/jsonp/server.go b/vendor/github.com/labstack/echo/cookbook/jsonp/server.go
new file mode 100644
index 00000000..ba46bab0
--- /dev/null
+++ b/vendor/github.com/labstack/echo/cookbook/jsonp/server.go
@@ -0,0 +1,35 @@
+package main
+
+import (
+	"math/rand"
+	"net/http"
+	"time"
+
+	"github.com/labstack/echo"
+	"github.com/labstack/echo/middleware"
+)
+
+func main() {
+	e := echo.New()
+	e.Use(middleware.Logger())
+	e.Use(middleware.Recover())
+
+	e.Static("/", "public")
+
+	// JSONP
+	e.GET("/jsonp", func(c echo.Context) error {
+		callback := c.QueryParam("callback")
+		var content struct {
+			Response  string    `json:"response"`
+			Timestamp time.Time `json:"timestamp"`
+			Random    int       `json:"random"`
+		}
+		content.Response = "Sent via JSONP"
+		content.Timestamp = time.Now().UTC()
+		content.Random = rand.Intn(1000)
+		return c.JSONP(http.StatusOK, callback, &content)
+	})
+
+	// Start server
+	e.Logger.Fatal(e.Start(":1323"))
+}
diff --git a/vendor/github.com/labstack/echo/cookbook/jwt/custom-claims/server.go b/vendor/github.com/labstack/echo/cookbook/jwt/custom-claims/server.go
new file mode 100644
index 00000000..b3a13205
--- /dev/null
+++ b/vendor/github.com/labstack/echo/cookbook/jwt/custom-claims/server.go
@@ -0,0 +1,86 @@
+package main
+
+import (
+	"net/http"
+	"time"
+
+	jwt "github.com/dgrijalva/jwt-go"
+	"github.com/labstack/echo"
+	"github.com/labstack/echo/middleware"
+)
+
+// jwtCustomClaims are custom claims extending default ones.
+type jwtCustomClaims struct {
+	Name  string `json:"name"`
+	Admin bool   `json:"admin"`
+	jwt.StandardClaims
+}
+
+func login(c echo.Context) error {
+	username := c.FormValue("username")
+	password := c.FormValue("password")
+
+	if username == "jon" && password == "shhh!" {
+
+		// Set custom claims
+		claims := &jwtCustomClaims{
+			"Jon Snow",
+			true,
+			jwt.StandardClaims{
+				ExpiresAt: time.Now().Add(time.Hour * 72).Unix(),
+			},
+		}
+
+		// Create token with claims
+		token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
+
+		// Generate encoded token and send it as response.
+		t, err := token.SignedString([]byte("secret"))
+		if err != nil {
+			return err
+		}
+		return c.JSON(http.StatusOK, echo.Map{
+			"token": t,
+		})
+	}
+
+	return echo.ErrUnauthorized
+}
+
+func accessible(c echo.Context) error {
+	return c.String(http.StatusOK, "Accessible")
+}
+
+func restricted(c echo.Context) error {
+	user := c.Get("user").(*jwt.Token)
+	claims := user.Claims.(*jwtCustomClaims)
+	name := claims.Name
+	return c.String(http.StatusOK, "Welcome "+name+"!")
+}
+
+func main() {
+	e := echo.New()
+
+	// Middleware
+	e.Use(middleware.Logger())
+	e.Use(middleware.Recover())
+
+	// Login route
+	e.POST("/login", login)
+
+	// Unauthenticated route
+	e.GET("/", accessible)
+
+	// Restricted group
+	r := e.Group("/restricted")
+
+	// Configure middleware with the custom claims type
+	config := middleware.JWTConfig{
+		Claims:     &jwtCustomClaims{},
+		SigningKey: []byte("secret"),
+	}
+	r.Use(middleware.JWTWithConfig(config))
+	r.GET("", restricted)
+
+	e.Logger.Fatal(e.Start(":1323"))
+}
diff --git a/vendor/github.com/labstack/echo/cookbook/jwt/map-claims/server.go b/vendor/github.com/labstack/echo/cookbook/jwt/map-claims/server.go
new file mode 100644
index 00000000..678be490
--- /dev/null
+++ b/vendor/github.com/labstack/echo/cookbook/jwt/map-claims/server.go
@@ -0,0 +1,69 @@
+package main
+
+import (
+	"net/http"
+	"time"
+
+	jwt "github.com/dgrijalva/jwt-go"
+	"github.com/labstack/echo"
+	"github.com/labstack/echo/middleware"
+)
+
+func login(c echo.Context) error {
+	username := c.FormValue("username")
+	password := c.FormValue("password")
+
+	if username == "jon" && password == "shhh!" {
+		// Create token
+		token := jwt.New(jwt.SigningMethodHS256)
+
+		// Set claims
+		claims := token.Claims.(jwt.MapClaims)
+		claims["name"] = "Jon Snow"
+		claims["admin"] = true
+		claims["exp"] = time.Now().Add(time.Hour * 72).Unix()
+
+		// Generate encoded token and send it as response.
+		t, err := token.SignedString([]byte("secret"))
+		if err != nil {
+			return err
+		}
+		return c.JSON(http.StatusOK, map[string]string{
+			"token": t,
+		})
+	}
+
+	return echo.ErrUnauthorized
+}
+
+func accessible(c echo.Context) error {
+	return c.String(http.StatusOK, "Accessible")
+}
+
+func restricted(c echo.Context) error {
+	user := c.Get("user").(*jwt.Token)
+	claims := user.Claims.(jwt.MapClaims)
+	name := claims["name"].(string)
+	return c.String(http.StatusOK, "Welcome "+name+"!")
+}
+
+func main() {
+	e := echo.New()
+
+	// Middleware
+	e.Use(middleware.Logger())
+	e.Use(middleware.Recover())
+
+	// Login route
+	e.POST("/login", login)
+
+	// Unauthenticated route
+	e.GET("/", accessible)
+
+	// Restricted group
+	r := e.Group("/restricted")
+	r.Use(middleware.JWT([]byte("secret")))
+	r.GET("", restricted)
+
+	e.Logger.Fatal(e.Start(":1323"))
+}
diff --git a/vendor/github.com/labstack/echo/cookbook/middleware/server.go b/vendor/github.com/labstack/echo/cookbook/middleware/server.go
new file mode 100644
index 00000000..2f21df50
--- /dev/null
+++ b/vendor/github.com/labstack/echo/cookbook/middleware/server.go
@@ -0,0 +1,82 @@
+package main
+
+import (
+	"net/http"
+	"strconv"
+	"sync"
+	"time"
+
+	"github.com/labstack/echo"
+)
+
+type (
+	Stats struct {
+		Uptime       time.Time      `json:"uptime"`
+		RequestCount uint64         `json:"requestCount"`
+		Statuses     map[string]int `json:"statuses"`
+		mutex        sync.RWMutex
+	}
+)
+
+func NewStats() *Stats {
+	return &Stats{
+		Uptime:   time.Now(),
+		Statuses: make(map[string]int),
+	}
+}
+
+// Process is the middleware function.
+func (s *Stats) Process(next echo.HandlerFunc) echo.HandlerFunc {
+	return func(c echo.Context) error {
+		if err := next(c); err != nil {
+			c.Error(err)
+		}
+		s.mutex.Lock()
+		defer s.mutex.Unlock()
+		s.RequestCount++
+		status := strconv.Itoa(c.Response().Status)
+		s.Statuses[status]++
+		return nil
+	}
+}
+
+// Handle is the endpoint to get stats.
+func (s *Stats) Handle(c echo.Context) error {
+	s.mutex.RLock()
+	defer s.mutex.RUnlock()
+	return c.JSON(http.StatusOK, s)
+}
+
+// ServerHeader middleware adds a `Server` header to the response.
+func ServerHeader(next echo.HandlerFunc) echo.HandlerFunc {
+	return func(c echo.Context) error {
+		c.Response().Header().Set(echo.HeaderServer, "Echo/3.0")
+		return next(c)
+	}
+}
+
+func main() {
+	e := echo.New()
+
+	// Debug mode
+	e.Debug = true
+
+	//-------------------
+	// Custom middleware
+	//-------------------
+	// Stats
+	s := NewStats()
+	e.Use(s.Process)
+	e.GET("/stats", s.Handle) // Endpoint to get stats
+
+	// Server header
+	e.Use(ServerHeader)
+
+	// Handler
+	e.GET("/", func(c echo.Context) error {
+		return c.String(http.StatusOK, "Hello, World!")
+	})
+
+	// Start server
+	e.Logger.Fatal(e.Start(":1323"))
+}
diff --git a/vendor/github.com/labstack/echo/cookbook/streaming-response/server.go b/vendor/github.com/labstack/echo/cookbook/streaming-response/server.go
new file mode 100644
index 00000000..a3a679ef
--- /dev/null
+++ b/vendor/github.com/labstack/echo/cookbook/streaming-response/server.go
@@ -0,0 +1,45 @@
+package main
+
+import (
+	"net/http"
+	"time"
+
+	"encoding/json"
+
+	"github.com/labstack/echo"
+)
+
+type (
+	Geolocation struct {
+		Altitude  float64
+		Latitude  float64
+		Longitude float64
+	}
+)
+
+var (
+	locations = []Geolocation{
+		{-97, 37.819929, -122.478255},
+		{1899, 39.096849, -120.032351},
+		{2619, 37.865101, -119.538329},
+		{42, 33.812092, -117.918974},
+		{15, 37.77493, -122.419416},
+	}
+)
+
+func main() {
+	e := echo.New()
+	e.GET("/", func(c echo.Context) error {
+		c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
+		c.Response().WriteHeader(http.StatusOK)
+		for _, l := range locations {
+			if err := json.NewEncoder(c.Response()).Encode(l); err != nil {
+				return err
+			}
+			c.Response().Flush()
+			time.Sleep(1 * time.Second)
+		}
+		return nil
+	})
+	e.Logger.Fatal(e.Start(":1323"))
+}
diff --git a/vendor/github.com/labstack/echo/cookbook/subdomains/server.go b/vendor/github.com/labstack/echo/cookbook/subdomains/server.go
new file mode 100644
index 00000000..ef4f65f9
--- /dev/null
+++ b/vendor/github.com/labstack/echo/cookbook/subdomains/server.go
@@ -0,0 +1,78 @@
+package main
+
+import (
+	"net/http"
+
+	"github.com/labstack/echo"
+	"github.com/labstack/echo/middleware"
+)
+
+type (
+	Host struct {
+		Echo *echo.Echo
+	}
+)
+
+func main() {
+	// Hosts
+	hosts := make(map[string]*Host)
+
+	//-----
+	// API
+	//-----
+
+	api := echo.New()
+	api.Use(middleware.Logger())
+	api.Use(middleware.Recover())
+
+	hosts["api.localhost:1323"] = &Host{api}
+
+	api.GET("/", func(c echo.Context) error {
+		return c.String(http.StatusOK, "API")
+	})
+
+	//------
+	// Blog
+	//------
+
+	blog := echo.New()
+	blog.Use(middleware.Logger())
+	blog.Use(middleware.Recover())
+
+	hosts["blog.localhost:1323"] = &Host{blog}
+
+	blog.GET("/", func(c echo.Context) error {
+		return c.String(http.StatusOK, "Blog")
+	})
+
+	//---------
+	// Website
+	//---------
+
+	site := echo.New()
+	site.Use(middleware.Logger())
+	site.Use(middleware.Recover())
+
+	hosts["localhost:1323"] = &Host{site}
+
+	site.GET("/", func(c echo.Context) error {
+		return c.String(http.StatusOK, "Website")
+	})
+
+	// Server
+	e := echo.New()
+	e.Any("/*", func(c echo.Context) (err error) {
+		req := c.Request()
+		res := c.Response()
+		host := hosts[req.Host]
+
+		if host == nil {
+			err = echo.ErrNotFound
+		} else {
+			host.Echo.ServeHTTP(res, req)
+		}
+
+		return
+	})
+	e.Logger.Fatal(e.Start(":1323"))
+}
diff --git a/vendor/github.com/labstack/echo/cookbook/twitter/handler/handler.go b/vendor/github.com/labstack/echo/cookbook/twitter/handler/handler.go
new file mode 100644
index 00000000..263c5e21
--- /dev/null
+++ b/vendor/github.com/labstack/echo/cookbook/twitter/handler/handler.go
@@ -0,0 +1,14 @@
+package handler
+
+import mgo "gopkg.in/mgo.v2"
+
+type (
+	Handler struct {
+		DB *mgo.Session
+	}
+)
+
+const (
+	// Key (Should come from somewhere else).
+	Key = "secret"
+)
diff --git a/vendor/github.com/labstack/echo/cookbook/twitter/handler/post.go b/vendor/github.com/labstack/echo/cookbook/twitter/handler/post.go
new file mode 100644
index 00000000..b1428a30
--- /dev/null
+++ b/vendor/github.com/labstack/echo/cookbook/twitter/handler/post.go
@@ -0,0 +1,73 @@
+package handler
+
+import (
+	"net/http"
+	"strconv"
+
+	"github.com/labstack/echo"
+	"github.com/labstack/echo/cookbook/twitter/model"
+	mgo "gopkg.in/mgo.v2"
+	"gopkg.in/mgo.v2/bson"
+)
+
+func (h *Handler) CreatePost(c echo.Context) (err error) {
+	u := &model.User{
+		ID: bson.ObjectIdHex(userIDFromToken(c)),
+	}
+	p := &model.Post{
+		ID:   bson.NewObjectId(),
+		From: u.ID.Hex(),
+	}
+	if err = c.Bind(p); err != nil {
+		return
+	}
+
+	// Validation
+	if p.To == "" || p.Message == "" {
+		return &echo.HTTPError{Code: http.StatusBadRequest, Message: "invalid to or message fields"}
+	}
+
+	// Find user from database
+	db := h.DB.Clone()
+	defer db.Close()
+	if err = db.DB("twitter").C("users").FindId(u.ID).One(u); err != nil {
+		if err == mgo.ErrNotFound {
+			return echo.ErrNotFound
+		}
+		return
+	}
+
+	// Save post in database
+	if err = db.DB("twitter").C("posts").Insert(p); err != nil {
+		return
+	}
+	return c.JSON(http.StatusCreated, p)
+}
+
+func (h *Handler) FetchPost(c echo.Context) (err error) {
+	userID := userIDFromToken(c)
+	page, _ := strconv.Atoi(c.QueryParam("page"))
+	limit, _ := strconv.Atoi(c.QueryParam("limit"))
+
+	// Defaults
+	if page == 0 {
+		page = 1
+	}
+	if limit == 0 {
+		limit = 100
+	}
+
+	// Retrieve posts from database
+	posts := []*model.Post{}
+	db := h.DB.Clone()
+	if err = db.DB("twitter").C("posts").
+		Find(bson.M{"to": userID}).
+		Skip((page - 1) * limit).
+		Limit(limit).
+		All(&posts); err != nil {
+		return
+	}
+	defer db.Close()
+
+	return c.JSON(http.StatusOK, posts)
+}
diff --git a/vendor/github.com/labstack/echo/cookbook/twitter/handler/user.go b/vendor/github.com/labstack/echo/cookbook/twitter/handler/user.go
new file mode 100644
index 00000000..a34d2f4e
--- /dev/null
+++ b/vendor/github.com/labstack/echo/cookbook/twitter/handler/user.go
@@ -0,0 +1,97 @@
+package handler
+
+import (
+	"net/http"
+	"time"
+
+	jwt "github.com/dgrijalva/jwt-go"
+	"github.com/labstack/echo"
+	"github.com/labstack/echo/cookbook/twitter/model"
+	mgo "gopkg.in/mgo.v2"
+	"gopkg.in/mgo.v2/bson"
+)
+
+func (h *Handler) Signup(c echo.Context) (err error) {
+	// Bind
+	u := &model.User{ID: bson.NewObjectId()}
+	if err = c.Bind(u); err != nil {
+		return
+	}
+
+	// Validate
+	if u.Email == "" || u.Password == "" {
+		return &echo.HTTPError{Code: http.StatusBadRequest, Message: "invalid email or password"}
+	}
+
+	// Save user
+	db := h.DB.Clone()
+	defer db.Close()
+	if err = db.DB("twitter").C("users").Insert(u); err != nil {
+		return
+	}
+
+	return c.JSON(http.StatusCreated, u)
+}
+
+func (h *Handler) Login(c echo.Context) (err error) {
+	// Bind
+	u := new(model.User)
+	if err = c.Bind(u); err != nil {
+		return
+	}
+
+	// Find user
+	db := h.DB.Clone()
+	defer db.Close()
+	if err = db.DB("twitter").C("users").
+		Find(bson.M{"email": u.Email, "password": u.Password}).One(u); err != nil {
+		if err == mgo.ErrNotFound {
+			return &echo.HTTPError{Code: http.StatusUnauthorized, Message: "invalid email or password"}
+		}
+		return
+	}
+
+	//-----
+	// JWT
+	//-----
+
+	// Create token
+	token := jwt.New(jwt.SigningMethodHS256)
+
+	// Set claims
+	claims := token.Claims.(jwt.MapClaims)
+	claims["id"] = u.ID
+	claims["exp"] = time.Now().Add(time.Hour * 72).Unix()
+
+	// Generate encoded token and send it as response
+	u.Token, err = token.SignedString([]byte(Key))
+	if err != nil {
+		return err
+	}
+
+	u.Password = "" // Don't send password
+	return c.JSON(http.StatusOK, u)
+}
+
+func (h *Handler) Follow(c echo.Context) (err error) {
+	userID := userIDFromToken(c)
+	id := c.Param("id")
+
+	// Add a follower to user
+	db := h.DB.Clone()
+	defer db.Close()
+	if err = db.DB("twitter").C("users").
+		UpdateId(bson.ObjectIdHex(id), bson.M{"$addToSet": bson.M{"followers": userID}}); err != nil {
+		if err == mgo.ErrNotFound {
+			return echo.ErrNotFound
+		}
+	}
+
+	return
+}
+
+func userIDFromToken(c echo.Context) string {
+	user := c.Get("user").(*jwt.Token)
+	claims := user.Claims.(jwt.MapClaims)
+	return claims["id"].(string)
+}
diff --git a/vendor/github.com/labstack/echo/cookbook/twitter/model/post.go b/vendor/github.com/labstack/echo/cookbook/twitter/model/post.go
new file mode 100644
index 00000000..7344296e
--- /dev/null
+++ b/vendor/github.com/labstack/echo/cookbook/twitter/model/post.go
@@ -0,0 +1,12 @@
+package model
+
+import "gopkg.in/mgo.v2/bson"
+
+type (
+	Post struct {
+		ID      bson.ObjectId `json:"id" bson:"_id,omitempty"`
+		To      string        `json:"to" bson:"to"`
+		From    string        `json:"from" bson:"from"`
+		Message string        `json:"message" bson:"message"`
+	}
+)
diff --git a/vendor/github.com/labstack/echo/cookbook/twitter/model/user.go b/vendor/github.com/labstack/echo/cookbook/twitter/model/user.go
new file mode 100644
index 00000000..e063c89b
--- /dev/null
+++ b/vendor/github.com/labstack/echo/cookbook/twitter/model/user.go
@@ -0,0 +1,13 @@
+package model
+
+import "gopkg.in/mgo.v2/bson"
+
+type (
+	User struct {
+		ID        bson.ObjectId `json:"id" bson:"_id,omitempty"`
+		Email     string        `json:"email" bson:"email"`
+		Password  string        `json:"password,omitempty" bson:"password"`
+		Token     string        `json:"token,omitempty" bson:"-"`
+		Followers []string      `json:"followers,omitempty" bson:"followers,omitempty"`
+	}
+)
diff --git a/vendor/github.com/labstack/echo/cookbook/twitter/server.go b/vendor/github.com/labstack/echo/cookbook/twitter/server.go
new file mode 100644
index 00000000..22db7aa0
--- /dev/null
+++ b/vendor/github.com/labstack/echo/cookbook/twitter/server.go
@@ -0,0 +1,52 @@
+package main
+
+import (
+	"github.com/labstack/echo"
+	"github.com/labstack/echo/cookbook/twitter/handler"
+	"github.com/labstack/echo/middleware"
+	"github.com/labstack/gommon/log"
+	mgo "gopkg.in/mgo.v2"
+)
+
+func main() {
+	e := echo.New()
+	e.Logger.SetLevel(log.ERROR)
+	e.Use(middleware.Logger())
+	e.Use(middleware.JWTWithConfig(middleware.JWTConfig{
+		SigningKey: []byte(handler.Key),
+		Skipper: func(c echo.Context) bool {
+			// Skip authentication for and signup login requests
+			if c.Path() == "/login" || c.Path() == "/signup" {
+				return true
+			}
+			return false
+		},
+	}))
+
+	// Database connection
+	db, err := mgo.Dial("localhost")
+	if err != nil {
+		e.Logger.Fatal(err)
+	}
+
+	// Create indices
+	if err = db.Copy().DB("twitter").C("users").EnsureIndex(mgo.Index{
+		Key:    []string{"email"},
+		Unique: true,
+	}); err != nil {
+		log.Fatal(err)
+	}
+
+	// Initialize handler
+	h := &handler.Handler{DB: db}
+
+	// Routes
+	e.POST("/signup", h.Signup)
+	e.POST("/login", h.Login)
+	e.POST("/follow/:id", h.Follow)
+	e.POST("/posts", h.CreatePost)
+	e.GET("/feed", h.FetchPost)
+
+	// Start server
+	e.Logger.Fatal(e.Start(":1323"))
+}
diff --git a/vendor/github.com/labstack/echo/cookbook/websocket/gorilla/server.go b/vendor/github.com/labstack/echo/cookbook/websocket/gorilla/server.go
new file mode 100644
index 00000000..e9d52dbb
--- /dev/null
+++ b/vendor/github.com/labstack/echo/cookbook/websocket/gorilla/server.go
@@ -0,0 +1,47 @@
+package main
+
+import (
+	"fmt"
+	"log"
+
+	"github.com/labstack/echo"
+
+	"github.com/gorilla/websocket"
+	"github.com/labstack/echo/middleware"
+)
+
+var (
+	upgrader = websocket.Upgrader{}
+)
+
+func hello(c echo.Context) error {
+	ws, err := upgrader.Upgrade(c.Response(), c.Request(), nil)
+	if err != nil {
+		return err
+	}
+	defer ws.Close()
+
+	for {
+		// Write
+		err := ws.WriteMessage(websocket.TextMessage, []byte("Hello, Client!"))
+		if err != nil {
+			log.Fatal(err)
+		}
+
+		// Read
+		_, msg, err := ws.ReadMessage()
+		if err != nil {
+			log.Fatal(err)
+		}
+		fmt.Printf("%s\n", msg)
+	}
+}
+
+func main() {
+	e := echo.New()
+	e.Use(middleware.Logger())
+	e.Use(middleware.Recover())
+	e.Static("/", "../public")
+	e.GET("/ws", hello)
+	e.Logger.Fatal(e.Start(":1323"))
+}
diff --git a/vendor/github.com/labstack/echo/cookbook/websocket/net/server.go b/vendor/github.com/labstack/echo/cookbook/websocket/net/server.go
new file mode 100644
index 00000000..aa746030
--- /dev/null
+++ b/vendor/github.com/labstack/echo/cookbook/websocket/net/server.go
@@ -0,0 +1,41 @@
+package main
+
+import (
+	"fmt"
+	"log"
+
+	"github.com/labstack/echo"
+	"github.com/labstack/echo/middleware"
+	"golang.org/x/net/websocket"
+)
+
+func hello(c echo.Context) error {
+	websocket.Handler(func(ws *websocket.Conn) {
+		defer ws.Close()
+		for {
+			// Write
+			err := websocket.Message.Send(ws, "Hello, Client!")
+			if err != nil {
+				log.Fatal(err)
+			}
+
+			// Read
+			msg := ""
+			err = websocket.Message.Receive(ws, &msg)
+			if err != nil {
+				log.Fatal(err)
+			}
+			fmt.Printf("%s\n", msg)
+		}
+	}).ServeHTTP(c.Response(), c.Request())
+	return nil
+}
+
+func main() {
+	e := echo.New()
+	e.Use(middleware.Logger())
+	e.Use(middleware.Recover())
+	e.Static("/", "../public")
+	e.GET("/ws", hello)
+	e.Logger.Fatal(e.Start(":1323"))
+}
-- 
cgit v1.2.3