package core
import (
"fmt"
"html/template"
"io/ioutil"
"net/http"
"os"
"regexp"
)
const (
defaultLruSize = int64(1024 * 1024 * 50)
)
type ErrorResponse struct {
Code int
Message string
}
type (
Servlet struct {
Port string
Routes []*ServletRoute
Cache *Lru
}
ServletRoute struct {
Pattern *regexp.Regexp
Handler ServletHandleFunction
}
ServletHandleFunction func(w http.ResponseWriter, req *http.Request)
)
func NewServlet(port string) *Servlet {
lru := NewLRU(defaultLruSize)
srv := Servlet{Port: port, Cache: lru}
return &srv
}
func NewServletRoute(routePattern string, handleFunc ServletHandleFunction) *ServletRoute {
route := ServletRoute{}
pattern := regexp.MustCompile(routePattern)
route.Pattern = pattern
route.Handler = handleFunc
return &route
}
func (s *Servlet) AddRoute(route *ServletRoute) {
s.Routes = append(s.Routes, route)
}
func (s *Servlet) ServeHTTP(w http.ResponseWriter, req *http.Request) {
path := req.URL.Path
fmt.Println("Attempting to match request for " + path)
for _, route := range s.Routes {
if route.Pattern.MatchString(path) {
route.Handler(w, req)
return
}
}
}
func StartServerGood(s *Servlet) {
err := http.ListenAndServe(s.Port, s)
if err != nil {
panic(err)
}
}
func SendError(w http.ResponseWriter, code int, msg string) {
errorFile := "templates/error.html"
errorResp := ErrorResponse{code, msg}
tmplManager := template.New("error")
f, err := os.OpenFile(errorFile, os.O_RDONLY, 0777)
if err != nil {
panic(err)
}
defer f.Close()
content, err := ioutil.ReadAll(f)
if err != nil {
panic(err)
}
tmpl, err := tmplManager.Parse(string(content))
if err != nil {
panic(err)
}
w.WriteHeader(code)
err = tmpl.Execute(w, errorResp)
if err != nil {
panic(err)
}
}
func renderTemplate(w http.ResponseWriter, pathlike string, data any) {
templateHelper := template.New(pathlike)
f, err := os.OpenFile(pathlike, os.O_RDONLY, 0777)
if err != nil {
panic(err)
}
defer f.Close()
content, err := ioutil.ReadAll(f)
if err != nil {
panic(err)
}
templ, err := templateHelper.Parse(string(content))
err = templ.Execute(w, data)
if err != nil {
panic(err)
}
}