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 }