vinegar/servlet/server.go
2022-07-18 17:00:22 -04:00

129 lines
2.3 KiB
Go

package servlet
import (
"fmt"
"html/template"
"io/ioutil"
"net/http"
"os"
"regexp"
"vinegar/cacheutil"
)
const (
defaultLruSize = int64(1024 * 1024 * 50)
ContentTypeHeaderKey = "Content-Type"
ContentEncodingHeaderKey = "Content-Encoding"
)
type ErrorResponse struct {
Code int
Message string
}
type (
VinegarServlet struct {
Port string
Routes []*VinegarRoute
Cache *cacheutil.Lru
}
VinegarRoute struct {
Pattern *regexp.Regexp
Handler VinegarHandlerFunction
}
VinegarHandlerFunction func(w http.ResponseWriter, req *http.Request)
)
func NewServlet(port string) *VinegarServlet {
lru := cacheutil.NewLRU(defaultLruSize)
srv := VinegarServlet{Port: port, Cache: lru}
return &srv
}
func NewServletRoute(routePattern string, handleFunc VinegarHandlerFunction) *VinegarRoute {
route := VinegarRoute{}
pattern := regexp.MustCompile(routePattern)
route.Pattern = pattern
route.Handler = handleFunc
return &route
}
func (s *VinegarServlet) AddRoute(route *VinegarRoute) {
s.Routes = append(s.Routes, route)
}
func (s *VinegarServlet) 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 *VinegarServlet) {
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)
}
}