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 }