1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| package controller
import ( "fmt" "time"
"github.com/pkg/errors" "github.com/valyala/fasthttp"
"{{{ .Package }}}/app" "{{{ .Package }}}/app/controller/cutil" "{{{ .Package }}}/app/lib/telemetry"{{{ if .HasAccount }}} "{{{ .Package }}}/app/lib/user"{{{ end }}}{{{ if.HasModule "marketing" }}} "{{{ .Package }}}/app/site"{{{ end }}} "{{{ .Package }}}/app/util" )
func Act(key string, rc *fasthttp.RequestCtx, f func(as *app.State, ps *cutil.PageState) (string, error)) { as := _currentAppState ps := cutil.LoadPageState(as, rc, key, _currentAppRootLogger){{{ if .HasAccount }}} if allowed, reason := user.Check(string(ps.URI.Path()), ps.Accounts); !allowed { f = Unauthorized(rc, reason, ps.Accounts) }{{{ end }}} if err := initAppRequest(as, ps); err != nil { ps.Logger.Warnf("%+v", err) } actComplete(key, as, ps, rc, f) } {{{ if.HasModule "marketing" }}} func ActSite(key string, rc *fasthttp.RequestCtx, f func(as *app.State, ps *cutil.PageState) (string, error)) { as := _currentSiteState ps := cutil.LoadPageState(as, rc, key, _currentSiteRootLogger) ps.Menu = site.Menu(ps.Context, as, ps.Profile{{{ if .HasAccount }}}, ps.Accounts{{{ end }}}, ps.Logger){{{ if .HasAccount }}} if allowed, reason := user.Check(string(ps.URI.Path()), ps.Accounts); !allowed { f = Unauthorized(rc, reason, ps.Accounts) }{{{ end }}} if err := initSiteRequest(as, ps); err != nil { ps.Logger.Warnf("%+v", err) } actComplete(key, as, ps, rc, f) } {{{ end }}} func actComplete(key string, as *app.State, ps *cutil.PageState, rc *fasthttp.RequestCtx, f func(as *app.State, ps *cutil.PageState) (string, error)) { err := ps.Clean(rc, as) if err != nil { ps.Logger.Warnf("error while cleaning request, somehow: %+v", err) } status := fasthttp.StatusOK cutil.WriteCORS(rc) var redir string logger := ps.Logger ctx := ps.Context if !telemetry.SkipControllerMetrics { var span *telemetry.Span ctx, span, logger = telemetry.StartSpan(ps.Context, "controller."+key, ps.Logger) defer span.Complete() } logger = logger.With("path", string(rc.URI().Path()), "method", ps.Method, "status", status) ps.Context = ctx
if ps.ForceRedirect == "" || ps.ForceRedirect == string(rc.URI().Path()) { redir, err = safeRun(f, as, ps) if err != nil { redir, err = handleError(key, as, ps, rc, err) if err != nil { ps.Logger.Warnf("unable to handle error: %+v", err) } } } else { redir = ps.ForceRedirect } if redir != "" { rc.Response.Header.Set("Location", redir) status = fasthttp.StatusFound rc.SetStatusCode(status) } elapsedMillis := float64((util.TimeCurrentNanos()-ps.Started.UnixNano())/int64(time.Microsecond)) / float64(1000) defer ps.Close() rc.Response.Header.Set("Server-Timing", fmt.Sprintf("server:dur=%.3f", elapsedMillis)) logger = logger.With("elapsed", elapsedMillis) logger.Debugf("processed request in [%.3fms] (render: %.3fms)", elapsedMillis, ps.RenderElapsed) }
func safeRun(f func(as *app.State, ps *cutil.PageState) (string, error), as *app.State, ps *cutil.PageState) (s string, e error) { defer func() { if rec := recover(); rec != nil { if recoverErr, ok := rec.(error); ok { e = errors.Wrap(recoverErr, "panic") } else { e = errors.Errorf("controller encountered panic recovery of type [%T]: %s", rec, fmt.Sprint(rec)) } } }() s, e = f(as, ps) return }
|