155 lines
4.1 KiB
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
|
|
}
|