summaryrefslogtreecommitdiff
path: root/plugins/http/static/static.go
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/http/static/static.go')
-rw-r--r--plugins/http/static/static.go88
1 files changed, 88 insertions, 0 deletions
diff --git a/plugins/http/static/static.go b/plugins/http/static/static.go
new file mode 100644
index 00000000..d0278466
--- /dev/null
+++ b/plugins/http/static/static.go
@@ -0,0 +1,88 @@
+package static
+
+import (
+ "io/fs"
+ "net/http"
+ "path/filepath"
+ "strings"
+
+ httpConfig "github.com/spiral/roadrunner/v2/plugins/http/config"
+)
+
+type ExtensionFilter struct {
+ allowed map[string]struct{}
+ forbidden map[string]struct{}
+}
+
+func NewExtensionFilter(allow, forbid []string) *ExtensionFilter {
+ ef := &ExtensionFilter{
+ allowed: make(map[string]struct{}, len(allow)),
+ forbidden: make(map[string]struct{}, len(forbid)),
+ }
+
+ for i := 0; i < len(forbid); i++ {
+ // skip empty lines
+ if forbid[i] == "" {
+ continue
+ }
+ ef.forbidden[forbid[i]] = struct{}{}
+ }
+
+ for i := 0; i < len(allow); i++ {
+ // skip empty lines
+ if allow[i] == "" {
+ continue
+ }
+ ef.allowed[allow[i]] = struct{}{}
+ }
+
+ // check if any forbidden items presented in the allowed
+ // if presented, delete such items from allowed
+ for k := range ef.allowed {
+ if _, ok := ef.forbidden[k]; ok {
+ delete(ef.allowed, k)
+ }
+ }
+
+ return ef
+}
+
+type FileSystem struct {
+ ef *ExtensionFilter
+ // embedded
+ http.FileSystem
+}
+
+// Open wrapper around http.FileSystem Open method, name here is the name of the
+func (f FileSystem) Open(name string) (http.File, error) {
+ file, err := f.FileSystem.Open(name)
+ if err != nil {
+ return nil, err
+ }
+
+ fstat, err := file.Stat()
+ if err != nil {
+ return nil, fs.ErrNotExist
+ }
+
+ if fstat.IsDir() {
+ return nil, fs.ErrPermission
+ }
+
+ ext := strings.ToLower(filepath.Ext(fstat.Name()))
+ if _, ok := f.ef.forbidden[ext]; ok {
+ return nil, fs.ErrPermission
+ }
+
+ // if file extension is allowed, append it to the FileInfo slice
+ if _, ok := f.ef.allowed[ext]; ok {
+ return file, nil
+ }
+
+ return nil, fs.ErrNotExist
+}
+
+// FS is a constructor for the http.FileSystem
+func FS(config *httpConfig.Static) http.FileSystem {
+ return FileSystem{NewExtensionFilter(config.Allow, config.Forbid), http.Dir(config.Dir)}
+}