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

Commit

Permalink
Merge pull request #2226 from gochigo/fix-multi-homing
Browse files Browse the repository at this point in the history
Fixed multi-homing feature and related bugs. (#2222)
  • Loading branch information
paganotoni authored Apr 2, 2022
2 parents 999fb9d + efeb149 commit f330f9b
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 88 deletions.
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

0 comments on commit f330f9b

Please sign in to comment.