//will catch a panic and if the logger is set will log it, if not will panic again func PanicCatcher(w http.ResponseWriter, r *http.Request) { ctx := httpway.GetContext(r) defer func() { if rec := recover(); rec != nil { if ctx.StatusCode() == 0 { w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(w, "Internal Server error") if _, ok := w.(http.Flusher); ok { println("HAHAHAHAHA FLUSHER") } } if !ctx.HasLog() { panic(rec) } file, line := getFileLine() ctx.Log().Error("Panic catched on %s:%d - %s", file, line, rec) } }() ctx.Next(w, r) }
func Profile(w http.ResponseWriter, r *http.Request) { ctx := httpway.GetContext(r) fmt.Fprintf(w, "logged in: %s", ctx.Session().Username()) ctx.Log().Info("profile") }
func AccessLogger(w http.ResponseWriter, r *http.Request) { startTime := time.Now() httpway.GetContext(r).Next(w, r) fmt.Printf("Request: %s duration: %s\n", r.URL.EscapedPath(), time.Since(startTime)) }
func AuthCheck(w http.ResponseWriter, r *http.Request) { ctx := httpway.GetContext(r) if r.URL.EscapedPath() == "/public" { http.Error(w, "Auth required", http.StatusForbidden) return } ctx.Next(w, r) }
func Logout(w http.ResponseWriter, r *http.Request) { ctx := httpway.GetContext(r) sess := ctx.Session().(*httpwaymid.Session) sess.SetUsername("") sess.SetAuth(false) fmt.Fprint(w, "logged out") ctx.Log().Info("logout") }
func Index(w http.ResponseWriter, r *http.Request) { ctx := httpway.GetContext(r) if ctx.Session().IsAuth() { fmt.Fprintf(w, "index data for: %s", ctx.Session().Username()) } else { fmt.Fprint(w, "index data") } ctx.Log().Info("index") }
func Login(w http.ResponseWriter, r *http.Request) { ctx := httpway.GetContext(r) sess := ctx.Session().(*httpwaymid.Session) sess.SetUsername(ctx.ParamByName("username")) sess.SetAuth(true) fmt.Fprint(w, "logged in") ctx.Log().Info("login") }
//this handler will write to logger function (the one form parameter) the w3c access log //this are the fields: //#Fields: c-ip x-c-user date time cs-method cs-uri-stem cs-uri-query cs(X-Forwarded-For) sc-bytes sc-status time-taken //when you first init or change logging file, call AccessLogHeader to write the w3c fields func AccessLog(logger func(v ...interface{})) httpway.Handler { return func(w http.ResponseWriter, r *http.Request) { ctx := httpway.GetContext(r) starttime := time.Now() ctx.Next(w, r) username := "******" if ctx.HasSession() && ctx.Session().Username() != "" { username = ctx.Session().Username() } ip, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { ip = r.RemoteAddr } query := r.URL.RawQuery if query == "" { query = "-" } xforwarded := r.Header.Get("X-Forwarded-For") if xforwarded != "" { tmpsplit := strings.Split(xforwarded, ",") if len(tmpsplit) > 0 { xforwarded = tmpsplit[len(tmpsplit)-1] } xforwarded = strings.Trim(xforwarded, " ") } else { xforwarded = "-" } statuscode := ctx.StatusCode() if statuscode == 0 { statuscode = 200 } logger("%s %s %s %s %s %s %s %d %d %d", ip, username, starttime.UTC().Format("2006-01-02 15:04:05"), r.Method, r.URL.EscapedPath(), query, xforwarded, ctx.TransferedBytes(), statuscode, time.Since(starttime).Nanoseconds()/1000, ) } }
func MiddlewaresFactory(router *httpway.Router) (routes map[string]*httpway.Router) { routes = make(map[string]*httpway.Router) routes["public"] = router routes["private"] = router.Middleware(func(w http.ResponseWriter, r *http.Request) { ctx := httpway.GetContext(r) if !ctx.Session().IsAuth() { w.WriteHeader(http.StatusUnauthorized) fmt.Fprint(w, "Not authenticated") return } ctx.Next(w, r) }) return }
// a simple golang Template Renderer // this will scan the templeteDir and load all the files that ends in tmpl // in handler you must set "ctxTemplateNameVar" wich is the template file name and // "ctxTempalteDataVar" the data to pass to the template // you can set a diffrent (the 200) http status code with "ctxHttpStatusCodeVar" func TemplateRenderer(templateDir, ctxTemplateNameVar, ctxTempalteDataVar, ctxHttpStatusCodeVar string) httpway.Handler { templates := template.Must(parseFiles(templateDir, getAllTemplatesFiles(templateDir)...)) return func(w http.ResponseWriter, r *http.Request) { ctx := httpway.GetContext(r) ctx.Next(w, r) if ctx.Has(ctxTempalteDataVar) && ctx.Has(ctxTemplateNameVar) { if ctx.Has(ctxHttpStatusCodeVar) { w.WriteHeader(ctx.Get(ctxHttpStatusCodeVar).(int)) } err := templates.ExecuteTemplate(w, ctx.Get(ctxTemplateNameVar).(string), ctx.Get(ctxTempalteDataVar)) if err != nil { ctx.Log().Error("I was unable to execute template %s with error: %s", ctx.Get(ctxTemplateNameVar), err) } } } }
//a simple JSON renderer //from your handler you need to set on context your data (and optional the http status code) //you need to set here what are those keys where you are going to save them //data from ctx key "ctxDataVar" must be and object that can be marshal by json.Marshal //data from ctx key "ctxHttpStatusCodeVar" must be int func JSONRenderer(ctxDataVar, ctxHttpStatusCodeVar string) httpway.Handler { return func(w http.ResponseWriter, r *http.Request) { ctx := httpway.GetContext(r) ctx.Next(w, r) if ctx.Has(ctxDataVar) { if ctx.StatusCode() != 0 { ctx.Log().Error("I have json from context to write but the status already set") return } w.Header().Set("Content-Type", "application/json") data, err := json.Marshal(ctx.Get(ctxDataVar)) if err != nil { ctx.Log().Error("I was unable to marshal to json: %s", err) w.Write([]byte("{\"Error\": \"Internal server error\"}")) w.WriteHeader(http.StatusInternalServerError) return } if ctx.Has(ctxHttpStatusCodeVar) { w.WriteHeader(ctx.Get(ctxHttpStatusCodeVar).(int)) } n, err := w.Write(data) if err != nil { ctx.Log().Error("I was unable to write payload to the socket: %s", err) return } if n != len(data) { ctx.Log().Error("Not all data was written to the socket expected: %d sent %d (fix this with some retry's)", len(data), n) } } } }