@@ -42,6 +42,10 @@ type (
4242 // the filesystem path is not doubled
4343 // Optional. Default value false.
4444 IgnoreBase bool `yaml:"ignoreBase"`
45+
46+ // Filesystem provides access to the static content.
47+ // Optional. Defaults to http.Dir(config.Root)
48+ Filesystem http.FileSystem `yaml:"-"`
4549 }
4650)
4751
@@ -146,6 +150,10 @@ func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc {
146150 if config .Index == "" {
147151 config .Index = DefaultStaticConfig .Index
148152 }
153+ if config .Filesystem == nil {
154+ config .Filesystem = http .Dir (config .Root )
155+ config .Root = "."
156+ }
149157
150158 // Index template
151159 t , err := template .New ("index" ).Parse (html )
@@ -178,49 +186,73 @@ func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc {
178186 }
179187 }
180188
181- fi , err := os . Stat ( name )
189+ file , err := openFile ( config . Filesystem , name )
182190 if err != nil {
183- if os .IsNotExist (err ) {
184- if err = next (c ); err != nil {
185- if he , ok := err .(* echo.HTTPError ); ok {
186- if config .HTML5 && he .Code == http .StatusNotFound {
187- return c .File (filepath .Join (config .Root , config .Index ))
188- }
189- }
190- return
191- }
191+ if ! os .IsNotExist (err ) {
192+ return err
193+ }
194+
195+ if err = next (c ); err == nil {
196+ return err
197+ }
198+
199+ he , ok := err .(* echo.HTTPError )
200+ if ! (ok && config .HTML5 && he .Code == http .StatusNotFound ) {
201+ return err
202+ }
203+
204+ file , err = openFile (config .Filesystem , filepath .Join (config .Root , config .Index ))
205+ if err != nil {
206+ return err
192207 }
193- return
194208 }
195209
196- if fi .IsDir () {
197- index := filepath .Join (name , config .Index )
198- fi , err = os .Stat (index )
210+ defer file .Close ()
211+
212+ info , err := file .Stat ()
213+ if err != nil {
214+ return err
215+ }
199216
217+ if info .IsDir () {
218+ index , err := openFile (config .Filesystem , filepath .Join (name , config .Index ))
200219 if err != nil {
201220 if config .Browse {
202- return listDir (t , name , c .Response ())
221+ return listDir (t , name , file , c .Response ())
203222 }
223+
204224 if os .IsNotExist (err ) {
205225 return next (c )
206226 }
207- return
208227 }
209228
210- return c .File (index )
229+ defer index .Close ()
230+
231+ info , err = index .Stat ()
232+ if err != nil {
233+ return err
234+ }
235+
236+ return serveFile (c , index , info )
211237 }
212238
213- return c . File ( name )
239+ return serveFile ( c , file , info )
214240 }
215241 }
216242}
217243
218- func listDir (t * template.Template , name string , res * echo.Response ) (err error ) {
219- file , err := os .Open (name )
220- if err != nil {
221- return
222- }
223- files , err := file .Readdir (- 1 )
244+ func openFile (fs http.FileSystem , name string ) (http.File , error ) {
245+ pathWithSlashes := filepath .ToSlash (name )
246+ return fs .Open (pathWithSlashes )
247+ }
248+
249+ func serveFile (c echo.Context , file http.File , info os.FileInfo ) error {
250+ http .ServeContent (c .Response (), c .Request (), info .Name (), info .ModTime (), file )
251+ return nil
252+ }
253+
254+ func listDir (t * template.Template , name string , dir http.File , res * echo.Response ) (err error ) {
255+ files , err := dir .Readdir (- 1 )
224256 if err != nil {
225257 return
226258 }
0 commit comments