func (app *App) errorPage(ctx *Context, elapsed time.Duration, skip int, stackSkip int, req string, err interface{}) { t := newInternalTemplate(app) if terr := t.parse("panic.html", devserver.TemplateVars(&Context{})); terr != nil { panic(terr) } if devserver.IsActive() { t.tmpl.AddPlugin(devserver.ReloadPlugin()) } if terr := t.prepare(); terr != nil { panic(terr) } stack := runtimeutil.FormatStackHTML(stackSkip + 1) location, code := runtimeutil.FormatCallerHTML(skip+1, 5, true, true) ctx.statusCode = -http.StatusInternalServerError data := map[string]interface{}{ "Error": fmt.Sprintf("%v", err), "Subtitle": fmt.Sprintf("(after %s)", elapsed), "Location": location, "Code": code, "Stack": stack, "Request": req, "Name": filepath.Base(os.Args[0]), "IsDevServer": devserver.IsDevServer(app), } if err := t.Execute(ctx, data); err != nil { var msg string if file, line, ok := runtimeutil.PanicLocation(); ok { msg = fmt.Sprintf("error rendering error page: %v @ %s:%d)", err, file, line) } else { msg = fmt.Sprintf("error rendering error page: %v", err) } ctx.WriteString(msg) } }
// Prepare is automatically called for you. This function is // only exposed because the gnd.la/app/tester package needs // to call it to set the App up without making it listen on // a port. func (app *App) Prepare() error { // Make Prepare() idempotent. Otherwise the tester package // would need a lot of extra logic to deal with GAE vs // non-GAE environments. if app.prepared { return nil } // Initialize the ORM first, so admin commands // run with the ORM ready to be used. if app.parent == nil { err := app.prepareOrm() if err != nil && err != errNoDefaultDatabase && err != errNoAppOrm { return err } } Signals.WillPrepare.emit(app) if s := app.cfg.Secret; s != "" && len(s) < 32 && os.Getenv("GONDOLA_ALLOW_SHORT_SECRET") == "" && !devserver.IsDevServer(app) { return fmt.Errorf("secret %q is too short, must be at least 32 characters - use gondola random-string to generate one", s) } for _, v := range app.included { child := v.app child.cfg = app.cfg child.CookieOptions = app.CookieOptions child.CookieCodec = app.CookieCodec child.Hasher = app.Hasher child.Cipherer = app.Cipherer child.languageHandler = app.languageHandler child.userFunc = app.userFunc child.Logger = app.Logger } // Add template plugins from each included app to all the other apps for _, h := range app.templatePlugins { if h.Position == assets.None { continue } for _, v := range app.included { child := v.app has := false for _, ch := range child.templatePlugins { if ch == h { has = true break } } if !has { child.templatePlugins = append(child.templatePlugins, h) } } } app.prepared = true Signals.DidPrepare.emit(app) return nil }