From 22947b131ef40560018219d8ca569ff569cb266d Mon Sep 17 00:00:00 2001 From: Yonghwan SO Date: Tue, 22 Mar 2022 23:10:12 +0900 Subject: [PATCH 01/20] intermediately, introduce Home struct --- app.go | 29 ++++++++++++++++------------- home.go | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 13 deletions(-) create mode 100644 home.go diff --git a/app.go b/app.go index 804061e43..8ac10e0d8 100644 --- a/app.go +++ b/app.go @@ -14,15 +14,13 @@ import ( // Without an App you can't do much! type App struct { Options - // Middleware returns the current MiddlewareStack for the App/Group. - Middleware *MiddlewareStack `json:"-"` - ErrorHandlers ErrorHandlers `json:"-"` - router *mux.Router - moot *sync.RWMutex - routes RouteList - root *App - children []*App - filepaths []string + // Middleware, ErrorHandlers, router, and filepaths are moved to Home. + Home + moot *sync.RWMutex + routes RouteList + // TODO: to be deprecated #road-to-v1 + root *App + children []*App // Routenamer for the app. This field provides the ability to override the // base route namer for something more specific to the app. @@ -44,11 +42,16 @@ func New(opts Options) *App { a := &App{ Options: opts, - ErrorHandlers: ErrorHandlers{ - http.StatusNotFound: defaultErrorHandler, - http.StatusInternalServerError: defaultErrorHandler, + Home: Home{ + name: opts.Name, + host: opts.Host, + prefix: opts.Prefix, + ErrorHandlers: ErrorHandlers{ + http.StatusNotFound: defaultErrorHandler, + http.StatusInternalServerError: defaultErrorHandler, + }, + router: mux.NewRouter(), }, - router: mux.NewRouter(), moot: &sync.RWMutex{}, routes: RouteList{}, children: []*App{}, diff --git a/home.go b/home.go new file mode 100644 index 000000000..79255e547 --- /dev/null +++ b/home.go @@ -0,0 +1,39 @@ +package buffalo + +import ( + "github.com/gorilla/mux" +) + +/* TODO: consider to split out Home (or Router, whatever) from App #road-to-v1 + Group and Domain based multi-homing are actually not an App if the concept + of the App represents the application. The App should be only one for whole + application. + + For an extreme example, App.Group().Stop() or even App.Group().Serve() are + still valid function calls while they should not be allowed and the result + could be strage. +*/ + +// Home is a container for Domains and Groups that independantly serves a +// group of pages with its own Middleware and ErrorHandlers. It is usually +// a multi-homed server domain or group of paths under a certain prefix. +// +// While the App is for managing whole application life cycle along with its +// default Home, including initializing and stopping its all components such +// as listeners and long-running jobs, Home is only for a specific group of +// services to serve its service logic efficiently. +type Home struct { + app *App // will replace App.root + appSelf *App // temporary while the App is in action. + // replace Options' Name, Host, and Prefix + name string + host string + prefix string + + // moved from App + // Middleware returns the current MiddlewareStack for the App/Group. + Middleware *MiddlewareStack `json:"-"` + ErrorHandlers ErrorHandlers `json:"-"` + router *mux.Router + filepaths []string +} From 211ee6893f3f87a729602c59e541ba1413fc1bfd Mon Sep 17 00:00:00 2001 From: Yonghwan SO Date: Wed, 23 Mar 2022 19:34:51 +0900 Subject: [PATCH 02/20] adapted to the new struct (with small bugfix) --- app.go | 2 ++ route.go | 1 + route_info.go | 2 +- route_mappings.go | 58 +++++++++++++++++++++++++++++------------------ 4 files changed, 40 insertions(+), 23 deletions(-) diff --git a/app.go b/app.go index 8ac10e0d8..12a4dc348 100644 --- a/app.go +++ b/app.go @@ -58,6 +58,8 @@ func New(opts Options) *App { RouteNamer: baseRouteNamer{}, } + a.Home.app = a // replace root. + a.Home.appSelf = a // temporary, reverse reference to the group app. dem := a.defaultErrorMiddleware a.Middleware = newMiddlewareStack(dem) diff --git a/route.go b/route.go index b5f7b3111..a0a04cff7 100644 --- a/route.go +++ b/route.go @@ -11,6 +11,7 @@ import ( // Routes returns a list of all of the routes defined // in this application. func (a *App) Routes() RouteList { + // CHKME: why this function is exported? can we deprecate it? if a.root != nil { return a.root.routes } diff --git a/route_info.go b/route_info.go index b5e20d512..c6be5a636 100644 --- a/route_info.go +++ b/route_info.go @@ -49,7 +49,7 @@ func (ri *RouteInfo) Alias(aliases ...string) *RouteInfo { func (ri *RouteInfo) Name(name string) *RouteInfo { routeIndex := -1 for index, route := range ri.App.Routes() { - if route.Path == ri.Path && route.Method == ri.Method { + if route.App.host == ri.App.host && route.Path == ri.Path && route.Method == ri.Method { routeIndex = index break } diff --git a/route_mappings.go b/route_mappings.go index 4f42b0551..824e87abf 100644 --- a/route_mappings.go +++ b/route_mappings.go @@ -20,6 +20,8 @@ const ( AssetsAgeVarName = "ASSETS_MAX_AGE" ) +// These method functions will be moved to Home structure. + // GET maps an HTTP "GET" request to the path and the specified handler. func (a *App) GET(p string, h Handler) *RouteInfo { return a.addRoute("GET", p, h) @@ -92,17 +94,21 @@ func (a *App) Mount(p string, h http.Handler) { a.Host("{subdomain:[a-z]+}.example.com") */ func (a *App) Host(h string) *App { + // TODO: move this function to app.go or home.go eventually. + // in the end, it should return *Home. g := New(a.Options) + g.host = h g.router = a.router.Host(h).Subrouter() g.RouteNamer = a.RouteNamer g.Middleware = a.Middleware.clone() g.ErrorHandlers = a.ErrorHandlers - g.root = a - if a.root != nil { - g.root = a.root - } + g.app = a.app // will replace g.root + g.root = g.app // will be deprecated + + // to be replaced with child Homes. currently, only used in grifts. + a.children = append(a.children, g) return g } @@ -228,6 +234,7 @@ func (a *App) Resource(p string, r Resource) *App { g.DELETE(path.Join(spath), r.Destroy).ResourceName = resourceName g.Prefix = path.Join(g.Prefix, spath) + g.prefix = g.Prefix return g } @@ -254,18 +261,26 @@ func (a *App) ANY(p string, h Handler) { g.GET("/users/:user_id, APIUserShowHandler) */ func (a *App) Group(groupPath string) *App { + // TODO: move this function to app.go or home.go eventually. g := New(a.Options) + // keep them for v0 compatibility g.Prefix = path.Join(a.Prefix, groupPath) g.Name = g.Prefix + // for Home structure + g.prefix = path.Join(a.prefix, groupPath) + g.host = a.host + g.name = g.prefix + g.router = a.router g.RouteNamer = a.RouteNamer g.Middleware = a.Middleware.clone() g.ErrorHandlers = a.ErrorHandlers - g.root = a - if a.root != nil { - g.root = a.root - } + + g.app = a.app // will replace g.root + g.root = g.app // will be deprecated + + // to be replaced with child Homes. currently, only used in grifts. a.children = append(a.children, g) return g } @@ -280,13 +295,15 @@ func (a *App) RouteHelpers() map[string]RouteHelperFunc { return rh } -func (a *App) addRoute(method string, url string, h Handler) *RouteInfo { - a.moot.Lock() - defer a.moot.Unlock() +func (e *Home) addRoute(method string, url string, h Handler) *RouteInfo { + // NOTE: lock the root app (not this app). only the root has the affective + // routes list. + e.app.moot.Lock() + defer e.app.moot.Unlock() - url = path.Join(a.Prefix, url) - url = a.normalizePath(url) - name := a.RouteNamer.NameRoute(url) + url = path.Join(e.prefix, url) + url = e.app.normalizePath(url) + name := e.app.RouteNamer.NameRoute(url) hs := funcKey(h) r := &RouteInfo{ @@ -294,22 +311,19 @@ func (a *App) addRoute(method string, url string, h Handler) *RouteInfo { Path: url, HandlerName: hs, Handler: h, - App: a, + App: e.appSelf, // CHKME: to be replaced with Home Aliases: []string{}, } - r.MuxRoute = a.router.Handle(url, r).Methods(method) + r.MuxRoute = e.router.Handle(url, r).Methods(method) r.Name(name) - routes := a.Routes() + routes := e.app.Routes() routes = append(routes, r) + // do we really need to sort this? sort.Sort(routes) - if a.root != nil { - a.root.routes = routes - } else { - a.routes = routes - } + e.app.routes = routes return r } From 16d6f7c072952ec193bdc47c2000da834f27d513 Mon Sep 17 00:00:00 2001 From: Yonghwan SO Date: Thu, 24 Mar 2022 23:35:18 +0900 Subject: [PATCH 03/20] fixed issues related to multi-homing and task {routes,middleware} --- grifts.go | 30 ++++++++++++++++-------------- route.go | 13 +++++++++++-- route_mappings.go | 38 ++++++++++++++++++++++++-------------- 3 files changed, 51 insertions(+), 30 deletions(-) diff --git a/grifts.go b/grifts.go index 84af4a774..1cd5a28c1 100644 --- a/grifts.go +++ b/grifts.go @@ -44,22 +44,24 @@ func printMiddleware(a *App) { func printMiddlewareByRoute(a *App) { mws := map[string]string{} + // TODO: middleware is 'per App' can it be a loop for Apps? for _, r := range a.Routes() { - if mws[r.App.Name] == "" { - pname := "" + key := r.App.host + r.App.name + if mws[key] == "" { + pname := r.App.host if parent := getParentApp(r.App.root, r.App.Name); parent != nil { - pname = parent.Name + pname += parent.Name } - mws[r.App.Name] = r.App.Middleware.String() - if mws[pname] != mws[r.App.Name] { - fmt.Printf("-> %s\n", r.App.Name) - printMiddlewareStackWithIndent(mws[r.App.Name]) + mws[key] = r.App.Middleware.String() + if pname == key || mws[pname] != mws[key] { + fmt.Printf("-> %s\n", key) + printMiddlewareStackWithIndent(mws[key]) } else { - fmt.Printf("-> %s (see: %v)\n", r.App.Name, pname) + fmt.Printf("-> %s (see: %v)\n", key, pname) } } - s := "\n" + mws[r.App.Name] + s := "\n" + mws[key] for k := range r.App.Middleware.skips { mw := strings.Split(k, funcKeyDelimeter)[0] h := strings.Split(k, funcKeyDelimeter)[1] @@ -67,10 +69,10 @@ func printMiddlewareByRoute(a *App) { s = strings.Replace(s, "\n"+mw, "", 1) } } - if "\n"+mws[r.App.Name] != s { + if "\n"+mws[key] != s { ahn := strings.Split(r.HandlerName, "/") hn := ahn[len(ahn)-1] - fmt.Printf("-> %s %s (by %s)\n", r.Method, r.Path, hn) + fmt.Printf("-> %s %s (by %s)\n", r.Method, r.App.host+r.Path, hn) printMiddlewareStackWithIndent(s) } } @@ -106,10 +108,10 @@ func routesGrift(a *App) { grift.Add("routes", func(c *grift.Context) error { routes := a.Routes() w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.Debug) - fmt.Fprintln(w, "METHOD\t PATH\t ALIASES\t NAME\t HANDLER") - fmt.Fprintln(w, "------\t ----\t -------\t ----\t -------") + fmt.Fprintln(w, "METHOD\t HOST\t PATH\t ALIASES\t NAME\t HANDLER") + fmt.Fprintln(w, "------\t ----\t ----\t -------\t ----\t -------") for _, r := range routes { - fmt.Fprintf(w, "%s\t %s\t %s\t %s\t %s\n", r.Method, r.Path, strings.Join(r.Aliases, " "), r.PathName, r.HandlerName) + fmt.Fprintf(w, "%s\t %s\t %s\t %s\t %s\t %s\n", r.Method, r.App.host, r.Path, strings.Join(r.Aliases, " "), r.PathName, r.HandlerName) } w.Flush() return nil diff --git a/route.go b/route.go index a0a04cff7..cab38c424 100644 --- a/route.go +++ b/route.go @@ -65,11 +65,20 @@ type RouteHelperFunc func(opts map[string]interface{}) (template.HTML, error) // and the name of the Handler defined to process that route. type RouteList []*RouteInfo +var methodOrder = map[string]string{ + "GET": "1", + "POST": "2", + "PUT": "3", + "DELETE": "4", +} + func (a RouteList) Len() int { return len(a) } func (a RouteList) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a RouteList) Less(i, j int) bool { - x := a[i].Path // + a[i].Method - y := a[j].Path // + a[j].Method + // NOTE: it was used for sorting of app.routes but we don't sort the routes anymore. + // keep it for compatibility but could be deprecated. + x := a[i].App.host + a[i].Path + methodOrder[a[i].Method] + y := a[j].App.host + a[j].Path + methodOrder[a[j].Method] return x < y } diff --git a/route_mappings.go b/route_mappings.go index 824e87abf..5bf33f483 100644 --- a/route_mappings.go +++ b/route_mappings.go @@ -7,7 +7,6 @@ import ( "os" "path" "reflect" - "sort" "strings" "github.com/gobuffalo/envy" @@ -162,6 +161,11 @@ type editable interface { // to the appropriate RESTful mappings. Resource returns the *App // associated with this group of mappings so you can set middleware, etc... // on that group, just as if you had used the a.Group functionality. +// +// Resource automatically creates a URL `/resources/new` if the resource +// has a function `New()`. So it could act as a restriction for the value +// of `resource_id`. URL `/resources/new` will always show the resource +// creation page instead of showing the resource called `new`. /* a.Resource("/users", &UsersResource{}) @@ -170,12 +174,12 @@ type editable interface { ur := &UsersResource{} g := a.Group("/users") g.GET("/", ur.List) // GET /users => ur.List + g.POST("/", ur.Create) // POST /users => ur.Create g.GET("/new", ur.New) // GET /users/new => ur.New g.GET("/{user_id}", ur.Show) // GET /users/{user_id} => ur.Show + g.PUT("/{user_id}", ur.Update) // PUT /users/{user_id} => ur.Update + g.DELETE("/{user_id}", ur.Destroy) // DELETE /users/{user_id} => ur.Destroy g.GET("/{user_id}/edit", ur.Edit) // GET /users/{user_id}/edit => ur.Edit - g.POST("/", ur.Create) // POST /users => ur.Create - g.PUT("/{user_id}", ur.Update) PUT /users/{user_id} => ur.Update - g.DELETE("/{user_id}", ur.Destroy) DELETE /users/{user_id} => ur.Destroy */ func (a *App) Resource(p string, r Resource) *App { g := a.Group(p) @@ -208,9 +212,14 @@ func (a *App) Resource(p string, r Resource) *App { spath := path.Join(p, "{"+paramName+"}") + // This order will become the order of route evaluation too. setFuncKey(r.List, fmt.Sprintf(handlerName, "List")) g.GET(p, r.List).ResourceName = resourceName + setFuncKey(r.Create, fmt.Sprintf(handlerName, "Create")) + g.POST(p, r.Create).ResourceName = resourceName + + // NOTE: it makes restriction that resource id cannot be 'new'. if n, ok := r.(newable); ok { setFuncKey(n.New, fmt.Sprintf(handlerName, "New")) g.GET(path.Join(p, "new"), n.New).ResourceName = resourceName @@ -219,20 +228,17 @@ func (a *App) Resource(p string, r Resource) *App { setFuncKey(r.Show, fmt.Sprintf(handlerName, "Show")) g.GET(path.Join(spath), r.Show).ResourceName = resourceName - if n, ok := r.(editable); ok { - setFuncKey(n.Edit, fmt.Sprintf(handlerName, "Edit")) - g.GET(path.Join(spath, "edit"), n.Edit).ResourceName = resourceName - } - - setFuncKey(r.Create, fmt.Sprintf(handlerName, "Create")) - g.POST(p, r.Create).ResourceName = resourceName - setFuncKey(r.Update, fmt.Sprintf(handlerName, "Update")) g.PUT(path.Join(spath), r.Update).ResourceName = resourceName setFuncKey(r.Destroy, fmt.Sprintf(handlerName, "Destroy")) g.DELETE(path.Join(spath), r.Destroy).ResourceName = resourceName + if n, ok := r.(editable); ok { + setFuncKey(n.Edit, fmt.Sprintf(handlerName, "Edit")) + g.GET(path.Join(spath, "edit"), n.Edit).ResourceName = resourceName + } + g.Prefix = path.Join(g.Prefix, spath) g.prefix = g.Prefix @@ -320,8 +326,12 @@ func (e *Home) addRoute(method string, url string, h Handler) *RouteInfo { routes := e.app.Routes() routes = append(routes, r) - // do we really need to sort this? - sort.Sort(routes) + // NOTE: sorting is fancy but we lose the evaluation order information + // of routing decision. Let's keep the routes as registered order so + // developers can easily evaluate the order with `buffalo routes` and + // can debug any routing priority issue. (just keep the original line + // as history reference) + //sort.Sort(routes) e.app.routes = routes From efeb149fe79c206bcd3e1a9444fde51afae15d51 Mon Sep 17 00:00:00 2001 From: Yonghwan SO Date: Fri, 25 Mar 2022 00:37:16 +0900 Subject: [PATCH 04/20] simplified, renamed the multi-homing function (Host -> VirtualHost) --- route_mappings.go | 51 ++++++++++++++++++++---------------------- route_mappings_test.go | 6 ++--- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/route_mappings.go b/route_mappings.go index 5bf33f483..c0f7d4d89 100644 --- a/route_mappings.go +++ b/route_mappings.go @@ -85,33 +85,6 @@ func (a *App) Mount(p string, h http.Handler) { a.ANY(path, WrapHandler(http.StripPrefix(prefix, h))) } -// Host creates a new "*App" group that matches the domain passed. -// This is useful for creating groups of end-points for different domains. -/* - a.Host("www.example.com") - a.Host("{subdomain}.example.com") - a.Host("{subdomain:[a-z]+}.example.com") -*/ -func (a *App) Host(h string) *App { - // TODO: move this function to app.go or home.go eventually. - // in the end, it should return *Home. - g := New(a.Options) - - g.host = h - g.router = a.router.Host(h).Subrouter() - g.RouteNamer = a.RouteNamer - g.Middleware = a.Middleware.clone() - g.ErrorHandlers = a.ErrorHandlers - - g.app = a.app // will replace g.root - g.root = g.app // will be deprecated - - // to be replaced with child Homes. currently, only used in grifts. - a.children = append(a.children, g) - - return g -} - // ServeFiles maps an path to a directory on disk to serve static files. // Useful for JavaScript, images, CSS, etc... /* @@ -291,6 +264,30 @@ func (a *App) Group(groupPath string) *App { return g } +// VirtualHost creates a new `*App` that inherits from it's parent `*App`. +// All pre-configured things on the parent App such as middlewares will be +// applied, and can be modified only for this child App. +// +// This is a multi-homing feature similar to the `VirtualHost` in Apache +// or multiple `server`s in nginx. One important different behavior is that +// there is no concept of the `default` host in buffalo (at least for now) +// and the routing decision will be made with the "first match" manner. +// (e.g. if you have already set the route for '/' for the root App before +// setting up a virualhost, the route of the root App will be picked up +// even if the client makes a request to the specified domain.) +/* + a.VirtualHost("www.example.com") + a.VirtualHost("{subdomain}.example.com") + a.VirtualHost("{subdomain:[a-z]+}.example.com") +*/ +func (a *App) VirtualHost(h string) *App { + g := a.Group("/") + g.host = h + g.router = a.router.Host(h).Subrouter() + + return g +} + // RouteHelpers returns a map of BuildPathHelper() for each route available in the app. func (a *App) RouteHelpers() map[string]RouteHelperFunc { rh := map[string]RouteHelperFunc{} diff --git a/route_mappings_test.go b/route_mappings_test.go index fe80e2888..5a189e316 100644 --- a/route_mappings_test.go +++ b/route_mappings_test.go @@ -155,13 +155,13 @@ func Test_App_Routes_Resource(t *testing.T) { } } -func Test_App_Host(t *testing.T) { +func Test_App_VirtualHost(t *testing.T) { r := require.New(t) a1 := New(Options{}) r.Nil(a1.root) - h1 := a1.Host("www.example.com") + h1 := a1.VirtualHost("www.example.com") h1.GET("/foo", voidHandler) routes := h1.Routes() @@ -177,7 +177,7 @@ func Test_App_Host(t *testing.T) { a2 := New(Options{}) r.Nil(a1.root) - h2 := a2.Host("{subdomain}.example.com") + h2 := a2.VirtualHost("{subdomain}.example.com") h2.GET("/foo", voidHandler) h2.GET("/foo/{id}", voidHandler).Name("fooID") From 999fb9d400671b27f21c721372deb74d607b6a84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Mar 2022 17:23:12 +0000 Subject: [PATCH 05/20] Bump github.com/gobuffalo/plush/v4 from 4.1.9 to 4.1.10 Bumps [github.com/gobuffalo/plush/v4](https://github.com/gobuffalo/plush) from 4.1.9 to 4.1.10. - [Release notes](https://github.com/gobuffalo/plush/releases) - [Commits](https://github.com/gobuffalo/plush/compare/v4.1.9...v4.1.10) --- updated-dependencies: - dependency-name: github.com/gobuffalo/plush/v4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index b5909ca7c..f87dfb982 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/gobuffalo/logger v1.0.6 github.com/gobuffalo/meta v0.3.1 github.com/gobuffalo/nulls v0.4.1 - github.com/gobuffalo/plush/v4 v4.1.9 + github.com/gobuffalo/plush/v4 v4.1.10 github.com/gobuffalo/pop/v6 v6.0.1 github.com/gobuffalo/tags/v3 v3.1.2 github.com/google/go-cmp v0.5.6 // indirect diff --git a/go.sum b/go.sum index a0f31d797..fdc9a9e59 100644 --- a/go.sum +++ b/go.sum @@ -131,8 +131,9 @@ github.com/gobuffalo/nulls v0.4.1 h1:k7QVCJfMplv9VRQQLb4N1d8tXUdGvcdMNfp4BfMnG2M github.com/gobuffalo/nulls v0.4.1/go.mod h1:pp8e1hWTRJZFpMl4fj/CVbSMlaxjeGKkFq4RuBZi3w8= github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY= github.com/gobuffalo/plush/v4 v4.0.0/go.mod h1:ErFS3UxKqEb8fpFJT7lYErfN/Nw6vHGiDMTjxpk5bQ0= -github.com/gobuffalo/plush/v4 v4.1.9 h1:u9rQBuYCeHC0ppKxsZljk5vb1oT8PQa5EMNTAN2337s= github.com/gobuffalo/plush/v4 v4.1.9/go.mod h1:9OOII9uAM5pZnhWu1OkQnboXJjaWMQ7kcTl3zNcxvTM= +github.com/gobuffalo/plush/v4 v4.1.10 h1:sBTmJJ1Hpj4ExqC4NFmCvAgH6Iq6t58JaWvAl8NEAFc= +github.com/gobuffalo/plush/v4 v4.1.10/go.mod h1:9OOII9uAM5pZnhWu1OkQnboXJjaWMQ7kcTl3zNcxvTM= github.com/gobuffalo/pop/v6 v6.0.0/go.mod h1:5rd3OnViLhjteR8+0i/mT9Q4CzkTzCoR7tm/9mmAic4= github.com/gobuffalo/pop/v6 v6.0.1 h1:4YhzxW4hVvf0xLW9zVkhPZFuH5VmBc4ffIIP/C++SLQ= github.com/gobuffalo/pop/v6 v6.0.1/go.mod h1:5NO7ehmyRjRctnbMDhIqKkkg6zvdueufYltxErfp9BU= From b9dc28b98df92416d32f9a654a012b1071acc3af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Apr 2022 17:35:08 +0000 Subject: [PATCH 06/20] Bump github.com/gobuffalo/flect from 0.2.4 to 0.2.5 Bumps [github.com/gobuffalo/flect](https://github.com/gobuffalo/flect) from 0.2.4 to 0.2.5. - [Release notes](https://github.com/gobuffalo/flect/releases) - [Commits](https://github.com/gobuffalo/flect/compare/v0.2.4...v0.2.5) --- updated-dependencies: - dependency-name: github.com/gobuffalo/flect dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index f87dfb982..058f82349 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/fatih/color v1.13.0 github.com/gobuffalo/envy v1.10.1 github.com/gobuffalo/events v1.4.2 - github.com/gobuffalo/flect v0.2.4 + github.com/gobuffalo/flect v0.2.5 github.com/gobuffalo/github_flavored_markdown v1.1.1 github.com/gobuffalo/helpers v0.6.4 github.com/gobuffalo/httptest v1.5.1 diff --git a/go.sum b/go.sum index fdc9a9e59..eca7cb170 100644 --- a/go.sum +++ b/go.sum @@ -111,8 +111,9 @@ github.com/gobuffalo/fizz v1.10.0/go.mod h1:J2XGPO0AfJ1zKw7+2BA+6FEGAkyEsdCOLvN9 github.com/gobuffalo/fizz v1.14.0 h1:hicZBYSwSWITXEDUR77tqrLU1/vScXHddd02IaFkkPI= github.com/gobuffalo/fizz v1.14.0/go.mod h1:0aF1kAZYCfKqbLM/lmZ3jXFyqqWE/kY/nIOKnNdAYXQ= github.com/gobuffalo/flect v0.2.0/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= -github.com/gobuffalo/flect v0.2.4 h1:BSYA8+T60cdyq+vynaSUjqSVI9mDEg9ZfQUXKmfjo4I= github.com/gobuffalo/flect v0.2.4/go.mod h1:1ZyCLIbg0YD7sDkzvFdPoOydPtD8y9JQnrOROolUcM8= +github.com/gobuffalo/flect v0.2.5 h1:H6vvsv2an0lalEaCDRThvtBfmg44W/QHXBCYUXf/6S4= +github.com/gobuffalo/flect v0.2.5/go.mod h1:1ZyCLIbg0YD7sDkzvFdPoOydPtD8y9JQnrOROolUcM8= github.com/gobuffalo/genny/v2 v2.0.8/go.mod h1:R45scCyQfff2HysNJHNanjrpvPw4Qu+rM1MOMDBB5oU= github.com/gobuffalo/github_flavored_markdown v1.1.0/go.mod h1:TSpTKWcRTI0+v7W3x8dkSKMLJSUpuVitlptCkpeY8ic= github.com/gobuffalo/github_flavored_markdown v1.1.1 h1:kUf8ginyBOTRXcKSTPsPAqlA25vQ80+xAspLIYaxmTU= From f25bbeeb8f10ed9e43c6c3d557ea9ff1a6ad7adb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Apr 2022 17:26:04 +0000 Subject: [PATCH 07/20] Bump github.com/BurntSushi/toml from 1.0.0 to 1.1.0 Bumps [github.com/BurntSushi/toml](https://github.com/BurntSushi/toml) from 1.0.0 to 1.1.0. - [Release notes](https://github.com/BurntSushi/toml/releases) - [Commits](https://github.com/BurntSushi/toml/compare/v1.0.0...v1.1.0) --- updated-dependencies: - dependency-name: github.com/BurntSushi/toml dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 058f82349..ac291b6b0 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/gobuffalo/buffalo go 1.16 require ( - github.com/BurntSushi/toml v1.0.0 + github.com/BurntSushi/toml v1.1.0 github.com/dustin/go-humanize v1.0.0 github.com/fatih/color v1.13.0 github.com/gobuffalo/envy v1.10.1 diff --git a/go.sum b/go.sum index eca7cb170..57f5b2e09 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= -github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= +github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= From edcda04ccc918d79080f504b84f6eb3a1f4937ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Apr 2022 17:21:43 +0000 Subject: [PATCH 08/20] Bump actions/stale from 4 to 5 Bumps [actions/stale](https://github.com/actions/stale) from 4 to 5. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/stale dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index ee6e64c88..50fc43b64 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -7,7 +7,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v4 + - uses: actions/stale@v5 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: "This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days." From 3518513d908de1fd8609cd7a7a3b61bfd53656c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Apr 2022 17:21:46 +0000 Subject: [PATCH 09/20] Bump actions/setup-go from 2 to 3 Bumps [actions/setup-go](https://github.com/actions/setup-go) from 2 to 3. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 661129f85..3a0f80279 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Setup Go ${{ matrix.go }} - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: go-version: ${{ matrix.go-version }} From f53c9246ca5dac53f8a3d03c0ccc38984531d3a7 Mon Sep 17 00:00:00 2001 From: Stefan Aurori Date: Fri, 15 Apr 2022 12:04:46 -0400 Subject: [PATCH 10/20] HTTPError Error() avoid nil pointer dereference on nil Cause --- errors.go | 2 +- errors_test.go | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/errors.go b/errors.go index f98595419..fc764861e 100644 --- a/errors.go +++ b/errors.go @@ -30,7 +30,7 @@ func (h HTTPError) Unwrap() error { // Error returns the cause of the error as string. func (h HTTPError) Error() string { - return h.Cause.Error() + return fmt.Sprint(h.Cause) } // ErrorHandler interface for handling an error for a diff --git a/errors_test.go b/errors_test.go index 7042ade25..bf55f6002 100644 --- a/errors_test.go +++ b/errors_test.go @@ -143,6 +143,18 @@ func Test_defaultErrorHandler_XML_production(t *testing.T) { r.Contains(b, ``) } +func Test_defaultErrorHandler_nil_error(t *testing.T) { + r := require.New(t) + app := New(Options{}) + app.GET("/", func(c Context) error { + return c.Error(http.StatusInternalServerError, nil) + }) + + w := httptest.New(app) + res := w.JSON("/").Get() + r.Equal(http.StatusInternalServerError, res.Code) +} + func Test_PanicHandler(t *testing.T) { app := New(Options{}) app.GET("/string", func(c Context) error { From 1acf05b3e1af3a2e28bd5a8bbba93127ed0f9a8e Mon Sep 17 00:00:00 2001 From: Stefan Aurori Date: Sat, 16 Apr 2022 11:00:02 -0400 Subject: [PATCH 11/20] HTTPError Error() return when Cause is nil --- errors.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/errors.go b/errors.go index fc764861e..228bd3865 100644 --- a/errors.go +++ b/errors.go @@ -30,7 +30,10 @@ func (h HTTPError) Unwrap() error { // Error returns the cause of the error as string. func (h HTTPError) Error() string { - return fmt.Sprint(h.Cause) + if h.Cause != nil { + return h.Cause.Error() + } + return "unknown cause" } // ErrorHandler interface for handling an error for a From 82c678787f449aa4b6b94cf1fb75f0631d3d8642 Mon Sep 17 00:00:00 2001 From: Antonio Pagano Date: Sat, 16 Apr 2022 10:11:28 -0500 Subject: [PATCH 12/20] task: adding next version number --- runtime/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/version.go b/runtime/version.go index 2159ff4a2..701242d91 100644 --- a/runtime/version.go +++ b/runtime/version.go @@ -1,4 +1,4 @@ package runtime // Version is the current version of the buffalo binary -var Version = "v0.18.5" +var Version = "v0.18.6" From 9d7343390d4ff3fac575761e57ccafbbc2acdab7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Apr 2022 17:25:17 +0000 Subject: [PATCH 13/20] Bump github.com/gobuffalo/pop/v6 from 6.0.1 to 6.0.2 Bumps [github.com/gobuffalo/pop/v6](https://github.com/gobuffalo/pop) from 6.0.1 to 6.0.2. - [Release notes](https://github.com/gobuffalo/pop/releases) - [Changelog](https://github.com/gobuffalo/pop/blob/master/.goreleaser.yml) - [Commits](https://github.com/gobuffalo/pop/compare/v6.0.1...v6.0.2) --- updated-dependencies: - dependency-name: github.com/gobuffalo/pop/v6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index ac291b6b0..d62525b1f 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/gobuffalo/meta v0.3.1 github.com/gobuffalo/nulls v0.4.1 github.com/gobuffalo/plush/v4 v4.1.10 - github.com/gobuffalo/pop/v6 v6.0.1 + github.com/gobuffalo/pop/v6 v6.0.2 github.com/gobuffalo/tags/v3 v3.1.2 github.com/google/go-cmp v0.5.6 // indirect github.com/gorilla/handlers v1.5.1 diff --git a/go.sum b/go.sum index 57f5b2e09..c753f91c7 100644 --- a/go.sum +++ b/go.sum @@ -115,6 +115,7 @@ github.com/gobuffalo/flect v0.2.4/go.mod h1:1ZyCLIbg0YD7sDkzvFdPoOydPtD8y9JQnrOR github.com/gobuffalo/flect v0.2.5 h1:H6vvsv2an0lalEaCDRThvtBfmg44W/QHXBCYUXf/6S4= github.com/gobuffalo/flect v0.2.5/go.mod h1:1ZyCLIbg0YD7sDkzvFdPoOydPtD8y9JQnrOROolUcM8= github.com/gobuffalo/genny/v2 v2.0.8/go.mod h1:R45scCyQfff2HysNJHNanjrpvPw4Qu+rM1MOMDBB5oU= +github.com/gobuffalo/genny/v2 v2.0.9/go.mod h1:R45scCyQfff2HysNJHNanjrpvPw4Qu+rM1MOMDBB5oU= github.com/gobuffalo/github_flavored_markdown v1.1.0/go.mod h1:TSpTKWcRTI0+v7W3x8dkSKMLJSUpuVitlptCkpeY8ic= github.com/gobuffalo/github_flavored_markdown v1.1.1 h1:kUf8ginyBOTRXcKSTPsPAqlA25vQ80+xAspLIYaxmTU= github.com/gobuffalo/github_flavored_markdown v1.1.1/go.mod h1:yU32Pen+eorS58oxh/bNZx76zUOCJwmvyV5FBrvzOKQ= @@ -136,8 +137,8 @@ github.com/gobuffalo/plush/v4 v4.1.9/go.mod h1:9OOII9uAM5pZnhWu1OkQnboXJjaWMQ7kc github.com/gobuffalo/plush/v4 v4.1.10 h1:sBTmJJ1Hpj4ExqC4NFmCvAgH6Iq6t58JaWvAl8NEAFc= github.com/gobuffalo/plush/v4 v4.1.10/go.mod h1:9OOII9uAM5pZnhWu1OkQnboXJjaWMQ7kcTl3zNcxvTM= github.com/gobuffalo/pop/v6 v6.0.0/go.mod h1:5rd3OnViLhjteR8+0i/mT9Q4CzkTzCoR7tm/9mmAic4= -github.com/gobuffalo/pop/v6 v6.0.1 h1:4YhzxW4hVvf0xLW9zVkhPZFuH5VmBc4ffIIP/C++SLQ= -github.com/gobuffalo/pop/v6 v6.0.1/go.mod h1:5NO7ehmyRjRctnbMDhIqKkkg6zvdueufYltxErfp9BU= +github.com/gobuffalo/pop/v6 v6.0.2 h1:NuIMTwZ54aHK92ertwv3R2SepAvhTRlQj9/MLqO9Qdo= +github.com/gobuffalo/pop/v6 v6.0.2/go.mod h1:1g+AV0EDe0rUoy1I3yA3aa9N5+/uC5RxtGbxI0KNe4c= github.com/gobuffalo/tags/v3 v3.0.2/go.mod h1:ZQeN6TCTiwAFnS0dNcbDtSgZDwNKSpqajvVtt6mlYpA= github.com/gobuffalo/tags/v3 v3.1.2 h1:68sHcwFFDstXyfbk5ovbGcQFDsupgVLs+lw1XZinHJw= github.com/gobuffalo/tags/v3 v3.1.2/go.mod h1:o3ldUfKv50jxWAC8eZHXMm8dnKW3YvyZUMr0xqUcZTI= @@ -147,8 +148,9 @@ github.com/gobuffalo/validate/v3 v3.3.1/go.mod h1:Ehu8ieNJQuUM4peDDr/0VapzdGA7Rg github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.1.0+incompatible h1:sIa2eCvUTwgjbqXrPLfNwUf9S3i3mpH1O1atV+iL/Wk= github.com/gofrs/uuid v4.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= +github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -261,8 +263,9 @@ github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfG github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgconn v1.10.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.10.1 h1:DzdIHIjG1AxGwoEEqS+mGsURyjt4enSmqzACXvVzOT8= github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.11.0 h1:HiHArx4yFbwl91X3qqIHtUFoiIfLNJXCQRsnzkiwwaQ= +github.com/jackc/pgconn v1.11.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= @@ -278,25 +281,29 @@ github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.1.1 h1:7PQ/4gLoqnl87ZxL7xjO0DR5gYuviDCZxQJsUlFW1eI= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.2.0 h1:r7JypeP2D3onoQTCxWdTpCtJ4D+qpKr0TxvoyMhZ5ns= +github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.8.1 h1:9k0IXtdJXHJbyAWQgbWr1lU+MEhPXZz6RIXxfR5oxXs= github.com/jackc/pgtype v1.8.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgtype v1.10.0 h1:ILnBWrRMSXGczYvmkYD6PsYyVFUNLTnIUJHHDLmqk38= +github.com/jackc/pgtype v1.10.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.13.0 h1:JCjhT5vmhMAf/YwBHLvrBn4OGdIQBiFG6ym8Zmdx570= github.com/jackc/pgx/v4 v4.13.0/go.mod h1:9P4X524sErlaxj0XSGZk7s+LD0eOyu1ZDUrrpznYDF0= +github.com/jackc/pgx/v4 v4.15.0 h1:B7dTkXsdILD3MF987WGGCcg+tvLW6bZJdEcqVFeU//w= +github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w= github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= @@ -325,8 +332,9 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.5 h1:J+gdV2cUmX7ZqL2B0lFcW0m+egaHC2V3lpO8nWxyYiQ= +github.com/lib/pq v1.10.5/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/luna-duclos/instrumentedsql v1.1.3 h1:t7mvC0z1jUt5A0UQ6I/0H31ryymuQRnJcWCiqV3lSAA= github.com/luna-duclos/instrumentedsql v1.1.3/go.mod h1:9J1njvFds+zN7y85EDhN9XNQLANWwZt2ULeIC8yMNYs= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= From 2ccfb9fd825876795215d9e570e79037d9e1dbd9 Mon Sep 17 00:00:00 2001 From: Yonghwan SO Date: Thu, 21 Apr 2022 23:48:37 +0900 Subject: [PATCH 14/20] hardening DefaultContext to make it panic-free --- default_context.go | 16 +++++++- default_context_test.go | 81 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/default_context.go b/default_context.go index 3f2eec99d..e88acbf4b 100644 --- a/default_context.go +++ b/default_context.go @@ -23,6 +23,9 @@ import ( var _ Context = &DefaultContext{} var _ context.Context = &DefaultContext{} +// TODO(sio4): #road-to-v1 - make DefaultContext private +// and only allow it to be generated by App.newContext() or any similar. + // DefaultContext is, as its name implies, a default // implementation of the Context interface. type DefaultContext struct { @@ -67,16 +70,22 @@ func (d *DefaultContext) Param(key string) string { // Set a value onto the Context. Any value set onto the Context // will be automatically available in templates. func (d *DefaultContext) Set(key string, value interface{}) { + if d.data == nil { + d.data = &sync.Map{} + } d.data.Store(key, value) } // Value that has previously stored on the context. func (d *DefaultContext) Value(key interface{}) interface{} { - if k, ok := key.(string); ok { + if k, ok := key.(string); ok && d.data != nil { if v, ok := d.data.Load(k); ok { return v } } + if d.Context == nil { + return nil + } return d.Context.Value(key) } @@ -235,6 +244,11 @@ func (d *DefaultContext) Redirect(status int, url string, args ...interface{}) e // Data contains all the values set through Get/Set. func (d *DefaultContext) Data() map[string]interface{} { m := map[string]interface{}{} + + if d.data == nil { + return m + } + d.data.Range(func(k, v interface{}) bool { s, ok := k.(string) if !ok { diff --git a/default_context_test.go b/default_context_test.go index 2823828cc..203781641 100644 --- a/default_context_test.go +++ b/default_context_test.go @@ -143,6 +143,15 @@ func Test_DefaultContext_GetSet(t *testing.T) { r.Equal("Mark", c.Value("name").(string)) } +func Test_DefaultContext_Set_Unconfigured(t *testing.T) { + r := require.New(t) + c := DefaultContext{} + + c.Set("name", "Yonghwan") + r.NotNil(c.Value("name")) + r.Equal("Yonghwan", c.Value("name").(string)) +} + func Test_DefaultContext_Value(t *testing.T) { r := require.New(t) c := basicContext() @@ -151,7 +160,12 @@ func Test_DefaultContext_Value(t *testing.T) { c.Set("name", "Mark") r.NotNil(c.Value("name")) r.Equal("Mark", c.Value("name").(string)) - r.Equal("Mark", c.Value("name").(string)) +} + +func Test_DefaultContext_Value_Unconfigured(t *testing.T) { + r := require.New(t) + c := DefaultContext{} + r.Nil(c.Value("name")) } func Test_DefaultContext_Render(t *testing.T) { @@ -301,3 +315,68 @@ func Test_DefaultContext_Bind_JSON(t *testing.T) { r.Equal("Mark", user.FirstName) } + +func Test_DefaultContext_Data(t *testing.T) { + r := require.New(t) + c := basicContext() + + r.EqualValues(map[string]interface{}{}, c.Data()) +} + +func Test_DefaultContext_Data_Unconfigured(t *testing.T) { + r := require.New(t) + c := DefaultContext{} + + r.EqualValues(map[string]interface{}{}, c.Data()) +} + +func Test_DefaultContext_String(t *testing.T) { + r := require.New(t) + c := basicContext() + c.Set("name", "Buffalo") + c.Set("language", "go") + + r.EqualValues("language: go\n\nname: Buffalo", c.String()) +} + +func Test_DefaultContext_String_EmptyData(t *testing.T) { + r := require.New(t) + c := basicContext() + r.EqualValues("", c.String()) +} + +func Test_DefaultContext_String_EmptyData_Unconfigured(t *testing.T) { + r := require.New(t) + c := DefaultContext{} + + r.EqualValues("", c.String()) +} + +func Test_DefaultContext_MarshalJSON(t *testing.T) { + r := require.New(t) + c := basicContext() + c.Set("name", "Buffalo") + c.Set("language", "go") + + jb, err := c.MarshalJSON() + r.NoError(err) + r.EqualValues(`{"language":"go","name":"Buffalo"}`, string(jb)) +} + +func Test_DefaultContext_MarshalJSON_EmptyData(t *testing.T) { + r := require.New(t) + c := basicContext() + + jb, err := c.MarshalJSON() + r.NoError(err) + r.EqualValues(`{}`, string(jb)) +} + +func Test_DefaultContext_MarshalJSON_EmptyData_Unconfigured(t *testing.T) { + r := require.New(t) + c := DefaultContext{} + + jb, err := c.MarshalJSON() + r.NoError(err) + r.EqualValues(`{}`, string(jb)) +} From 9195c040df91e090ccda4d441bf755514a8f6732 Mon Sep 17 00:00:00 2001 From: Yonghwan SO Date: Mon, 18 Apr 2022 22:21:58 +0900 Subject: [PATCH 15/20] added input/status checks, testcases, and comments for road-to-v1 --- worker/simple.go | 33 ++++++- worker/simple_test.go | 209 +++++++++++++++++++++++++++++++++++------- 2 files changed, 208 insertions(+), 34 deletions(-) diff --git a/worker/simple.go b/worker/simple.go index 3f5788d40..76d9ef673 100644 --- a/worker/simple.go +++ b/worker/simple.go @@ -15,6 +15,9 @@ var _ Worker = &Simple{} // NewSimple creates a basic implementation of the Worker interface // that is backed using just the standard library and goroutines. func NewSimple() *Simple { + // TODO(sio4): #road-to-v1 - how to check if the worker is ready to work + // when worker should be initialized? how to check if worker is ready? + // and purpose of the context return NewSimpleWithContext(context.Background()) } @@ -49,6 +52,10 @@ type Simple struct { // Register Handler with the worker func (w *Simple) Register(name string, h Handler) error { + if name == "" || h == nil { + return fmt.Errorf("name or handler cannot be empty/nil") + } + w.moot.Lock() defer w.moot.Unlock() if _, ok := w.handlers[name]; ok { @@ -60,6 +67,7 @@ func (w *Simple) Register(name string, h Handler) error { // Start the worker func (w *Simple) Start(ctx context.Context) error { + // TODO(sio4): #road-to-v1 - define the purpose of Start clearly w.Logger.Info("starting Simple background worker") w.ctx, w.cancel = context.WithCancel(ctx) @@ -68,20 +76,30 @@ func (w *Simple) Start(ctx context.Context) error { // Stop the worker func (w *Simple) Stop() error { + // prevent job submission when stopping + w.moot.Lock() + defer w.moot.Unlock() + w.Logger.Info("stopping Simple background worker") + w.cancel() + w.wg.Wait() w.Logger.Info("all background jobs stopped completely") - w.cancel() return nil } // Perform a job as soon as possibly using a goroutine. func (w *Simple) Perform(job Job) error { + // Perform should not allow a job submission if the worker is not running + if err := w.ctx.Err(); err != nil { + return fmt.Errorf("worker is not ready to perform a job: %v", err) + } + w.Logger.Debugf("performing job %s", job) if job.Handler == "" { - err := fmt.Errorf("no handler name given for %s", job) + err := fmt.Errorf("no handler name given: %s", job) w.Logger.Error(err) return err } @@ -89,7 +107,7 @@ func (w *Simple) Perform(job Job) error { w.moot.Lock() defer w.moot.Unlock() if h, ok := w.handlers[job.Handler]; ok { - // TODO: consider to implement timeout and/or cancellation + // TODO(sio4): #road-to-v1 - consider timeout and/or cancellation w.wg.Add(1) go func() { defer w.wg.Done() @@ -118,11 +136,20 @@ func (w *Simple) PerformAt(job Job, t time.Time) error { // PerformIn performs a job after waiting for a specified amount // using a goroutine. func (w *Simple) PerformIn(job Job, d time.Duration) error { + // Perform should not allow a job submission if the worker is not running + if err := w.ctx.Err(); err != nil { + return fmt.Errorf("worker is not ready to perform a job: %v", err) + } + + w.wg.Add(1) // waiting job also should be counted go func() { + defer w.wg.Done() + select { case <-time.After(d): w.Perform(job) case <-w.ctx.Done(): + // TODO(sio4): #road-to-v1 - it should be guaranteed to be performed w.cancel() } }() diff --git a/worker/simple_test.go b/worker/simple_test.go index 6372d60ca..24d16f1f8 100644 --- a/worker/simple_test.go +++ b/worker/simple_test.go @@ -1,99 +1,246 @@ package worker import ( - "sync" + "context" "testing" "time" "github.com/stretchr/testify/require" ) +func sampleHandler(Args) error { + return nil +} + +func Test_Simple_RegisterEmpty(t *testing.T) { + r := require.New(t) + + w := NewSimple() + err := w.Register("", sampleHandler) + r.Error(err) +} + +func Test_Simple_RegisterNil(t *testing.T) { + r := require.New(t) + + w := NewSimple() + err := w.Register("sample", nil) + r.Error(err) +} + +func Test_Simple_RegisterEmptyNil(t *testing.T) { + r := require.New(t) + + w := NewSimple() + err := w.Register("", nil) + r.Error(err) +} + +func Test_Simple_RegisterExisting(t *testing.T) { + r := require.New(t) + + w := NewSimple() + err := w.Register("sample", sampleHandler) + r.NoError(err) + + err = w.Register("sample", sampleHandler) + r.Error(err) +} + +func Test_Simple_StartStop(t *testing.T) { + r := require.New(t) + + w := NewSimple() + ctx := context.Background() + err := w.Start(ctx) + r.NoError(err) + r.NotNil(w.ctx) + r.Nil(w.ctx.Err()) + + err = w.Stop() + r.NoError(err) + r.NotNil(w.ctx) + r.NotNil(w.ctx.Err()) +} + func Test_Simple_Perform(t *testing.T) { r := require.New(t) var hit bool - wg := &sync.WaitGroup{} - wg.Add(1) w := NewSimple() + r.NoError(w.Start(context.Background())) + w.Register("x", func(Args) error { hit = true - wg.Done() return nil }) w.Perform(Job{ Handler: "x", }) - wg.Wait() + + // the worker should guarantee the job is finished before the worker stopped + r.NoError(w.Stop()) r.True(hit) } -func Test_Simple_PerformAt(t *testing.T) { +func Test_Simple_PerformBroken(t *testing.T) { r := require.New(t) var hit bool - wg := &sync.WaitGroup{} - wg.Add(1) w := NewSimple() + r.NoError(w.Start(context.Background())) + w.Register("x", func(Args) error { hit = true - wg.Done() + + //Index out of bounds on purpose + println([]string{}[0]) + return nil }) - w.PerformAt(Job{ + w.Perform(Job{ Handler: "x", - }, time.Now().Add(5*time.Millisecond)) - wg.Wait() + }) + + r.NoError(w.Stop()) r.True(hit) } -func Test_Simple_PerformBroken(t *testing.T) { +func Test_Simple_PerformWithEmptyJob(t *testing.T) { r := require.New(t) - var hit bool - wg := &sync.WaitGroup{} - wg.Add(1) + w := NewSimple() + r.NoError(w.Start(context.Background())) + defer w.Stop() + + err := w.Perform(Job{}) + r.Error(err) +} + +func Test_Simple_PerformWithUnknownJob(t *testing.T) { + r := require.New(t) w := NewSimple() - w.Register("x", func(Args) error { - hit = true - wg.Done() + r.NoError(w.Start(context.Background())) + defer w.Stop() - //Index out of bounds on purpose - println([]string{}[0]) + err := w.Perform(Job{Handler: "unknown"}) + r.Error(err) +} + +/* TODO(sio4): #road-to-v1 - define the purpose of Start clearly + consider to make Perform to work only when the worker is started. +func Test_Simple_PerformBeforeStart(t *testing.T) { + r := require.New(t) + + w := NewSimple() + r.NoError(w.Register("sample", sampleHandler)) + + err := w.Perform(Job{Handler: "sample"}) + r.Error(err) +} +*/ + +func Test_Simple_PerformAfterStop(t *testing.T) { + r := require.New(t) + + w := NewSimple() + r.NoError(w.Register("sample", sampleHandler)) + r.NoError(w.Start(context.Background())) + r.NoError(w.Stop()) + + err := w.Perform(Job{Handler: "sample"}) + r.Error(err) +} + +func Test_Simple_PerformAt(t *testing.T) { + r := require.New(t) + var hit bool + w := NewSimple() + r.NoError(w.Start(context.Background())) + + w.Register("x", func(Args) error { + hit = true return nil }) - - w.Perform(Job{ + w.PerformAt(Job{ Handler: "x", - }) - wg.Wait() + }, time.Now().Add(5*time.Millisecond)) + + time.Sleep(10 * time.Millisecond) r.True(hit) + + r.NoError(w.Stop()) } func Test_Simple_PerformIn(t *testing.T) { r := require.New(t) var hit bool - wg := &sync.WaitGroup{} - wg.Add(1) w := NewSimple() + r.NoError(w.Start(context.Background())) + w.Register("x", func(Args) error { hit = true - wg.Done() return nil }) w.PerformIn(Job{ Handler: "x", }, 5*time.Millisecond) - wg.Wait() + + time.Sleep(10 * time.Millisecond) r.True(hit) + + r.NoError(w.Stop()) } -func Test_Simple_NoHandler(t *testing.T) { +/* TODO(sio4): #road-to-v1 - define the purpose of Start clearly + consider to make Perform to work only when the worker is started. +func Test_Simple_PerformInBeforeStart(t *testing.T) { r := require.New(t) w := NewSimple() - err := w.Perform(Job{}) + r.NoError(w.Register("sample", sampleHandler)) + + err := w.PerformIn(Job{Handler: "sample"}, 5*time.Millisecond) r.Error(err) } +*/ + +func Test_Simple_PerformInAfterStop(t *testing.T) { + r := require.New(t) + + w := NewSimple() + r.NoError(w.Register("sample", sampleHandler)) + r.NoError(w.Start(context.Background())) + r.NoError(w.Stop()) + + err := w.PerformIn(Job{Handler: "sample"}, 5*time.Millisecond) + r.Error(err) +} + +/* TODO(sio4): #road-to-v1 - it should be guaranteed to be performed + consider to make PerformIn to guarantee the job execution +func Test_Simple_PerformInFollowedByStop(t *testing.T) { + r := require.New(t) + + var hit bool + w := NewSimple() + r.NoError(w.Start(context.Background())) + + w.Register("x", func(Args) error { + hit = true + return nil + }) + err := w.PerformIn(Job{ + Handler: "x", + }, 5*time.Millisecond) + r.NoError(err) + + // stop the worker immediately after PerformIn + r.NoError(w.Stop()) + + r.True(hit) +} +*/ From 11507d3375ec64d33a142c53044000b2083c5ce2 Mon Sep 17 00:00:00 2001 From: Yonghwan SO Date: Tue, 19 Apr 2022 01:11:34 +0900 Subject: [PATCH 16/20] added sync for testcases. currently execution is not guaranteed for PerformIn --- worker/simple_test.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/worker/simple_test.go b/worker/simple_test.go index 24d16f1f8..7abf0b499 100644 --- a/worker/simple_test.go +++ b/worker/simple_test.go @@ -2,6 +2,7 @@ package worker import ( "context" + "sync" "testing" "time" @@ -160,15 +161,21 @@ func Test_Simple_PerformAt(t *testing.T) { w := NewSimple() r.NoError(w.Start(context.Background())) + wg := &sync.WaitGroup{} + wg.Add(1) + w.Register("x", func(Args) error { hit = true + wg.Done() return nil }) w.PerformAt(Job{ Handler: "x", }, time.Now().Add(5*time.Millisecond)) - time.Sleep(10 * time.Millisecond) + // how long does the handler take for assignment? hmm, + time.Sleep(100 * time.Millisecond) + wg.Wait() r.True(hit) r.NoError(w.Stop()) @@ -181,15 +188,21 @@ func Test_Simple_PerformIn(t *testing.T) { w := NewSimple() r.NoError(w.Start(context.Background())) + wg := &sync.WaitGroup{} + wg.Add(1) + w.Register("x", func(Args) error { hit = true + wg.Done() return nil }) w.PerformIn(Job{ Handler: "x", }, 5*time.Millisecond) - time.Sleep(10 * time.Millisecond) + // how long does the handler take for assignment? hmm, + time.Sleep(100 * time.Millisecond) + wg.Wait() r.True(hit) r.NoError(w.Stop()) From 4398c1641f6e63dbbe4608e7e448e07eb4647ae1 Mon Sep 17 00:00:00 2001 From: Matthias Fasching Date: Thu, 28 Apr 2022 13:35:46 +0200 Subject: [PATCH 17/20] Remove ioutil and replace with io/os functions --- plugins/plugins_test.go | 4 ++-- router_test.go | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/plugins/plugins_test.go b/plugins/plugins_test.go index 1f6317435..855850a1f 100644 --- a/plugins/plugins_test.go +++ b/plugins/plugins_test.go @@ -2,7 +2,7 @@ package plugins import ( "context" - "io/ioutil" + "os" "strings" "testing" "time" @@ -20,7 +20,7 @@ func TestAskBin_respectsTimeout(t *testing.T) { return } - if fileEntries, err := ioutil.ReadDir(from); err == nil { + if fileEntries, err := os.ReadDir(from); err == nil { found := false for _, e := range fileEntries { if strings.HasPrefix(e.Name(), "buffalo-") { diff --git a/router_test.go b/router_test.go index ff3584fa5..29bbdff3b 100644 --- a/router_test.go +++ b/router_test.go @@ -2,7 +2,7 @@ package buffalo import ( "fmt" - "io/ioutil" + "io" "net/http" "os" "path" @@ -98,7 +98,7 @@ func Test_Mount_Buffalo(t *testing.T) { r.NoError(err) res, err := http.DefaultClient.Do(req) r.NoError(err) - b, _ := ioutil.ReadAll(res.Body) + b, _ := io.ReadAll(res.Body) r.Equal(fmt.Sprintf("%s - %s/", m, u), string(b)) } } @@ -123,7 +123,7 @@ func Test_Mount_Buffalo_on_Group(t *testing.T) { r.NoError(err) res, err := http.DefaultClient.Do(req) r.NoError(err) - b, _ := ioutil.ReadAll(res.Body) + b, _ := io.ReadAll(res.Body) r.Equal(fmt.Sprintf("%s - %s/", m, u), string(b)) } } @@ -158,7 +158,7 @@ func Test_Mount_Handler(t *testing.T) { r.NoError(err) res, err := http.DefaultClient.Do(req) r.NoError(err) - b, _ := ioutil.ReadAll(res.Body) + b, _ := io.ReadAll(res.Body) r.Equal(fmt.Sprintf("%s - %s/", m, u), string(b)) } } @@ -197,7 +197,7 @@ func Test_PreHandlers(t *testing.T) { r.NoError(err) res, err := http.DefaultClient.Do(req) r.NoError(err) - b, err := ioutil.ReadAll(res.Body) + b, err := io.ReadAll(res.Body) r.NoError(err) r.Equal(v.Code, res.StatusCode) r.Equal(v.Result, string(b)) @@ -242,7 +242,7 @@ func Test_PreWares(t *testing.T) { r.NoError(err) res, err := http.DefaultClient.Do(req) r.NoError(err) - b, err := ioutil.ReadAll(res.Body) + b, err := io.ReadAll(res.Body) r.NoError(err) r.Equal(v.Code, res.StatusCode) r.Equal(v.Result, string(b)) @@ -269,7 +269,7 @@ func Test_Router(t *testing.T) { r.NoError(err) res, err := http.DefaultClient.Do(req) r.NoError(err) - b, _ := ioutil.ReadAll(res.Body) + b, _ := io.ReadAll(res.Body) r.Equal(fmt.Sprintf("%s|/router/tests", v), string(b)) } } @@ -552,7 +552,7 @@ func Test_Resource(t *testing.T) { r.NoError(err) res, err := c.Do(req) r.NoError(err) - b, err := ioutil.ReadAll(res.Body) + b, err := io.ReadAll(res.Body) r.NoError(err) r.Equal(test.Result, string(b)) } @@ -710,7 +710,7 @@ func Test_ResourceOnResource(t *testing.T) { r.NoError(err) res, err := c.Do(req) r.NoError(err) - b, err := ioutil.ReadAll(res.Body) + b, err := io.ReadAll(res.Body) r.NoError(err) r.Equal(test.Result, string(b)) } From d78ef76f231a57562afb3d261732edee03dacce2 Mon Sep 17 00:00:00 2001 From: Liam Bowen Date: Mon, 25 Apr 2022 23:20:33 +0000 Subject: [PATCH 18/20] Fix logging of where application is bound --- server.go | 7 +++---- servers/listener.go | 5 +++++ servers/servers.go | 1 + servers/simple.go | 5 +++++ servers/tls.go | 5 +++++ 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/server.go b/server.go index 17e21321c..26a57e97c 100644 --- a/server.go +++ b/server.go @@ -22,10 +22,6 @@ import ( func (a *App) Serve(srvs ...servers.Server) error { var wg sync.WaitGroup - // FIXME: this information is not correct. - // It needs to be fixed as we support multiple servers. - a.Logger.Infof("starting application at http://%s", a.Options.Addr) - payload := events.Payload{ "app": a, } @@ -35,6 +31,7 @@ func (a *App) Serve(srvs ...servers.Server) error { return err } + // Add default server if necessary if len(srvs) == 0 { if strings.HasPrefix(a.Options.Addr, "unix:") { tcp, err := servers.UnixSocket(a.Options.Addr[5:]) @@ -98,6 +95,8 @@ func (a *App) Serve(srvs ...servers.Server) error { for _, s := range srvs { s.SetAddr(a.Addr) + a.Logger.Infof("starting server of type %T at %s", + s, s.Addr()) wg.Add(1) go func(s servers.Server) { defer wg.Done() diff --git a/servers/listener.go b/servers/listener.go index b36f8895c..6f3497308 100644 --- a/servers/listener.go +++ b/servers/listener.go @@ -19,6 +19,11 @@ func (s *Listener) SetAddr(addr string) { } } +// Addr gets the HTTP server address +func (s *Listener) Addr() string { + return s.Server.Addr +} + // Start the server func (s *Listener) Start(c context.Context, h http.Handler) error { s.Handler = h diff --git a/servers/servers.go b/servers/servers.go index 4a703d74f..93d1f831d 100644 --- a/servers/servers.go +++ b/servers/servers.go @@ -8,6 +8,7 @@ import ( // Server allows for custom server implementations type Server interface { + Addr() string Shutdown(context.Context) error Start(context.Context, http.Handler) error SetAddr(string) diff --git a/servers/simple.go b/servers/simple.go index b0e30d0d1..9b57a99c1 100644 --- a/servers/simple.go +++ b/servers/simple.go @@ -17,6 +17,11 @@ func (s *Simple) SetAddr(addr string) { } } +// Addr gets the HTTP server address +func (s *Simple) Addr() string { + return s.Server.Addr +} + // Start the server func (s *Simple) Start(c context.Context, h http.Handler) error { s.Handler = h diff --git a/servers/tls.go b/servers/tls.go index 826eaa748..5a48524ae 100644 --- a/servers/tls.go +++ b/servers/tls.go @@ -19,6 +19,11 @@ func (s *TLS) SetAddr(addr string) { } } +// Addr gets the HTTP server address +func (s *TLS) Addr() string { + return s.Server.Addr +} + // Start the server func (s *TLS) Start(c context.Context, h http.Handler) error { s.Handler = h From 7390982767d3daf838c22e5e64d6584391a3919a Mon Sep 17 00:00:00 2001 From: Liam Bowen Date: Tue, 26 Apr 2022 20:03:53 +0000 Subject: [PATCH 19/20] Revision as per @sio4 Makes changes backwards compatible and restores logging statement at beginning of startup --- server.go | 6 +++--- servers/listener.go | 7 ++++--- servers/servers.go | 1 - servers/simple.go | 7 ++++--- servers/tls.go | 7 ++++--- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/server.go b/server.go index 26a57e97c..d225904b9 100644 --- a/server.go +++ b/server.go @@ -22,6 +22,8 @@ import ( func (a *App) Serve(srvs ...servers.Server) error { var wg sync.WaitGroup + a.Logger.Debug("starting application") + payload := events.Payload{ "app": a, } @@ -31,7 +33,6 @@ func (a *App) Serve(srvs ...servers.Server) error { return err } - // Add default server if necessary if len(srvs) == 0 { if strings.HasPrefix(a.Options.Addr, "unix:") { tcp, err := servers.UnixSocket(a.Options.Addr[5:]) @@ -95,8 +96,7 @@ func (a *App) Serve(srvs ...servers.Server) error { for _, s := range srvs { s.SetAddr(a.Addr) - a.Logger.Infof("starting server of type %T at %s", - s, s.Addr()) + a.Logger.Infof("starting %s", s) wg.Add(1) go func(s servers.Server) { defer wg.Done() diff --git a/servers/listener.go b/servers/listener.go index 6f3497308..e0f985d76 100644 --- a/servers/listener.go +++ b/servers/listener.go @@ -2,6 +2,7 @@ package servers import ( "context" + "fmt" "net" "net/http" ) @@ -19,9 +20,9 @@ func (s *Listener) SetAddr(addr string) { } } -// Addr gets the HTTP server address -func (s *Listener) Addr() string { - return s.Server.Addr +// String returns a string representation of a Listener +func (s *Listener) String() string { + return fmt.Sprintf("listener on %s", s.Server.Addr) } // Start the server diff --git a/servers/servers.go b/servers/servers.go index 93d1f831d..4a703d74f 100644 --- a/servers/servers.go +++ b/servers/servers.go @@ -8,7 +8,6 @@ import ( // Server allows for custom server implementations type Server interface { - Addr() string Shutdown(context.Context) error Start(context.Context, http.Handler) error SetAddr(string) diff --git a/servers/simple.go b/servers/simple.go index 9b57a99c1..61891e441 100644 --- a/servers/simple.go +++ b/servers/simple.go @@ -2,6 +2,7 @@ package servers import ( "context" + "fmt" "net/http" ) @@ -17,9 +18,9 @@ func (s *Simple) SetAddr(addr string) { } } -// Addr gets the HTTP server address -func (s *Simple) Addr() string { - return s.Server.Addr +// String returns a string representation of a Simple server +func (s *Simple) String() string { + return fmt.Sprintf("simple server on %s", s.Server.Addr) } // Start the server diff --git a/servers/tls.go b/servers/tls.go index 5a48524ae..8e5f837b7 100644 --- a/servers/tls.go +++ b/servers/tls.go @@ -2,6 +2,7 @@ package servers import ( "context" + "fmt" "net/http" ) @@ -19,9 +20,9 @@ func (s *TLS) SetAddr(addr string) { } } -// Addr gets the HTTP server address -func (s *TLS) Addr() string { - return s.Server.Addr +// String returns a string representation of a Listener +func (s *TLS) String() string { + return fmt.Sprintf("TLS server on %s", s.Server.Addr) } // Start the server From 1b38e5b507bfd64324f012c12cd6cbaf706a5bea Mon Sep 17 00:00:00 2001 From: Antonio Pagano Date: Tue, 3 May 2022 19:12:13 -0500 Subject: [PATCH 20/20] task: updating version number --- runtime/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/version.go b/runtime/version.go index 701242d91..753bbdae1 100644 --- a/runtime/version.go +++ b/runtime/version.go @@ -1,4 +1,4 @@ package runtime // Version is the current version of the buffalo binary -var Version = "v0.18.6" +var Version = "v0.18.7"