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) } }
func init() { if profile.On { if devserver.IsActive() { t := newInternalTemplate(&App{}) t.tmpl.Funcs([]*template.Func{ {Name: "_gondola_profile_info", Fn: getProfileInfo}, {Name: "_gondola_internal_asset", Fn: func(arg string) string { return internalAssetsManager.URL(arg) }}, }) if err := t.parse("profile.html", nil); err != nil { panic(err) } profilePlugin = &template.Plugin{Template: t.tmpl, Position: assets.Bottom} } } }
// WebsocketURL returns an absolute websocket URL from a relative // URL (relative to the current request), adjusting also the protocol // (e.g. http to ws and https to wss). Note that this function calls // Context.URL(), so check its documentation to make sure the current // request URL can be correctly determined. func (c *Context) WebsocketURL(rel string) (*url.URL, error) { u, err := c.URL().Parse(rel) if err != nil { return nil, err } switch u.Scheme { case "http": u.Scheme = "ws" case "https": u.Scheme = "wss" } if sep := strings.IndexByte(u.Host, ':'); sep >= 0 && devserver.IsActive() { // If we're running from the development server, we need to send // the request directly to the app, since the httputil proxy doesn't // support websockets. u.Host = u.Host[:sep] + ":" + strconv.Itoa(c.app.Config().Port) } return u, nil }
// ListenAndServe starts listening on the configured address and // port (see Address() and Port). func (app *App) ListenAndServe() error { if err := app.Prepare(); err != nil { return err } if err := app.checkPort(); err != nil { return err } Signals.WillListen.emit(app) app.started = time.Now().UTC() if devserver.IsActive() { // Attach the automatic reload template plugin to automatically // reload the page when the server restarts vars := devserver.TemplateVars(&Context{}) plugin := devserver.ReloadPlugin() app.AddTemplateVars(vars) app.AddTemplatePlugin(plugin) for _, c := range app.included { c.app.AddTemplateVars(vars) c.app.AddTemplatePlugin(plugin) } } else { if app.Logger != nil { if app.address != "" { app.Logger.Infof("Listening on %s, port %d", app.address, app.cfg.Port) } else { app.Logger.Infof("Listening on port %d", app.cfg.Port) } } } var err error time.AfterFunc(500*time.Millisecond, func() { if err == nil { Signals.DidListen.emit(app) } }) err = http.ListenAndServe(app.address+":"+strconv.Itoa(app.cfg.Port), app) return err }