package wrapper import ( "bytes" "html/template" "log" "net" "net/http" "os" "strings" "golang-fave/constants" "golang-fave/engine/sessions" ) type handleRun func(wrapper *Wrapper) bool type tmplDataSystem struct { PathIcoFav string PathSvgLogo string PathCssStyles string PathCssCpStyles string PathCssBootstrap string PathJsJquery string PathJsPopper string PathJsBootstrap string PathJsCpScripts string } type TmplDataAll struct { System tmplDataSystem Data interface{} } type Wrapper struct { W *http.ResponseWriter R *http.Request VHost string Port string DirWww string DirVHostHome string RemoteIp string LoggerAcc *log.Logger LoggerErr *log.Logger Session *sessions.Session } func New(w *http.ResponseWriter, r *http.Request, vhost string, port string, wwwdir string, vhosthome string) *Wrapper { return &Wrapper{ VHost: vhost, Port: port, DirWww: wwwdir, DirVHostHome: vhosthome, W: w, R: r, } } func (this *Wrapper) Run(hRun handleRun) { // Populate some values this.RemoteIp = this.R.RemoteAddr // Create loggers this.LoggerAcc = log.New(os.Stdout, this.VHost+", ", log.LstdFlags) this.LoggerErr = log.New(os.Stdout, this.VHost+", ", log.LstdFlags) // Attach file for access log if !constants.Debug { acclogfile, acclogfileerr := os.OpenFile(this.DirVHostHome+"/logs/access.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if acclogfileerr == nil { defer acclogfile.Close() this.LoggerAcc.SetOutput(acclogfile) } } // Attach file for access log if !constants.Debug { errlogfile, errlogfileerr := os.OpenFile(this.DirVHostHome+"/logs/error.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if errlogfileerr == nil { defer errlogfile.Close() this.LoggerErr.SetOutput(errlogfile) } } // Fix remote IP if strings.ContainsRune(this.R.RemoteAddr, ':') { this.RemoteIp, _, _ = net.SplitHostPort(this.R.RemoteAddr) } // Redirect to main domain if this.redirectToMainDomain() { this.Log("301") return } // Static resource if this.staticResource() { this.Log("200") return } // Static file if this.staticFile() { this.Log("200") return } // Friendly search engine url if this.redirectSeoFix() { this.Log("301") return } // Create and load session this.Session = sessions.New(this.W, this.R, this.VHost, this.DirVHostHome, this.RemoteIp) this.Session.Load() // Set session vars if !this.Session.IsSetInt("UserId") { this.Session.SetInt("UserId", 0) } // Logic if hRun != nil { if hRun(this) { this.Log("200") this.Session.Save() return } } // Show default page if this.R.URL.Path == "/" { this.Log("200") this.printPageDefault() } else { this.LogError("404") this.printPage404() } } func (this *Wrapper) Log(value string) { this.LoggerAcc.Println("[ACC] [" + this.R.Method + "] [" + value + "] [" + this.RemoteIp + "] [" + this.R.URL.Scheme + "://" + this.R.Host + this.R.URL.RequestURI() + "] [" + this.R.Header.Get("User-Agent") + "]") } func (this *Wrapper) LogError(value string) { this.LoggerErr.Println("[ERR] [" + this.R.Method + "] [" + value + "] [" + this.RemoteIp + "] [" + this.R.URL.Scheme + "://" + this.R.Host + this.R.URL.RequestURI() + "] [" + this.R.Header.Get("User-Agent") + "]") } func (this *Wrapper) TmplGetSystemData() tmplDataSystem { return tmplDataSystem{ PathIcoFav: this.R.URL.Scheme + "://" + this.R.Host + "/assets/sys/fave.ico?v=" + constants.AssetsVersion, PathSvgLogo: this.R.URL.Scheme + "://" + this.R.Host + "/assets/sys/logo.svg?v=" + constants.AssetsVersion, PathCssStyles: this.R.URL.Scheme + "://" + this.R.Host + "/assets/sys/styles.css?v=" + constants.AssetsVersion, PathCssCpStyles: this.R.URL.Scheme + "://" + this.R.Host + "/assets/cp/styles.css?v=" + constants.AssetsVersion, PathCssBootstrap: this.R.URL.Scheme + "://" + this.R.Host + "/assets/sys/bootstrap.css?v=" + constants.AssetsVersion, PathJsJquery: this.R.URL.Scheme + "://" + this.R.Host + "/assets/sys/jquery.js?v=" + constants.AssetsVersion, PathJsPopper: this.R.URL.Scheme + "://" + this.R.Host + "/assets/sys/popper.js?v=" + constants.AssetsVersion, PathJsBootstrap: this.R.URL.Scheme + "://" + this.R.Host + "/assets/sys/bootstrap.js?v=" + constants.AssetsVersion, PathJsCpScripts: this.R.URL.Scheme + "://" + this.R.Host + "/assets/cp/scripts.js?v=" + constants.AssetsVersion, } } func (this *Wrapper) TmplParseToString(tcont []byte, data interface{}) string { tmpl, err := template.New("template").Parse(string(tcont)) if err != nil { return err.Error() } var tpl bytes.Buffer if err := tmpl.Execute(&tpl, data); err != nil { return err.Error() } return tpl.String() } func (this *Wrapper) TmplFrontEnd(tname string, data interface{}) bool { tmpl, err := template.ParseFiles( this.DirVHostHome+"/template"+"/"+tname+".html", this.DirVHostHome+"/template"+"/header.html", this.DirVHostHome+"/template"+"/sidebar.html", this.DirVHostHome+"/template"+"/footer.html", ) if err != nil { this.printTmplPageError(err) return true } (*this.W).Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") tmpl.Execute(*this.W, TmplDataAll{ System: this.TmplGetSystemData(), Data: data, }) return true } func (this *Wrapper) TmplBackEnd(tcont []byte, data interface{}) bool { tmpl, err := template.New("template").Parse(string(tcont)) if err != nil { this.printTmplPageError(err) return true } (*this.W).Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") tmpl.Execute(*this.W, TmplDataAll{ System: this.TmplGetSystemData(), Data: data, }) return true } func (this *Wrapper) EngineErrMsgOnError(err error) bool { if err != nil { this.PrintEnginePageError(err) return true } return false }