// ServeFile responds to w with the contents of path within fs. func ServeFile(w http.ResponseWriter, r *http.Request, fs http.FileSystem, path string) { // Open file handle. f, err := fs.Open(path) if err != nil { http.Error(w, "404 Not Found", 404) return } defer f.Close() // Make sure path exists. fileinfo, err1 := f.Stat() if err1 != nil { http.Error(w, "404 Not Found", 404) return } // Reject directory requests. if fileinfo.IsDir() { http.Error(w, "403 Forbidden", 403) return } http.ServeContent(w, r, fileinfo.Name(), fileinfo.ModTime(), f) }
func serveFile(w http.ResponseWriter, r *http.Request, fs http.FileSystem, name string) { f, err := fs.Open(name) if err != nil { http.NotFound(w, r) return } defer util.Close(f) d, err1 := f.Stat() if err1 != nil { http.NotFound(w, r) return } url := r.URL.Path if d.IsDir() { if url[len(url)-1] != '/' { w.Header().Set("Location", path.Base(url)+"/") w.WriteHeader(http.StatusMovedPermanently) return } glog.Infof("Dir List: %s", name) dirList(w, f) return } http.ServeContent(w, r, d.Name(), d.ModTime(), f) }
// StaticMiddlewareFromDir returns a middleware that serves static files from the specified http.FileSystem. // This middleware is great for development because each file is read from disk each time and no // special caching or cache headers are sent. // // If a path is requested which maps to a folder with an index.html folder on your filesystem, // then that index.html file will be served. func StaticMiddlewareFromDir(dir http.FileSystem, options ...StaticOption) func(ResponseWriter, *Request, NextMiddlewareFunc) { var option StaticOption if len(options) > 0 { option = options[0] } return func(w ResponseWriter, req *Request, next NextMiddlewareFunc) { if req.Method != "GET" && req.Method != "HEAD" { next(w, req) return } file := req.URL.Path if option.Prefix != "" { if !strings.HasPrefix(file, option.Prefix) { next(w, req) return } file = file[len(option.Prefix):] } f, err := dir.Open(file) if err != nil { next(w, req) return } defer f.Close() fi, err := f.Stat() if err != nil { next(w, req) return } // If the file is a directory, try to serve an index file. // If no index is available, DO NOT serve the directory to avoid // Content-Length issues. Simply skip to the next middleware, and return // a 404 if no path with the same name is handled. if fi.IsDir() { if option.IndexFile != "" { file = filepath.Join(file, option.IndexFile) f, err = dir.Open(file) if err != nil { next(w, req) return } defer f.Close() fi, err = f.Stat() if err != nil || fi.IsDir() { next(w, req) return } } else { next(w, req) return } } http.ServeContent(w, req.Request, file, fi.ModTime(), f) } }
// name is '/'-separated, not filepath.Separator. func (f *fileHandler) serveFile(w http.ResponseWriter, r *http.Request, fs http.FileSystem, name string, redirect bool) { looper += 1 if looper > 10 { panic("TILT") } const indexPage = "/index.html" debug("opening %s from fs", name) file, err := fs.Open(name) if err != nil { if os.IsNotExist(err) { if !testIfFile.MatchString(name) { f.serveFile(w, r, fs, ".", redirect) return } } msg, code := toHTTPError(err) http.Error(w, msg, code) return } defer file.Close() debug("getting stat") d, err1 := file.Stat() if err1 != nil { if os.IsNotExist(err1) { if !testIfFile.MatchString(name) { f.serveFile(w, r, fs, f.rootDir, redirect) return } } msg, code := toHTTPError(err1) http.Error(w, msg, code) return } // use contents of index.html for directory, if present if d.IsDir() { index := strings.TrimSuffix(name, "/") + indexPage ff, err := fs.Open(index) if err == nil { defer ff.Close() dd, err := ff.Stat() if err == nil { name = index d = dd file = ff } } } // Still a directory? (we didn't find an index.html file) if d.IsDir() { f.serveFile(w, r, fs, ".", redirect) } // serveContent will check modification time sizeFunc := func() (int64, error) { return d.Size(), nil } f.serveContent(w, r, d.Name(), d.ModTime(), sizeFunc, file) }
func serveFile(w http.ResponseWriter, r *http.Request, fs http.FileSystem, name string) { f, err := fs.Open(name) if err != nil { http.NotFound(w, r) return } defer f.Close() d, err1 := f.Stat() if err1 != nil { http.NotFound(w, r) return } if d.IsDir() { // Directory, list the contents dirList(w, f) } else { // Actually playback a recording offset, err := time.ParseDuration(r.FormValue("offset")) if err != nil { log.Error("parse offset: %v: %v", err, r.FormValue("offset")) offset = 0 } streamRecording(w, f, offset) } }
func (ms middlewareStatic) serveFile(w http.ResponseWriter, r *http.Request, fs http.FileSystem, name string) (err error) { f, err := fs.Open(name) if err != nil { return } defer f.Close() d, err := f.Stat() if err != nil { return ErrFileNotFound } if d.IsDir() { f.Close() f, err = fs.Open(name + "/index.html") if err != nil { return } d, err = f.Stat() if err != nil { return ErrFileNotFound } if d.IsDir() { return ErrFileNotFound } } http.ServeContent(w, r, d.Name(), d.ModTime(), f) return nil }
func ExampleReadTwoOpenedUncompressedFiles() { var fs http.FileSystem = assets f0, err := fs.Open("/not-worth-compressing-file.txt") if err != nil { panic(err) } defer f0.Close() _ = f0.(notWorthGzipCompressing) f1, err := fs.Open("/not-worth-compressing-file.txt") if err != nil { panic(err) } defer f1.Close() _ = f1.(notWorthGzipCompressing) _, err = io.CopyN(os.Stdout, f0, 9) if err != nil { panic(err) } _, err = io.CopyN(os.Stdout, f1, 9) if err != nil { panic(err) } // Output: // Its normaIts norma }
// Looks for a file.gz file and serves that if present // `original` is a file server func MaybeGzip(root http.FileSystem, original http.Handler) http.Handler { return http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) { if strings.Contains(request.Header.Get("Accept-Encoding"), "gzip") { requestPath := request.URL.Path if !strings.HasPrefix(requestPath, "/") { requestPath = "/" + requestPath } requestPath = path.Clean(requestPath) gzPath := requestPath + ".gz" if requestPath == "/" { gzPath = "/index.html.gz" } // log.Print(gzPath) file, err := root.Open(gzPath) if err == nil { file.Close() contentType := mime.TypeByExtension(filepath.Ext(requestPath)) if contentType == "" { contentType = "text/html; charset=utf-8" } response.Header().Set("Content-Type", contentType) response.Header().Set("Content-Encoding", "gzip") request.URL.Path = gzPath } } original.ServeHTTP(response, request) }) }
// ContextInclude opens filename using fs and executes a template with the context ctx. // This does the same thing that Context.Include() does, but with the ability to provide // your own context so that the included files can have access to additional fields your // type may provide. You can embed Context in your type, then override its Include method // to call this function with ctx being the instance of your type, and fs being Context.Root. func ContextInclude(filename string, ctx interface{}, fs http.FileSystem) (string, error) { file, err := fs.Open(filename) if err != nil { return "", err } defer file.Close() body, err := ioutil.ReadAll(file) if err != nil { return "", err } tpl, err := template.New(filename).Parse(string(body)) if err != nil { return "", err } var buf bytes.Buffer err = tpl.Execute(&buf, ctx) if err != nil { return "", err } return buf.String(), nil }
func ExampleReadTwoOpenedCompressedFiles() { var fs http.FileSystem = assets f0, err := fs.Open("/sample-file.txt") if err != nil { panic(err) } defer f0.Close() _ = f0.(gzipByter) f1, err := fs.Open("/sample-file.txt") if err != nil { panic(err) } defer f1.Close() _ = f1.(gzipByter) _, err = io.CopyN(os.Stdout, f0, 9) if err != nil { panic(err) } _, err = io.CopyN(os.Stdout, f1, 9) if err != nil { panic(err) } // Output: // This fileThis file }
// @ modified by henrylee2cn 2016.1.22 func (e *Echo) serveFile(fs http.FileSystem, file string, c *Context) (err error) { f, err := fs.Open(file) if err != nil { return NewHTTPError(http.StatusNotFound) } defer f.Close() fi, _ := f.Stat() if fi.IsDir() { /* NOTE: Not checking the Last-Modified header as it caches the response `304` when changing differnt directories for the same path. */ d := f // Index file file = filepath.Join(file, indexPage) f, err = fs.Open(file) if err != nil { if e.autoIndex { // Auto index return listDir(d, c) } return NewHTTPError(http.StatusForbidden) } fi, _ = f.Stat() // Index file stat } http.ServeContent(c.response, c.request, fi.Name(), fi.ModTime(), f) return }
func ExampleCompressed() { // Compressed file system. var fs http.FileSystem = assets walkFn := func(path string, fi os.FileInfo, err error) error { if err != nil { log.Printf("can't stat file %s: %v\n", path, err) return nil } fmt.Println(path) if fi.IsDir() { return nil } f, err := fs.Open(path) if err != nil { fmt.Printf("fs.Open(%q): %v\n", path, err) return nil } defer f.Close() b, err := ioutil.ReadAll(f) fmt.Printf("%q %v\n", string(b), err) if gzipFile, ok := f.(gzipByter); ok { b := gzipFile.GzipBytes() fmt.Printf("%q\n", string(b)) } else { fmt.Println("<not compressed>") } return nil } err := vfsutil.Walk(fs, "/", walkFn) if err != nil { panic(err) } // Output: // / // /folderA // /folderA/file1.txt // "Stuff in /folderA/file1.txt." <nil> // <not compressed> // /folderA/file2.txt // "Stuff in /folderA/file2.txt." <nil> // <not compressed> // /folderB // /folderB/folderC // /folderB/folderC/file3.txt // "Stuff in /folderB/folderC/file3.txt." <nil> // <not compressed> // /not-worth-compressing-file.txt // "Its normal contents are here." <nil> // <not compressed> // /sample-file.txt // "This file compresses well. Blaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah!" <nil> // "\x1f\x8b\b\x00\x00\tn\x88\x00\xff\n\xc9\xc8,VH\xcb\xccIUH\xce\xcf-(J-.N-V(O\xcd\xc9\xd1Sp\xcaI\x1c\xd4 C\x11\x10\x00\x00\xff\xff\xe7G\x81:\xbd\x00\x00\x00" }
// Stat returns the FileInfo structure describing file. func Stat(fs http.FileSystem, name string) (os.FileInfo, error) { f, err := fs.Open(name) if err != nil { return nil, err } defer f.Close() return f.Stat() }
// ReadDir reads the contents of the directory associated with file and // returns a slice of FileInfo values in directory order. func ReadDir(fs http.FileSystem, name string) ([]os.FileInfo, error) { f, err := fs.Open(name) if err != nil { return nil, err } defer f.Close() return f.Readdir(0) }
// ReadFile reads the file named by path from fs and returns the contents. func ReadFile(fs http.FileSystem, path string) ([]byte, error) { rc, err := fs.Open(path) if err != nil { return nil, err } defer rc.Close() return ioutil.ReadAll(rc) }
func readFile(fs http.FileSystem, path string) ([]byte, error) { file, err := fs.Open(path) if err != nil { return nil, err } defer file.Close() return ioutil.ReadAll(file) }
func serveFile(reply *Reply, r *http.Request, fs http.FileSystem, name string, redirect bool) { const indexPage = "/index.html" if strings.HasSuffix(r.URL.Path, indexPage) { localRedirect(reply, r, "./") return } f, err := fs.Open(name) if err != nil { reply.SetCode(http.StatusNotFound) return } d, err1 := f.Stat() if err1 != nil { reply.SetCode(http.StatusNotFound) return } if redirect { url := r.URL.Path if d.IsDir() { if url[len(url)-1] != '/' { localRedirect(reply, r, path.Base(url)+"/") return } } else { if url[len(url)-1] == '/' { localRedirect(reply, r, "../"+path.Base(url)) return } } } // use contents of index.html for directory, if present if d.IsDir() { index := strings.TrimSuffix(name, "/") + indexPage ff, err := fs.Open(index) if err == nil { dd, err := ff.Stat() if err == nil { name = index d = dd f = ff } } } // Still a directory? (we didn't find an index.html file) if d.IsDir() { if checkLastModified(reply, r, d.ModTime()) { return } dirList(reply, f) return } // serveContent will check modification time sizeFunc := func() (int64, error) { return d.Size(), nil } serveContent(reply, r, d.Name(), d.ModTime(), sizeFunc, f) }
func ExampleNotExist() { var fs http.FileSystem = assets _, err := fs.Open("/does-not-exist") fmt.Println("os.IsNotExist:", os.IsNotExist(err)) fmt.Println(err) // Output: // os.IsNotExist: true // open /does-not-exist: file does not exist }
func StaticFilesHandler(h http.Handler, prefix string, fs http.FileSystem) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { filename := strings.TrimPrefix(r.URL.Path, prefix) _, err := fs.Open(filename) if err != nil { h.ServeHTTP(w, r) return } fileserver := http.StripPrefix(prefix, http.FileServer(fs)) fileserver.ServeHTTP(w, r) }) }
// openStat performs Open and Stat and returns results, or first error encountered. // The caller is responsible for closing the returned file when done. func openStat(fs http.FileSystem, name string) (http.File, os.FileInfo, error) { f, err := fs.Open(name) if err != nil { return nil, nil, err } fi, err := f.Stat() if err != nil { f.Close() return nil, nil, err } return f, fi, nil }
func open(fs http.FileSystem, name string) (http.File, os.FileInfo) { f, err := fs.Open(name) if err != nil { return nil, nil } s, err := f.Stat() if err != nil { f.Close() return nil, nil } return f, s }
// StaticMiddlewareFromDir returns a middleware that serves static files from the specified http.FileSystem. // This middleware is great for development because each file is read from disk each time and no // special caching or cache headers are sent. // // If a path is requested which maps to a folder with an index.html folder on your filesystem, // then that index.html file will be served. func StaticMiddlewareFromDir(dir http.FileSystem, options ...StaticOption) func(ResponseWriter, *Request, NextMiddlewareFunc) { var option StaticOption if len(options) > 0 { option = options[0] } return func(w ResponseWriter, req *Request, next NextMiddlewareFunc) { if req.Method != "GET" && req.Method != "HEAD" { next(w, req) return } file := req.URL.Path if option.Prefix != "" { if !strings.HasPrefix(file, option.Prefix) { next(w, req) return } file = file[len(option.Prefix):] } f, err := dir.Open(file) if err != nil { next(w, req) return } defer f.Close() fi, err := f.Stat() if err != nil { next(w, req) return } // Try to serve index if option.IndexFile != "" && fi.IsDir() { file = filepath.Join(file, option.IndexFile) f, err = dir.Open(file) if err != nil { next(w, req) return } defer f.Close() fi, err = f.Stat() if err != nil || fi.IsDir() { next(w, req) return } } http.ServeContent(w, req.Request, file, fi.ModTime(), f) } }
func serveStaticFile(rw http.ResponseWriter, req *http.Request, root http.FileSystem, file string) { f, err := root.Open("/" + file) if err != nil { http.NotFound(rw, req) log.Printf("Failed to open file %q from uistatic.Files: %v", file, err) return } defer f.Close() var modTime time.Time if fi, err := f.Stat(); err == nil { modTime = fi.ModTime() } http.ServeContent(rw, req, file, modTime, f) }
func ExampleSeekDir1() { var fs http.FileSystem = assets f, err := fs.Open("/") if err != nil { panic(err) } defer f.Close() fis, err := f.Readdir(0) fmt.Println(fisStringer(fis), err) // Output: // [ folderA folderB not-worth-compressing-file.txt sample-file.txt ] <nil> }
// openFile attempts to open the file within the specified Filesystem. If // successful, the http.File is returned and must be closed by the caller. // Otherwise, the path was not a regular file that could be opened and an // error is returned. func openFile(fs http.FileSystem, path string) (http.File, error) { file, err := fs.Open(path) if err != nil { return nil, err } info, err := file.Stat() if err != nil { file.Close() return nil, err } if info.Mode().IsRegular() { return file, nil } file.Close() return nil, fmt.Errorf("%s is not a file on the given filesystem", path) }
// justFiles bypasses the http.FileServer if a directory is requested. func justFiles(dir http.FileSystem, next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { f, err := dir.Open(r.URL.Path) if err != nil { http.NotFound(w, r) return } info, err := f.Stat() if err == nil && info.IsDir() && strings.HasSuffix(r.URL.Path, "/") { http.NotFound(w, r) return } next.ServeHTTP(w, r) }) }
// IndexFile looks for a file in /root/fpath/indexFile for each string // in indexFiles. If an index file is found, it returns the root-relative // path to the file and true. If no index file is found, empty string // and false is returned. fpath must end in a forward slash '/' // otherwise no index files will be tried (directory paths must end // in a forward slash according to HTTP). // // All paths passed into and returned from this function use '/' as the // path separator, just like URLs. IndexFle handles path manipulation // internally for systems that use different path separators. func IndexFile(root http.FileSystem, fpath string, indexFiles []string) (string, bool) { if fpath[len(fpath)-1] != '/' || root == nil { return "", false } for _, indexFile := range indexFiles { // func (http.FileSystem).Open wants all paths separated by "/", // regardless of operating system convention, so use // path.Join instead of filepath.Join fp := path.Join(fpath, indexFile) f, err := root.Open(fp) if err == nil { f.Close() return fp, true } } return "", false }
func ExampleSeek() { var fs http.FileSystem = assets f, err := fs.Open("/sample-file.txt") if err != nil { panic(err) } defer f.Close() _, err = io.CopyN(os.Stdout, f, 5) if err != nil { panic(err) } _, err = f.Seek(22, os.SEEK_CUR) if err != nil { panic(err) } _, err = io.CopyN(os.Stdout, f, 10) if err != nil { panic(err) } fmt.Print("...") _, err = f.Seek(-4, os.SEEK_END) if err != nil { panic(err) } _, err = io.Copy(os.Stdout, f) if err != nil { panic(err) } _, err = f.Seek(3, os.SEEK_SET) if err != nil { panic(err) } _, err = f.Seek(1, os.SEEK_CUR) if err != nil { panic(err) } _, err = io.CopyN(os.Stdout, f, 22) if err != nil { panic(err) } // Output: // This Blaaaaaaaa...aah! file compresses well. }
func walkFileSystem(fs http.FileSystem, path string, t *tar.Writer) error { fh, e := fs.Open(path) if e != nil { return e } infos, e := fh.Readdir(0) if e != nil { return e } for i := range infos { name := infos[i].Name() if path != "/" { name = fmt.Sprintf("%s/%s", path, name) } header := &tar.Header{Name: name, ModTime: infos[i].ModTime().UTC()} switch { case infos[i].IsDir(): header.Typeflag = tar.TypeDir header.Mode = 0755 e = t.WriteHeader(header) if e = walkFileSystem(fs, name, t); e != nil { return e } default: file, e := fs.Open(name) if e != nil { return e } header.Mode = 0644 header.Size = infos[i].Size() e = t.WriteHeader(header) if e != nil { return e } _, e = io.Copy(t, file) if e != nil { return e } } } return nil }
// name is '/'-separated, not filepath.Separator. func serveFile(w http.ResponseWriter, r *http.Request, fs http.FileSystem, name string) { f, err := fs.Open(name) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } defer f.Close() d, err := f.Stat() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // redirect to canonical path: / at end of directory url // r.URL.Path always begins with / url := r.URL.Path if d.IsDir() { if url[len(url)-1] != '/' { localRedirect(w, r, path.Base(url)+"/") return } } else { if url[len(url)-1] == '/' { localRedirect(w, r, "../"+path.Base(url)) return } } // A directory? if d.IsDir() { // TODO: Consider using checkLastModified? /*if checkLastModified(w, r, d.ModTime()) { return }*/ dirList(w, f, name) return } if _, plain := r.URL.Query()["plain"]; plain { w.Header().Set("Content-Type", "text/plain") } http.ServeContent(w, r, d.Name(), d.ModTime(), f) }