func (h *Router) Serve(session *http.Session) { for _, route := range h.Routes { if matches := route.Route.Pattern.FindStringSubmatch(session.Request.URL.Path); len(matches) > 0 { _, ok := route.Route.Methods[session.Request.Method] if ok { for i, named := range route.Route.Pattern.SubexpNames() { if len(named) > 0 { log.Trace("Matched named pattern '%s': %s", named, matches[i]) session.Stash[named] = matches[i] } } session.Route = route.Route defer func() { if e := recover(); e != nil { switch e.(type) { case string: session.RenderException(500, errors.New(e.(string))) default: session.RenderException(500, e.(error)) } session.Response.Send() session.Response.Close() } }() var wg sync.WaitGroup wg.Add(1) // func() will be executed only if *all* event handlers call next() h.Config.Events.Emit(session, events.BeforeHandler, func() { route.Handler.ServeHTTP(session) h.Config.Events.Emit(session, events.AfterHandler, func() { session.Response.Send() session.Response.Close() wg.Done() }) }) wg.Wait() return } } } // no pattern matched; send 404 response h.Config.Events.Emit(session, events.BeforeHandler, func() { session.RenderNotFound() h.Config.Events.Emit(session, events.AfterHandler, func() { session.Response.Send() }) }) }