Skip to content
This repository has been archived by the owner on Feb 24, 2024. It is now read-only.

Fixed multi-homing feature and related bugs. (#2222) #2226

Merged
merged 4 commits into from
Apr 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 18 additions & 13 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -44,17 +42,24 @@ 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{},

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)
Expand Down
30 changes: 16 additions & 14 deletions grifts.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,33 +44,35 @@ 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]
if h == r.HandlerName {
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)
}
}
Expand Down Expand Up @@ -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
Expand Down
39 changes: 39 additions & 0 deletions home.go
Original file line number Diff line number Diff line change
@@ -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
}
14 changes: 12 additions & 2 deletions route.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -64,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
}

Expand Down
2 changes: 1 addition & 1 deletion route_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
Loading