package handler import ( "net/http" "os" "path" "strings" "git.i2edu.net/i2/go-zero/rest" "git.i2edu.net/i2/i2-bill-api/internal/svc" ) const INDEX = "index.html" type ServeFileSystem interface { http.FileSystem Exists(prefix string, path string) bool } type neuteredReaddirFile struct { http.File } type onlyFilesFS struct { fs http.FileSystem } // Open conforms to http.Filesystem. func (fs onlyFilesFS) Open(name string) (http.File, error) { f, err := fs.fs.Open(name) if err != nil { return nil, err } return neuteredReaddirFile{f}, nil } type localFileSystem struct { http.FileSystem root string indexes bool } func Dir(root string, listDirectory bool) http.FileSystem { fs := http.Dir(root) if listDirectory { return fs } return &onlyFilesFS{fs} } func LocalFile(root string, indexes bool) *localFileSystem { return &localFileSystem{ FileSystem: Dir(root, indexes), root: root, indexes: indexes, } } func (l *localFileSystem) Exists(prefix string, filepath string) bool { if p := strings.TrimPrefix(filepath, prefix); len(p) < len(filepath) { name := path.Join(l.root, p) stats, err := os.Stat(name) if err != nil { return false } if stats.IsDir() { if !l.indexes { index := path.Join(name, INDEX) _, err := os.Stat(index) if err != nil { return false } } } return true } return false } // Static returns a middleware handler that serves static files in the given directory. func Static(urlPrefix string, fs ServeFileSystem) (r []rest.Route) { fileserver := http.FileServer(fs) if urlPrefix != "" { fileserver = http.StripPrefix(urlPrefix, fileserver) } h := func(w http.ResponseWriter, r *http.Request) { if fs.Exists(urlPrefix, r.URL.Path) { fileserver.ServeHTTP(w, r) } } dirlevel := []string{":1", ":2", ":3", ":4", ":5", ":6", ":7", ":8"} for i := 1; i < len(dirlevel); i++ { path := urlPrefix + strings.Join(dirlevel[:i], "/") r = append(r, rest.Route{ Method: http.MethodGet, Path: path, Handler: h, }) } return } // CorsCheck returns a middleware handler that serves static files in the given directory. func CorsCheck() (r []rest.Route) { dirlevel := []string{":1", ":2", ":3", ":4", ":5", ":6", ":7", ":8"} for i := 1; i < len(dirlevel); i++ { path := "/" + strings.Join(dirlevel[:i], "/") r = append(r, rest.Route{ Method: http.MethodOptions, Path: path, Handler: func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Max-Age", "86400") w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, UPDATE, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "token, Origin, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") w.Header().Set("Access-Control-Expose-Headers", "Content-Length, Content-Disposition") w.Header().Set("Access-Control-Allow-Credentials", "true") w.WriteHeader(http.StatusNoContent) }, }) } return r } // Cors returns a middleware handler that serves static files in the given directory. func Cors(ctx *svc.ServiceContext) func(next http.HandlerFunc) http.HandlerFunc { return func(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Max-Age", "86400") w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, UPDATE, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "token, Origin, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") w.Header().Set("Access-Control-Expose-Headers", "Content-Length, Content-Disposition") w.Header().Set("Access-Control-Allow-Credentials", "true") next.ServeHTTP(w, r) } } }