package servlet import ( "fmt" "geniuscartel.xyz/vinegar/vinegarUtil" "log" "net/http" "os" "regexp" "strconv" ) const ( defaultLruSize = int64(1024 * 1024 * 50) ContentTypeHeaderKey = "Content-Type" ContentEncodingHeaderKey = "Content-Encoding" AcceptEncodingHeaderKey = "Accept-Encoding" ) type ErrorResponse struct { Code int Message string } type ( VinegarServlet struct { Port string Routes []*VinegarRoute ErrorRoutes map[int]*TemplateRoute } VinegarRoute struct { Pattern *regexp.Regexp Handler VinegarHandlerFunction Cache vinegarUtil.Cache } VinegarHandlerFunction func(w http.ResponseWriter, req *http.Request) ) func NewServlet(port string) *VinegarServlet { errors := make(map[int]*TemplateRoute) srv := VinegarServlet{Port: port, ErrorRoutes: errors} return &srv } func NewServletRoute(routePattern string, handleFunc VinegarHandlerFunction) *VinegarRoute { pattern := regexp.MustCompile(routePattern) route := VinegarRoute{Pattern: pattern, Handler: handleFunc, Cache: vinegarUtil.NewLRU(defaultLruSize)} return &route } func (s *VinegarServlet) AddRoute(route *VinegarRoute) { route.Announce() s.Routes = append(s.Routes, route) } func (s *VinegarServlet) AddErrorRoute(code int, route *TemplateRoute) { route.Announce() s.ErrorRoutes[code] = route } func (s *VinegarServlet) ServeHTTP(w http.ResponseWriter, req *http.Request) { path := req.URL.Path for _, route := range s.Routes { if route.Pattern.MatchString(path) { //fmt.Printf("SERVING: [%s]=>{%s}\n", path, route.Pattern.String()) route.Handler(w, req) return } } s.SendError(w, 404, "Couldn't find your content.") } func (s *VinegarServlet) Start() { if len(s.Routes) < 1 { log.Fatal("No routes found for server. Nothing to listen and serve.") os.Exit(1) } log.Printf("Listening on [%s]\n", s.Port) err := http.ListenAndServe(s.Port, s) if err != nil { panic(err) } } func (r *VinegarRoute) Announce() { log.Printf("Added route for [%s]\n", r.Pattern.String()) } func (s *VinegarServlet) SendError(w http.ResponseWriter, code int, msg string) { fmt.Printf("Reached SendError. Rendering template for code %d with message: %s\n", code, msg) tmpl, exists := s.ErrorRoutes[code] if exists { tmpl.TemplateManager.AddMixin("code", strconv.Itoa(code)) tmpl.TemplateManager.AddMixin("msg", msg) } w.WriteHeader(code) _, err := w.Write([]byte(tmpl.TemplateManager.RenderTemplate(fmt.Sprintf("%d.html", code)))) if err != nil { panic(err) } return }