vinegar/servlet/staticRoute.go

155 lines
4.1 KiB
Go

package servlet
import (
"fmt"
"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) {
acceptsGzip := clientAcceptsGzip(req)
if cacheutil.UseCache {
var content []byte
if acceptsGzip {
w.Header().Add(ContentEncodingHeaderKey, "gzip")
content = *cache.CompressedContent
} else {
content = *cache.Content
}
w.Header().Add(ContentTypeHeaderKey, cache.Mimetype)
_, err := w.Write(content)
if err != nil {
panic(err)
}
} else {
contents, exists := cacheutil.GetDiskContent(pathlike)
if exists {
fmt.Printf("returning contents: len of %d ", len(*contents))
w.Header().Add(ContentTypeHeaderKey, cache.Mimetype)
_, err := w.Write(*contents)
if err != nil {
panic(err)
}
return
} else {
w.WriteHeader(404)
w.Write(nil)
fmt.Println("returning nothing")
return
}
}
}
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)
//i don't like this logic below. we need to streamline this a lot better. it's a twisty jungle right now
if !exists {
content, fileExists := cacheutil.GetDiskContent(path.Join(pathlike, stub))
if fileExists {
if cacheutil.UseCache {
cache.Put(stub, content)
cachedContent, _ = cache.Get(stub)
} else {
w.Header().Add(ContentTypeHeaderKey, cacheutil.GuessMimetype(stub))
w.Write(*content)
return
}
} 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
}