119 lines
3.2 KiB
Go
119 lines
3.2 KiB
Go
package vinegar
|
|
|
|
import (
|
|
"net/http"
|
|
"path"
|
|
"strings"
|
|
)
|
|
|
|
type (
|
|
FileRoute struct {
|
|
*ServletRoute
|
|
fileRoot string
|
|
}
|
|
)
|
|
|
|
func NewImageRoute(urlPattern string, pathlike string, servlet *Servlet) *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 *Servlet) *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 *Servlet) *FileRoute {
|
|
fun := createSingleFileServletFunction(pathlike)
|
|
route := FileRoute{
|
|
ServletRoute: NewServletRoute("^"+urlPattern+"$", fun),
|
|
fileRoot: pathlike,
|
|
}
|
|
return &route
|
|
}
|
|
|
|
func createSingleFileServletFunction(pathlike string) ServletHandleFunction {
|
|
cache := NewSingleFileCache(pathlike)
|
|
var fun ServletHandleFunction = func(w http.ResponseWriter, req *http.Request) {
|
|
w.Header().Add(ContentTypeHeaderKey, cache.Mimetype)
|
|
if clientAcceptsGzip(req) {
|
|
w.Header().Add(ContentEncodingHeaderKey, "gzip")
|
|
w.Write(*cache.CompressedContent)
|
|
}
|
|
}
|
|
|
|
return fun
|
|
}
|
|
|
|
func createCompressibleFileServletFunction(basePattern string, pathlike string, cache *Lru) ServletHandleFunction {
|
|
var fun ServletHandleFunction = func(w http.ResponseWriter, req *http.Request) {
|
|
stub := strings.Replace(req.URL.Path, basePattern, "", 1)
|
|
cachedContent, exists := cache.Get(stub)
|
|
if !exists {
|
|
content, fileExists := 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 *Lru) ServletHandleFunction {
|
|
var fun ServletHandleFunction = func(w http.ResponseWriter, req *http.Request) {
|
|
stub := strings.Replace(req.URL.Path, basePattern, "", 1)
|
|
|
|
entry, exists := cache.Get(stub)
|
|
if !exists {
|
|
fileContent, fExists := 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
|
|
}
|