MCPcopy
hub / github.com/pocketbase/pocketbase / Static

Function Static

apis/base.go:109–171  ·  view source on GitHub ↗

Static is a handler function to serve static directory content from fsys. If a file resource is missing and indexFallback is true, the request will be forwarded to the base index.html (useful for SPA with pretty urls). NB! Expects the route to have a "{path...}" wildcard parameter. Special redire

(fsys fs.FS, indexFallback bool)

Source from the content-addressed store, hash-verified

107// fsys := os.DirFS("./pb_public")
108// router.GET("/files/{path...}", apis.Static(fsys, false))
109func Static(fsys fs.FS, indexFallback bool) func(*core.RequestEvent) error {
110 if fsys == nil {
111 panic("Static: the provided fs.FS argument is nil")
112 }
113
114 return func(e *core.RequestEvent) error {
115 // disable the activity logger to avoid flooding with messages
116 //
117 // note: errors are still logged
118 if e.Get(requestEventKeySkipSuccessActivityLog) == nil {
119 e.Set(requestEventKeySkipSuccessActivityLog, true)
120 }
121
122 filename := e.Request.PathValue(StaticWildcardParam)
123 filename = filepath.ToSlash(filepath.Clean(strings.TrimPrefix(filename, "/")))
124
125 // eagerly check for directory traversal
126 //
127 // note: this is just out of an abundance of caution because the fs.FS implementation could be non-std,
128 // but usually shouldn't be necessary since os.DirFS.Open is expected to fail if the filename starts with dots
129 if len(filename) > 2 && filename[0] == '.' && filename[1] == '.' && (filename[2] == '/' || filename[2] == '\\') {
130 if indexFallback && filename != router.IndexPage {
131 return e.FileFS(fsys, router.IndexPage)
132 }
133 return router.ErrFileNotFound
134 }
135
136 fi, err := fs.Stat(fsys, filename)
137 if err != nil {
138 if indexFallback && filename != router.IndexPage {
139 return e.FileFS(fsys, router.IndexPage)
140 }
141 return router.ErrFileNotFound
142 }
143
144 if fi.IsDir() {
145 // redirect to a canonical dir url, aka. with trailing slash
146 if !strings.HasSuffix(e.Request.URL.Path, "/") {
147 return e.Redirect(http.StatusMovedPermanently, safeRedirectPath(e.Request.URL.Path+"/"))
148 }
149 } else {
150 urlPath := e.Request.URL.Path
151 if strings.HasSuffix(urlPath, "/") {
152 // redirect to a non-trailing slash file route
153 urlPath = strings.TrimRight(urlPath, "/")
154 if len(urlPath) > 0 {
155 return e.Redirect(http.StatusMovedPermanently, safeRedirectPath(urlPath))
156 }
157 } else if stripped, ok := strings.CutSuffix(urlPath, router.IndexPage); ok {
158 // redirect without the index.html
159 return e.Redirect(http.StatusMovedPermanently, safeRedirectPath(stripped))
160 }
161 }
162
163 fileErr := e.FileFS(fsys, filename)
164
165 if fileErr != nil && indexFallback && filename != router.IndexPage && errors.Is(fileErr, router.ErrFileNotFound) {
166 return e.FileFS(fsys, router.IndexPage)

Callers 5

TestStaticFunction · 0.92
BindApisFunction · 0.92
mainFunction · 0.92
ServeFunction · 0.85
bindUIExtensionsFunction · 0.85

Calls 6

safeRedirectPathFunction · 0.85
FileFSMethod · 0.80
RedirectMethod · 0.80
IsMethod · 0.80
GetMethod · 0.65
SetMethod · 0.65

Tested by 1

TestStaticFunction · 0.74

Used in the wild real call sites across dependent graphs

searching dependent graphs…