middles.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package handler
  2. import (
  3. "net/http"
  4. "os"
  5. "path"
  6. "strings"
  7. "git.i2edu.net/i2/go-zero/rest"
  8. "git.i2edu.net/i2/i2-bill-api/internal/svc"
  9. )
  10. const INDEX = "index.html"
  11. type ServeFileSystem interface {
  12. http.FileSystem
  13. Exists(prefix string, path string) bool
  14. }
  15. type neuteredReaddirFile struct {
  16. http.File
  17. }
  18. type onlyFilesFS struct {
  19. fs http.FileSystem
  20. }
  21. // Open conforms to http.Filesystem.
  22. func (fs onlyFilesFS) Open(name string) (http.File, error) {
  23. f, err := fs.fs.Open(name)
  24. if err != nil {
  25. return nil, err
  26. }
  27. return neuteredReaddirFile{f}, nil
  28. }
  29. type localFileSystem struct {
  30. http.FileSystem
  31. root string
  32. indexes bool
  33. }
  34. func Dir(root string, listDirectory bool) http.FileSystem {
  35. fs := http.Dir(root)
  36. if listDirectory {
  37. return fs
  38. }
  39. return &onlyFilesFS{fs}
  40. }
  41. func LocalFile(root string, indexes bool) *localFileSystem {
  42. return &localFileSystem{
  43. FileSystem: Dir(root, indexes),
  44. root: root,
  45. indexes: indexes,
  46. }
  47. }
  48. func (l *localFileSystem) Exists(prefix string, filepath string) bool {
  49. if p := strings.TrimPrefix(filepath, prefix); len(p) < len(filepath) {
  50. name := path.Join(l.root, p)
  51. stats, err := os.Stat(name)
  52. if err != nil {
  53. return false
  54. }
  55. if stats.IsDir() {
  56. if !l.indexes {
  57. index := path.Join(name, INDEX)
  58. _, err := os.Stat(index)
  59. if err != nil {
  60. return false
  61. }
  62. }
  63. }
  64. return true
  65. }
  66. return false
  67. }
  68. // Static returns a middleware handler that serves static files in the given directory.
  69. func Static(urlPrefix string, fs ServeFileSystem) (r []rest.Route) {
  70. fileserver := http.FileServer(fs)
  71. if urlPrefix != "" {
  72. fileserver = http.StripPrefix(urlPrefix, fileserver)
  73. }
  74. h := func(w http.ResponseWriter, r *http.Request) {
  75. if fs.Exists(urlPrefix, r.URL.Path) {
  76. fileserver.ServeHTTP(w, r)
  77. }
  78. }
  79. dirlevel := []string{":1", ":2", ":3", ":4", ":5", ":6", ":7", ":8"}
  80. for i := 1; i < len(dirlevel); i++ {
  81. path := urlPrefix + strings.Join(dirlevel[:i], "/")
  82. r = append(r, rest.Route{
  83. Method: http.MethodGet,
  84. Path: path,
  85. Handler: h,
  86. })
  87. }
  88. return
  89. }
  90. // CorsCheck returns a middleware handler that serves static files in the given directory.
  91. func CorsCheck() (r []rest.Route) {
  92. dirlevel := []string{":1", ":2", ":3", ":4", ":5", ":6", ":7", ":8"}
  93. for i := 1; i < len(dirlevel); i++ {
  94. path := "/" + strings.Join(dirlevel[:i], "/")
  95. r = append(r, rest.Route{
  96. Method: http.MethodOptions,
  97. Path: path,
  98. Handler: func(w http.ResponseWriter, r *http.Request) {
  99. w.Header().Set("Access-Control-Allow-Origin", "*")
  100. w.Header().Set("Access-Control-Max-Age", "86400")
  101. w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, UPDATE, OPTIONS")
  102. w.Header().Set("Access-Control-Allow-Headers", "token, Origin, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
  103. w.Header().Set("Access-Control-Expose-Headers", "Content-Length, Content-Disposition")
  104. w.Header().Set("Access-Control-Allow-Credentials", "true")
  105. w.WriteHeader(http.StatusNoContent)
  106. },
  107. })
  108. }
  109. return r
  110. }
  111. // Cors returns a middleware handler that serves static files in the given directory.
  112. func Cors(ctx *svc.ServiceContext) func(next http.HandlerFunc) http.HandlerFunc {
  113. return func(next http.HandlerFunc) http.HandlerFunc {
  114. return func(w http.ResponseWriter, r *http.Request) {
  115. w.Header().Set("Access-Control-Allow-Origin", "*")
  116. w.Header().Set("Access-Control-Max-Age", "86400")
  117. w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, UPDATE, OPTIONS")
  118. w.Header().Set("Access-Control-Allow-Headers", "token, Origin, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
  119. w.Header().Set("Access-Control-Expose-Headers", "Content-Length, Content-Disposition")
  120. w.Header().Set("Access-Control-Allow-Credentials", "true")
  121. next.ServeHTTP(w, r)
  122. }
  123. }
  124. }