diff --git a/router.go b/router.go index 3c36cbe3c..84dbeb71c 100644 --- a/router.go +++ b/router.go @@ -147,6 +147,13 @@ func (r *Route) Match(method string, reqPath string) *RouteMatch { } } + // Special handling for explicit 404's. + if action == "404" { + return &RouteMatch{ + Action: "404", + } + } + // Split the action into controller and method actionSplit := strings.Split(action, ".") if len(actionSplit) != 2 { @@ -236,6 +243,11 @@ func (router *Router) validate(route *Route) *Error { return nil } + // Skip 404s + if route.Action == "404" { + return nil + } + // We should be able to load the action. parts := strings.Split(route.Action, ".") if len(parts) != 2 { diff --git a/router_test.go b/router_test.go index 480fe2436..9f7df2c0a 100644 --- a/router_test.go +++ b/router_test.go @@ -148,7 +148,9 @@ GET /app/{id} Application.Show POST /app/{id} Application.Save GET /public/ staticDir:www -* /{controller}/{action} {controller}.{action} +* /{controller}/{action} {controller}.{action} + +GET /favicon.ico 404 ` var routeMatchTestCases = map[*http.Request]*RouteMatch{ @@ -201,6 +203,17 @@ var routeMatchTestCases = map[*http.Request]*RouteMatch{ Params: map[string]string{"controller": "Implicit", "action": "Route"}, StaticFilename: "", }, + + &http.Request{ + Method: "GET", + URL: &url.URL{Path: "/favicon.ico"}, + }: &RouteMatch{ + ControllerName: "", + MethodName: "", + Action: "404", + Params: map[string]string{}, + StaticFilename: "", + }, } func TestRouteMatches(t *testing.T) { diff --git a/server.go b/server.go index f35622210..859e1fff2 100644 --- a/server.go +++ b/server.go @@ -50,6 +50,12 @@ func handleInternal(w http.ResponseWriter, r *http.Request, ws *websocket.Conn) return } + // The route may want to explicitly return a 404. + if route.Action == "404" { + NotFound(req, resp, "(intentionally)") + return + } + // Dispatch the static files first. if route.StaticFilename != "" { http.ServeFile(w, r, route.StaticFilename)