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

123 lines
3.3 KiB
Go

package servlet
import (
"net/http"
"path"
"strings"
"vinegar/cacheutil"
)
type (
FileRoute struct {
*VinegarRoute
fileRoot string
}
)
func NewImageRoute(urlPattern string, pathlike string, servlet *VinegarServlet) *FileRoute {
defaultPrune := strings.Replace(urlPattern, ".*", "", -1)
rootRoute := NewServletRoute(urlPattern, createUncompressedFileServletFunction(defaultPrune, pathlike, servlet.Cache))
imgRoute := FileRoute{rootRoute, pathlike}
return &imgRoute
}
func NewTextRoute(urlPattern string, pathlike string, servlet *VinegarServlet) *FileRoute {
defaultPrune := strings.Replace(urlPattern, ".*", "", -1)
rootRoute := NewServletRoute(urlPattern, createCompressibleFileServletFunction(defaultPrune, pathlike, servlet.Cache))
fr := FileRoute{rootRoute, pathlike}
return &fr
}
func NewSingleFileRoute(urlPattern string, pathlike string, servlet *VinegarServlet) *FileRoute {
fun := createSingleFileServletFunction(pathlike)
route := FileRoute{
VinegarRoute: NewServletRoute("^"+urlPattern+"$", fun),
fileRoot: pathlike,
}
return &route
}
func createSingleFileServletFunction(pathlike string) VinegarHandlerFunction {
cache := cacheutil.NewSingleFileCache(pathlike)
var fun VinegarHandlerFunction = func(w http.ResponseWriter, req *http.Request) {
w.Header().Add(ContentTypeHeaderKey, cache.Mimetype)
if clientAcceptsGzip(req) {
w.Header().Add(ContentEncodingHeaderKey, "gzip")
_, err := w.Write(*cache.CompressedContent)
if err != nil {
panic(err)
}
}
}
return fun
}
func createCompressibleFileServletFunction(basePattern string, pathlike string, cache *cacheutil.Lru) VinegarHandlerFunction {
var fun VinegarHandlerFunction = func(w http.ResponseWriter, req *http.Request) {
stub := strings.Replace(req.URL.Path, basePattern, "", 1)
cachedContent, exists := cache.Get(stub)
if !exists {
content, fileExists := cacheutil.GetDiskContent(path.Join(pathlike, stub))
if fileExists {
cache.Put(stub, content)
cachedContent, _ = cache.Get(stub)
} else {
SendError(w, 404, "Oops! Something went wrong.")
return
}
}
w.Header().Add(ContentTypeHeaderKey, cachedContent.MimeType)
var err error = nil
if clientAcceptsGzip(req) {
w.Header().Add(ContentEncodingHeaderKey, "gzip")
_, err = w.Write(cachedContent.CompressedContent)
} else {
_, err = w.Write(cachedContent.Content)
}
if err != nil {
panic(err)
}
}
return fun
}
func createUncompressedFileServletFunction(basePattern string, pathlike string, cache *cacheutil.Lru) VinegarHandlerFunction {
var fun VinegarHandlerFunction = func(w http.ResponseWriter, req *http.Request) {
stub := strings.Replace(req.URL.Path, basePattern, "", 1)
entry, exists := cache.Get(stub)
if !exists {
fileContent, fExists := cacheutil.GetDiskContent(path.Join(pathlike, stub))
if fExists {
cache.Put(stub, fileContent)
entry, exists = cache.Get(stub)
} else {
SendError(w, 404, "Oops! Something went wrong!")
return
}
}
if !exists {
SendError(w, 404, "Oops! Something went wrong.")
} else {
_, err := w.Write(entry.Content)
if err != nil {
panic(err)
}
return
}
}
return fun
}
func clientAcceptsGzip(req *http.Request) bool {
encodings := req.Header.Get("Accept-Encoding")
if strings.Contains(encodings, "gzip") {
return true
}
return false
}