Beispiel #1
0
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)
	}
}
Beispiel #2
0
func (s *State) recover(pc *int, tmpl *string, err *error) {
	if r := recover(); r != nil {
		e, ok := r.(error)
		if !ok {
			e = fmt.Errorf("%v", r)
		}
		if file, line, ok := runtimeutil.PanicLocation(); ok {
			e = fmt.Errorf("%v (at %s:%d)", e, file, line)
		}
		*err = s.formatErr(*pc, *tmpl, e)
	}
}
Beispiel #3
0
func (ns *namespace) eval(ctx *Context) (m map[string]interface{}, err error) {
	defer func() {
		if r := recover(); r != nil {
			var pe error
			if e, ok := r.(error); ok {
				pe = e
			} else {
				pe = fmt.Errorf("%v", r)
			}
			err = pe
			if file, line, ok := runtimeutil.PanicLocation(); ok {
				err = fmt.Errorf("%v (at %s:%d)", pe, file, line)
			}
		}
	}()
	m = make(map[string]interface{}, len(ns.vars)+len(ns.funcs)+len(ns.namespaces)+2)
	for k, v := range ns.vars {
		m[k] = v
	}
	in := []reflect.Value{reflect.ValueOf(ctx)}
	for k, v := range ns.funcs {
		var out []reflect.Value
		if v.Type().NumIn() == 0 {
			out = v.Call(nil)
		} else {
			if ctx == nil {
				m[k] = nil
				continue
			}
			out = v.Call(in)
		}
		if len(out) == 2 && !out[1].IsNil() {
			return nil, out[1].Interface().(error)
		}
		m[k] = out[0].Interface()
	}
	m["Ctx"] = ctx
	if ctx != nil {
		m["Request"] = ctx.R
	}
	for k, v := range ns.namespaces {
		if m[k], err = v.eval(ctx); err != nil {
			return nil, err
		}
	}
	return m, nil
}
Beispiel #4
0
func executeCommand(name string, cmd *command, args []string, a *app.App) (err error) {
	// Parse command flags
	set := flag.NewFlagSet(name, flag.ContinueOnError)
	set.Usage = func() {
		commandHelp(name, -1, os.Stderr)
	}
	flags := map[string]interface{}{}
	for _, arg := range cmd.opts.Flags {
		switch arg.typ {
		case typBool:
			var b bool
			set.BoolVar(&b, arg.name, arg.def.(bool), arg.help)
			flags[arg.name] = &b
		case typInt:
			var i int
			set.IntVar(&i, arg.name, arg.def.(int), arg.help)
			flags[arg.name] = &i
		case typString:
			var s string
			set.StringVar(&s, arg.name, arg.def.(string), arg.help)
			flags[arg.name] = &s
		default:
			panic("invalid arg type")
		}
	}
	// Print error/help messages ourselves
	set.SetOutput(ioutil.Discard)
	err = set.Parse(args)
	if err != nil {
		if err == flag.ErrHelp {
			return
		}
		if strings.Contains(err.Error(), "provided but not defined") {
			flagName := strings.TrimSpace(strings.Split(err.Error(), ":")[1])
			fmt.Fprintf(os.Stderr, "command %s does not accept flag %s\n", name, flagName)
			return
		}
		return err
	}
	var params []string
	paramValues := make(map[string]string)
	for _, arg := range cmd.opts.Flags {
		params = append(params, arg.name)
		paramValues[arg.name] = fmt.Sprintf("%v", reflect.ValueOf(flags[arg.name]).Elem().Interface())
	}
	provider := &contextProvider{
		args:        set.Args(),
		params:      params,
		paramValues: paramValues,
	}
	if os.Getenv("GONDOLA_COMMANDS_NO_RECOVER") == "" {
		defer func() {
			if r := recover(); r != nil {
				if e, ok := r.(error); ok {
					err = e
				} else {
					err = fmt.Errorf("%v", r)
				}
				if file, line, ok := runtimeutil.PanicLocation(); ok {
					err = fmt.Errorf("%v (at %s:%d)", err, file, line)
				}
			}
		}()
	}
	ctx := a.NewContext(provider)
	defer a.CloseContext(ctx)
	cmd.handler(ctx)
	return
}