package internal import ( "fmt" "html/template" "net/http" "strings" rice "github.com/GeertJohan/go.rice" "github.com/gomarkdown/markdown" "github.com/gomarkdown/markdown/html" "github.com/gomarkdown/markdown/parser" "github.com/james4k/fmatter" "github.com/julienschmidt/httprouter" log "github.com/sirupsen/logrus" ) const ( MaxFailedLogins = 3 // By default 3 failed login attempts per 5 minutes ) func (s *Server) NotFoundHandler(w http.ResponseWriter, r *http.Request) { if r.Header.Get("Accept") == "application/json" { w.Header().Set("Content-Type", "application/json") http.Error(w, "Endpoint Not Found", http.StatusNotFound) return } ctx := NewContext(s.config, s.db, r) ctx.Title = "Page Not Found" w.WriteHeader(http.StatusNotFound) s.render("404", w, ctx) } type FrontMatter struct { Title string } // PageHandler ... func (s *Server) PageHandler(name string) httprouter.Handle { box := rice.MustFindBox("pages") mdTpl := box.MustString(fmt.Sprintf("%s.md", name)) return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { ctx := NewContext(s.config, s.db, r) md, err := RenderString(mdTpl, ctx) if err != nil { log.WithError(err).Errorf("error rendering page %s", name) ctx.Error = true ctx.Message = "Error loading help page! Please contact support." s.render("error", w, ctx) return } var frontmatter FrontMatter content, err := fmatter.Read([]byte(md), &frontmatter) if err != nil { log.WithError(err).Error("error parsing front matter") ctx.Error = true ctx.Message = "Error loading page! Please contact support." s.render("error", w, ctx) return } extensions := parser.CommonExtensions | parser.AutoHeadingIDs p := parser.NewWithExtensions(extensions) htmlFlags := html.CommonFlags opts := html.RendererOptions{ Flags: htmlFlags, Generator: "", } renderer := html.NewRenderer(opts) html := markdown.ToHTML(content, p, renderer) var title string if frontmatter.Title != "" { title = frontmatter.Title } else { title = strings.Title(name) } ctx.Title = title ctx.Page = name ctx.Content = template.HTML(html) s.render("page", w, ctx) } } // IndexHandler ... func (s *Server) IndexHandler() httprouter.Handle { return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { ctx := NewContext(s.config, s.db, r) s.render("index", w, ctx) } } // AddHandler ... func (s *Server) AddHandler() httprouter.Handle { return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { ctx := NewContext(s.config, s.db, r) if r.Method == http.MethodGet { s.render("add", w, ctx) return } url := NormalizeURL(strings.TrimSpace(r.FormValue("url"))) if url == "" { ctx.Error = true ctx.Message = "Invalid URL" s.render("error", w, ctx) return } if err := s.crawler.Crawl(url); err != nil { ctx.Error = true ctx.Message = fmt.Sprintf("Error adding URL: %s", err) s.render("error", w, ctx) return } ctx.Error = false ctx.Message = "Successfully added url" s.render("error", w, ctx) } } // CacheHandler ... func (s *Server) CacheHandler() httprouter.Handle { return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { ctx := NewContext(s.config, s.db, r) s.render("cache", w, ctx) } } // SearchHandler ... func (s *Server) SearchHandler() httprouter.Handle { return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { ctx := NewContext(s.config, s.db, r) q := strings.TrimSpace(r.FormValue("q")) if q == "" { ctx.Error = true ctx.Message = "Error empty search" s.render("error", w, ctx) return } results, err := s.indexer.Search(q) if err != nil { log.WithError(err).Error("error performing search") ctx.Error = true ctx.Message = "Error performing search, please try again later" s.render("error", w, ctx) return } log.Debug(results) s.render("search", w, ctx) } }