diff --git a/errors.go b/errors.go index 4bfb667d6..f98595419 100644 --- a/errors.go +++ b/errors.go @@ -112,14 +112,12 @@ func (a *App) defaultErrorMiddleware(next Handler) Handler { } status := http.StatusInternalServerError // unpack root err and check for HTTPError - switch { - case errors.Is(err, sql.ErrNoRows): + if errors.Is(err, sql.ErrNoRows) { status = http.StatusNotFound - default: - var h HTTPError - if errors.As(err, &h) { - status = h.Status - } + } + var h HTTPError + if errors.As(err, &h) { + status = h.Status } payload := events.Payload{ "context": c, diff --git a/route_info.go b/route_info.go index 7fa122039..8bb849ce0 100644 --- a/route_info.go +++ b/route_info.go @@ -84,7 +84,7 @@ func (ri *RouteInfo) BuildPathHelper() RouteHelperFunc { return "", fmt.Errorf("missing parameters for %v: %s", cRoute.Path, err) } - result := url.Path + result := url.String() result = addExtraParamsTo(result, opts) return template.HTML(result), nil diff --git a/route_info_test.go b/route_info_test.go index 4475c3840..b24039cd1 100644 --- a/route_info_test.go +++ b/route_info_test.go @@ -2,6 +2,7 @@ package buffalo import ( "database/sql" + "fmt" "net/http" "testing" @@ -22,6 +23,18 @@ func Test_RouteInfo_ServeHTTP_SQL_Error(t *testing.T) { return sql.ErrNoRows }) + app.GET("/bad-2", func(c Context) error { + return sql.ErrTxDone + }) + + app.GET("/gone-unwrap", func(c Context) error { + return c.Error(http.StatusGone, sql.ErrTxDone) + }) + + app.GET("/gone-wrap", func(c Context) error { + return c.Error(http.StatusGone, fmt.Errorf("some error wrapping here: %w", sql.ErrNoRows)) + }) + w := httptest.New(app) res := w.HTML("/good").Get() @@ -29,4 +42,10 @@ func Test_RouteInfo_ServeHTTP_SQL_Error(t *testing.T) { res = w.HTML("/bad").Get() r.Equal(http.StatusNotFound, res.Code) + + res = w.HTML("/gone-wrap").Get() + r.Equal(http.StatusGone, res.Code) + + res = w.HTML("/gone-unwrap").Get() + r.Equal(http.StatusGone, res.Code) } diff --git a/route_mappings.go b/route_mappings.go index 1e860b018..4f42b0551 100644 --- a/route_mappings.go +++ b/route_mappings.go @@ -84,6 +84,29 @@ 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 { + g := New(a.Options) + + 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 + } + + return g +} + // ServeFiles maps an path to a directory on disk to serve static files. // Useful for JavaScript, images, CSS, etc... /* diff --git a/route_mappings_test.go b/route_mappings_test.go index 5ab171bb0..fe80e2888 100644 --- a/route_mappings_test.go +++ b/route_mappings_test.go @@ -154,3 +154,60 @@ func Test_App_Routes_Resource(t *testing.T) { } } } + +func Test_App_Host(t *testing.T) { + r := require.New(t) + + a1 := New(Options{}) + r.Nil(a1.root) + + h1 := a1.Host("www.example.com") + h1.GET("/foo", voidHandler) + + routes := h1.Routes() + r.Len(routes, 1) + + route := routes[0] + r.Equal("GET", route.Method) + r.Equal("/foo/", route.Path) + r.NotZero(route.HandlerName) + + // With Regular Expressions + + a2 := New(Options{}) + r.Nil(a1.root) + + h2 := a2.Host("{subdomain}.example.com") + h2.GET("/foo", voidHandler) + h2.GET("/foo/{id}", voidHandler).Name("fooID") + + rh := h2.RouteHelpers() + + routes = h2.Routes() + r.Len(routes, 2) + + r.Equal("GET", routes[0].Method) + r.Equal("/foo/", routes[0].Path) + r.NotZero(routes[0].HandlerName) + + r.Equal("GET", routes[1].Method) + r.Equal("/foo/{id}/", routes[1].Path) + r.NotZero(routes[1].HandlerName) + + f, ok := rh["fooPath"] + r.True(ok) + x, err := f(map[string]interface{}{ + "subdomain": "test", + }) + r.NoError(err) + r.Equal("http://test.example.com/foo/", string(x)) + + f, ok = rh["fooIDPath"] + r.True(ok) + x, err = f(map[string]interface{}{ + "subdomain": "test", + "id": 1, + }) + r.NoError(err) + r.Equal("http://test.example.com/foo/1/", string(x)) +} diff --git a/runtime/version.go b/runtime/version.go index dcec814ed..c6eafa101 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.1" +var Version = "v0.18.2"