diff --git a/Gopkg.lock b/Gopkg.lock index e07a8f4..d55222a 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -3,9 +3,15 @@ [[projects]] branch = "master" - name = "dmitri.shuralyov.com/kebabcase" + name = "dmitri.shuralyov.com/text/kebabcase" packages = ["."] - revision = "bf160e40a7918fbe9dc3cc841a023d87242bd2eb" + revision = "40e40b42552a9cb37d6e98f4ad31f63ae53ea43a" + +[[projects]] + branch = "master" + name = "github.com/cockroachdb/cockroach-go" + packages = ["crdb"] + revision = "59c0560478b705bf9bd12f9252224a0fad7c87df" [[projects]] name = "github.com/davecgh/go-spew" @@ -14,16 +20,16 @@ version = "v1.1.0" [[projects]] - branch = "master" name = "github.com/daviddengcn/go-colortext" packages = ["."] revision = "17e75f6184bc9e727756cd0d82e0af58b1fc7191" + version = "1.0.0" [[projects]] name = "github.com/fatih/color" packages = ["."] - revision = "570b54cabe6b8eb0bc2dfce68d964677d63b5260" - version = "v1.5.0" + revision = "507f6050b8568533fb3f5504de8e5205fa62a114" + version = "v1.6.0" [[projects]] name = "github.com/fatih/structs" @@ -40,32 +46,44 @@ [[projects]] name = "github.com/gobuffalo/buffalo" packages = ["render"] - revision = "4220930a985fea6cd3f207efa1f822940ab08c2b" - version = "v0.10.2" + revision = "bfa77a8652f7c8ec0bede640656c8add3cb230c2" + version = "v0.10.3" [[projects]] name = "github.com/gobuffalo/envy" packages = ["."] - revision = "e613c80275b86293880eddeb27417c9a7c670ff3" - version = "v1.3.0" + revision = "197631a8f4c665cf7eeb157d5bc00d988419c4e7" + version = "v1.5.0" [[projects]] name = "github.com/gobuffalo/packr" packages = ["."] - revision = "60f8243a040d5c5c80339403322a5a6fb56c2333" - version = "v1.9.10" + revision = "6434a292ac52e6964adebfdce3f9ce6d9f16be01" + version = "v1.10.4" [[projects]] name = "github.com/gobuffalo/plush" packages = [".","ast","lexer","parser","token"] - revision = "f15814743c4d25c1bc5371e75d1ef51c9afdddba" - version = "v3.6.0" + revision = "a3df688902c0ccd9fa712ed5a1da6b78e7efab0d" + version = "v3.6.12" [[projects]] name = "github.com/gobuffalo/tags" packages = [".","form","form/bootstrap"] - revision = "fd130d3e089cc2ae7285f7b4f3e45fd3f1aa3482" - version = "v1.9.0" + revision = "ab52126649ee51d858d9525f60bc1618592433b0" + version = "v2.0.0" + +[[projects]] + name = "github.com/gobuffalo/uuid" + packages = ["."] + revision = "3a9fb6c5c481d4886f1e9323c61ad743fb955860" + version = "v2.0.0" + +[[projects]] + name = "github.com/gobuffalo/validate" + packages = [".","validators"] + revision = "42d8db6e06e617cdedcc7a849d6690a2cb5a8d28" + version = "v2.0.0" [[projects]] name = "github.com/gorilla/context" @@ -76,14 +94,14 @@ [[projects]] name = "github.com/gorilla/mux" packages = ["."] - revision = "7f08801859139f86dfafd1c296e2cba9a80d292e" - version = "v1.6.0" + revision = "53c1911da2b537f792e7cafcb446b05ffe33b996" + version = "v1.6.1" [[projects]] branch = "master" name = "github.com/jmoiron/sqlx" packages = [".","reflectx"] - revision = "de8647470aafe4854c976707c431dbe1eb2822c6" + revision = "cf35089a197953c69420c8d0cecda90809764b1d" [[projects]] name = "github.com/joho/godotenv" @@ -95,7 +113,7 @@ branch = "master" name = "github.com/lib/pq" packages = [".","oid"] - revision = "83612a56d3dd153a94a629cd64925371c9adad78" + revision = "88edab0803230a3898347e77b474f8c1820a1f20" [[projects]] branch = "master" @@ -107,25 +125,25 @@ branch = "master" name = "github.com/markbates/inflect" packages = ["."] - revision = "a12c3aec81a6a938bf584a4bac567afed9256586" + revision = "3e32b42850a9f09fac18a6c09bbd04325f51f732" [[projects]] name = "github.com/markbates/pop" - packages = [".","columns","fizz","fizz/translators"] - revision = "b75753936c38f382be88b1ea4221b771994996c9" - version = "3.41.10" + packages = [".","associations","columns","fizz","fizz/translators"] + revision = "f230643ae0f8fa01e9444c2fb857ba1f1a78eb1f" + version = "v4.0.0" [[projects]] - branch = "master" name = "github.com/markbates/validate" - packages = [".","validators"] + packages = ["."] revision = "cd8cc34c703420d6b084fbbfd5085e8e71c5b830" + version = "v1.0.0" [[projects]] branch = "master" name = "github.com/mattn/anko" packages = ["ast","builtins","builtins/encoding/json","builtins/errors","builtins/flag","builtins/fmt","builtins/github.com/daviddengcn/go-colortext","builtins/io","builtins/io/ioutil","builtins/math","builtins/math/big","builtins/math/rand","builtins/net","builtins/net/http","builtins/net/url","builtins/os","builtins/os/exec","builtins/os/signal","builtins/path","builtins/path/filepath","builtins/regexp","builtins/runtime","builtins/sort","builtins/strconv","builtins/strings","builtins/time","parser","vm"] - revision = "3b446c7d031bdd754fc0183f599af173cd996715" + revision = "d5441ca3f0c7e071a9ede864f9db2cc652690f42" [[projects]] name = "github.com/mattn/go-colorable" @@ -142,8 +160,8 @@ [[projects]] name = "github.com/mattn/go-sqlite3" packages = ["."] - revision = "ed69081a91fd053f17672236b0dd52ba7485e1a3" - version = "v1.4.0" + revision = "6c771bb9887719704b210e87e934f08be014bdb1" + version = "v1.6.0" [[projects]] branch = "master" @@ -170,10 +188,10 @@ version = "v1.0.0" [[projects]] - branch = "master" name = "github.com/russross/blackfriday" packages = ["."] - revision = "6d1ef893fcb01b4f50cb6e57ed7df3e2e627b6b2" + revision = "55d61fa8aa702f59229e6cff85793c22e580eaf5" + version = "v1.5.1" [[projects]] name = "github.com/satori/go.uuid" @@ -187,10 +205,10 @@ revision = "a683aaf2d516deecd70cad0c72e3ca773ecfcef0" [[projects]] - branch = "master" name = "github.com/sergi/go-diff" packages = ["diffmatchpatch"] revision = "1744e2970ca51c86172c8190fadad617561ed6e7" + version = "v1.0.0" [[projects]] branch = "master" @@ -202,7 +220,7 @@ branch = "master" name = "github.com/shurcooL/go" packages = ["parserutil","printerutil","reflectfind","reflectsource"] - revision = "004faa6b0118cf52635363b72b51cdcc297800a2" + revision = "364c5ae8518b51f5fda954762864d6f4d5c30c89" [[projects]] branch = "master" @@ -214,7 +232,7 @@ branch = "master" name = "github.com/shurcooL/graphql" packages = ["ident"] - revision = "d0549edd16dceb6939e538fdb1b4f2ec7ee816cc" + revision = "3d276b9dcc6b1e0adf19557a8de5cb8632c07697" [[projects]] branch = "master" @@ -232,7 +250,7 @@ branch = "master" name = "github.com/shurcooL/octiconssvg" packages = ["."] - revision = "38b02129bb6460858e11f90798a3832da1e502bd" + revision = "91d14858bf8188ba5143d67a3a677ea559000b0a" [[projects]] branch = "master" @@ -240,6 +258,12 @@ packages = ["."] revision = "86672fcb3f950f35f2e675df2240550f2a50762f" +[[projects]] + name = "github.com/sirupsen/logrus" + packages = ["."] + revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc" + version = "v1.0.5" + [[projects]] branch = "master" name = "github.com/sourcegraph/annotate" @@ -255,14 +279,20 @@ [[projects]] name = "github.com/stretchr/testify" packages = ["assert","require"] - revision = "b91bfb9ebec76498946beb6af7c0230c7cc7ba6c" - version = "v1.2.0" + revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" + version = "v1.2.1" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = ["ssh/terminal"] + revision = "c7dcf104e3a7a1417abc0230cb0d5240d764159d" [[projects]] branch = "master" name = "golang.org/x/net" packages = ["context","html","html/atom"] - revision = "d866cfc389cec985d6fda2859936a575a55a3ab6" + revision = "ae89d30ce0c63142b652837da33d782e2b0a9b25" [[projects]] branch = "master" @@ -273,18 +303,18 @@ [[projects]] branch = "master" name = "golang.org/x/sys" - packages = ["unix"] - revision = "28a7276518d399b9634904daad79e18b44d481bc" + packages = ["unix","windows"] + revision = "c28acc882ebcbfbe8ce9f0f14b9ac26ee138dd51" [[projects]] - branch = "v2" name = "gopkg.in/yaml.v2" packages = ["."] - revision = "c95af922eae69f190717a0b7148960af8c55a072" + revision = "7f97868eec74b32b0982dd158a51a446d1da7eb5" + version = "v2.1.1" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "5163286dab1e7d44b868e3b51dd6e9b26a3e0453511a704264e72c518f760856" + inputs-digest = "686f5e2aed8b743dfbc53e74a1e48185702059972b7a587db36af49ec0eeea8f" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 7630162..c85374a 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -8,7 +8,7 @@ [[constraint]] name = "github.com/gorilla/mux" - version = "1.6.0" + version = "1.6.1" [[constraint]] name = "github.com/stretchr/testify" @@ -16,4 +16,7 @@ [[override]] name = "github.com/satori/go.uuid" - revision = "36e9d2ebbde5e3f13ab2e25625fd453271d6522e" \ No newline at end of file + revision = "36e9d2ebbde5e3f13ab2e25625fd453271d6522e" +[[constraint]] + name = "github.com/sirupsen/logrus" + version = "1.0.5" diff --git a/context.go b/context.go index f4f1834..899325a 100644 --- a/context.go +++ b/context.go @@ -6,6 +6,7 @@ import ( "net/url" "github.com/gobuffalo/buffalo/render" + "github.com/sirupsen/logrus" ) type Context interface { @@ -18,4 +19,5 @@ type Context interface { Render(status int, rr render.Renderer) error Redirect(status int, url string) error Env() string + Logger() *logrus.Logger } diff --git a/default_context.go b/default_context.go index 07800fb..d57f81c 100644 --- a/default_context.go +++ b/default_context.go @@ -9,12 +9,13 @@ import ( "github.com/gobuffalo/buffalo/render" "github.com/gorilla/mux" + "github.com/sirupsen/logrus" ) -func NewContext(r Route, res http.ResponseWriter, req *http.Request, env string) *DefaultContext { +func newContext(r Route, res http.ResponseWriter, req *http.Request) *DefaultContext { data := make(map[string]interface{}) data["path"] = r.Path - data["env"] = env + data["env"] = r.Env params := req.URL.Query() vars := mux.Vars(req) @@ -27,7 +28,7 @@ func NewContext(r Route, res http.ResponseWriter, req *http.Request, env string) request: req, params: params, data: data, - env: env, + env: r.Env, } } @@ -39,6 +40,7 @@ type DefaultContext struct { contentType string data map[string]interface{} env string + logger *logrus.Logger } // Response returns the original Response for the request. @@ -118,3 +120,7 @@ func (d *DefaultContext) Redirect(status int, url string) error { func (d *DefaultContext) Env() string { return d.env } + +func (d *DefaultContext) Logger() *logrus.Logger { + return d.logger +} diff --git a/default_router.go b/default_router.go index 84d26d6..5d3764b 100644 --- a/default_router.go +++ b/default_router.go @@ -6,24 +6,20 @@ import ( "strings" ) -func NewRouter() Router { - return &DefaultRouter{} +func NewRouter(opts ...RouterOption) Router { + router := &DefaultRouter{} + router.Options = &RouterOptions{} + for _, opt := range opts { + opt(router.Options) + } + + return router } type DefaultRouter struct { Routes []*Route StaticRoutes []*StaticRoute - - prefix string - env string -} - -func (r *DefaultRouter) Prefix(path string) { - r.prefix = path -} - -func (r *DefaultRouter) SetEnv(env string) { - r.env = env + Options *RouterOptions } func (r *DefaultRouter) GET(path string, h Handler) { @@ -53,15 +49,45 @@ func (r *DefaultRouter) GetStaticRoutes() []*StaticRoute { return r.StaticRoutes } +func (r *DefaultRouter) GetOptions() *RouterOptions { + return r.Options +} + func (r *DefaultRouter) addRoute(m, p string, h Handler) { - if r.prefix != "" { - p = fmt.Sprintf("/%s/%s", strings.Trim(r.prefix, "/"), strings.Trim(p, "/")) + if r.Options.Prefix != "" { + p = fmt.Sprintf("/%s/%s", strings.Trim(r.Options.Prefix, "/"), strings.Trim(p, "/")) } r.Routes = append(r.Routes, &Route{ Method: m, Path: p, Handler: h, - Env: r.env, + Env: r.Options.Env, }) } + +type RouterOptions struct { + Env string + Prefix string + MiddlewareStack MiddlewareStack +} + +type RouterOption func(*RouterOptions) + +func RouterEnv(env string) RouterOption { + return func(o *RouterOptions) { + o.Env = env + } +} + +func RouterPrefix(p string) RouterOption { + return func(o *RouterOptions) { + o.Prefix = p + } +} + +func RouterMiddleware(ms MiddlewareStack) RouterOption { + return func(o *RouterOptions) { + o.MiddlewareStack = ms + } +} diff --git a/default_router_test.go b/default_router_test.go index 4bdb9f4..91e321c 100644 --- a/default_router_test.go +++ b/default_router_test.go @@ -37,8 +37,7 @@ func Test_Static_Route_Creation(t *testing.T) { func Test_Prefix_Route_Creation(t *testing.T) { r := require.New(t) - router := tuu.NewRouter() - router.Prefix("/prefix/") + router := tuu.NewRouter(tuu.RouterPrefix("/prefix")) router.GET("/home", func(ctx tuu.Context) error { return nil }) router.GET("/home/about-us/", func(ctx tuu.Context) error { return nil }) diff --git a/examples/default_router.go b/examples/default_router.go index d33b27c..a083c4b 100644 --- a/examples/default_router.go +++ b/examples/default_router.go @@ -11,8 +11,7 @@ func main() { // The render we currently use is the one built by gobuffalo. r := render.New(render.Options{}) - router := tuu.NewRouter() - router.SetEnv("dev") + router := tuu.NewRouter(tuu.RouterEnv("env")) router.GET("/home", func(ctx tuu.Context) error { ctx.Set("template_data", "some value") @@ -28,13 +27,12 @@ func main() { return nil }) - app := tuu.New(router) - err := app.Serve(tuu.Config{ + app := tuu.New(router, tuu.Config{ IPAddr: "127.0.0.1", Port: "8080", Env: "dev", - } - + }) + err := app.Serve() if err != nil { panic(err) } diff --git a/middleware.go b/middleware.go new file mode 100644 index 0000000..ae253fd --- /dev/null +++ b/middleware.go @@ -0,0 +1,28 @@ +package tuu + +type Middleware func(Handler) Handler + +type MiddlewareStack struct { + stack []Middleware +} + +func (m *MiddlewareStack) Use(mw ...Middleware) { + m.stack = append(m.stack, mw...) +} + +func (m *MiddlewareStack) Get() []Middleware { + return m.stack +} + +func (m *MiddlewareStack) handler(r *Route) Handler { + handler := r.Handler + if len(m.stack) == 0 { + return handler + } + + for _, mw := range m.stack { + handler = mw(handler) + } + + return handler +} diff --git a/middleware/logger.go b/middleware/logger.go new file mode 100644 index 0000000..ea43947 --- /dev/null +++ b/middleware/logger.go @@ -0,0 +1,12 @@ +package middleware + +import "github.com/lukerodham/tuu" + +// RequestLogger is a default/example implementation of how a logging middleware would be implemented. +func RequestLogger(next tuu.Handler) tuu.Handler { + return func(c tuu.Context) error { + c.Logger().WithField("url", c.Value("path")).Debug("New request") + + return next(c) + } +} diff --git a/route.go b/route.go index a12dbac..1b65b12 100644 --- a/route.go +++ b/route.go @@ -3,8 +3,6 @@ package tuu import ( "net/http" - "github.com/gorilla/mux" - gcontext "github.com/gorilla/context" ) @@ -12,16 +10,18 @@ type Route struct { Method string Path string Handler Handler - MuxHandler mux.Route Env string + Middleware MiddlewareStack } func (r *Route) ServeHTTP(res http.ResponseWriter, req *http.Request) { defer gcontext.Clear(req) - c := NewContext(*r, res, req, r.Env) + c := newContext(*r, res, req) - if err := r.Handler(c); err != nil { + err := r.Middleware.handler(r)(c) + + if err != nil { c.Response().WriteHeader(500) c.Response().Write([]byte(err.Error())) } diff --git a/router.go b/router.go index 145ca79..184b031 100644 --- a/router.go +++ b/router.go @@ -5,9 +5,6 @@ import "net/http" type Handler func(Context) error type Router interface { - Prefix(path string) - SetEnv(env string) - GET(path string, h Handler) POST(path string, h Handler) Static(path string, root http.FileSystem) @@ -15,4 +12,5 @@ type Router interface { GetRoutes() []*Route GetStaticRoutes() []*StaticRoute + GetOptions() *RouterOptions } diff --git a/tuu.go b/tuu.go index 23fa183..c857720 100644 --- a/tuu.go +++ b/tuu.go @@ -17,16 +17,17 @@ type Config struct { Env string } -func New(r Router) *App { - return &App{router: r} +func New(r Router, cfg Config) *App { + return &App{router: r, cfg: cfg} } type App struct { router Router + cfg Config } -func (a *App) Serve(cfg Config) error { - log.Printf("http server running @ http://%s:%s", cfg.IPAddr, cfg.Port) +func (a *App) Serve() error { + log.Printf("http server running @ http://%s:%s", a.cfg.IPAddr, a.cfg.Port) r := mux.NewRouter() @@ -39,7 +40,7 @@ func (a *App) Serve(cfg Config) error { } server := http.Server{ - Addr: fmt.Sprintf("%s:%s", cfg.IPAddr, cfg.Port), + Addr: fmt.Sprintf("%s:%s", a.cfg.IPAddr, a.cfg.Port), Handler: r, }