static.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. package handler
  2. import (
  3. "net/http"
  4. "os"
  5. "path"
  6. "strings"
  7. "git.i2edu.net/i2/go-zero/rest"
  8. )
  9. const INDEX = "index.html"
  10. type ServeFileSystem interface {
  11. http.FileSystem
  12. Exists(prefix string, path string) bool
  13. }
  14. type neuteredReaddirFile struct {
  15. http.File
  16. }
  17. type onlyFilesFS struct {
  18. fs http.FileSystem
  19. }
  20. // Open conforms to http.Filesystem.
  21. func (fs onlyFilesFS) Open(name string) (http.File, error) {
  22. f, err := fs.fs.Open(name)
  23. if err != nil {
  24. return nil, err
  25. }
  26. return neuteredReaddirFile{f}, nil
  27. }
  28. type localFileSystem struct {
  29. http.FileSystem
  30. root string
  31. indexes bool
  32. }
  33. func Dir(root string, listDirectory bool) http.FileSystem {
  34. fs := http.Dir(root)
  35. if listDirectory {
  36. return fs
  37. }
  38. return &onlyFilesFS{fs}
  39. }
  40. func LocalFile(root string, indexes bool) *localFileSystem {
  41. return &localFileSystem{
  42. FileSystem: Dir(root, indexes),
  43. root: root,
  44. indexes: indexes,
  45. }
  46. }
  47. func (l *localFileSystem) Exists(prefix string, filepath string) bool {
  48. if p := strings.TrimPrefix(filepath, prefix); len(p) < len(filepath) {
  49. name := path.Join(l.root, p)
  50. stats, err := os.Stat(name)
  51. if err != nil {
  52. return false
  53. }
  54. if stats.IsDir() {
  55. if !l.indexes {
  56. index := path.Join(name, INDEX)
  57. _, err := os.Stat(index)
  58. if err != nil {
  59. return false
  60. }
  61. }
  62. }
  63. return true
  64. }
  65. return false
  66. }
  67. // Static returns a middleware handler that serves static files in the given directory.
  68. func Static(urlPrefix string, fs ServeFileSystem) (r []rest.Route) {
  69. fileserver := http.FileServer(fs)
  70. if urlPrefix != "" {
  71. fileserver = http.StripPrefix(urlPrefix, fileserver)
  72. }
  73. h := func(w http.ResponseWriter, r *http.Request) {
  74. if fs.Exists(urlPrefix, r.URL.Path) {
  75. fileserver.ServeHTTP(w, r)
  76. }
  77. }
  78. dirlevel := []string{":1", ":2", ":3", ":4", ":5", ":6", ":7", ":8"}
  79. for i := 1; i < len(dirlevel); i++ {
  80. path := urlPrefix + strings.Join(dirlevel[:i], "/")
  81. r = append(r, rest.Route{
  82. Method: http.MethodGet,
  83. Path: path,
  84. Handler: h,
  85. })
  86. }
  87. return
  88. }