mirror of
https://github.com/kataras/iris.git
synced 2025-03-14 05:36:27 +01:00
full commit from development branch. Examples, book, middleware, plugins are updated to the latest iris version. Read HISTORY.md for more. The 'old' v5 branch which relied on fasthttp exists for those who want to use it navigate there: https://github.com/kataras/iris/tree/5.0.0
150 lines
3.9 KiB
Go
150 lines
3.9 KiB
Go
package iris
|
|
|
|
import (
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
// StaticHandlerBuilder is the web file system's Handler builder
|
|
// use that or the iris.StaticHandler/StaticWeb methods
|
|
type StaticHandlerBuilder interface {
|
|
Path(requestRoutePath string) StaticHandlerBuilder
|
|
Gzip(enable bool) StaticHandlerBuilder
|
|
Listing(listDirectoriesOnOff bool) StaticHandlerBuilder
|
|
StripPath(yesNo bool) StaticHandlerBuilder
|
|
Build() HandlerFunc
|
|
}
|
|
|
|
type webfs struct {
|
|
// user options, only directory is required.
|
|
directory http.Dir
|
|
requestPath string
|
|
stripPath bool
|
|
gzip bool
|
|
listDirectories bool
|
|
// these are init on the Build() call
|
|
filesystem http.FileSystem
|
|
once sync.Once
|
|
handler HandlerFunc
|
|
}
|
|
|
|
func toWebPath(systemPath string) string {
|
|
// winos slash to slash
|
|
webpath := strings.Replace(systemPath, "\\", slash, -1)
|
|
// double slashes to single
|
|
webpath = strings.Replace(webpath, slash+slash, slash, -1)
|
|
// remove all dots
|
|
webpath = strings.Replace(webpath, ".", "", -1)
|
|
return webpath
|
|
}
|
|
|
|
// NewStaticHandlerBuilder returns a new Handler which serves static files
|
|
// supports gzip, no listing and much more
|
|
// Note that, this static builder returns a Handler
|
|
// it doesn't cares about the rest of your iris configuration.
|
|
//
|
|
// Use the iris.StaticHandler/StaticWeb in order to serve static files on more automatic way
|
|
// this builder is used by people who have more complicated application
|
|
// structure and want a fluent api to work on.
|
|
func NewStaticHandlerBuilder(dir string) StaticHandlerBuilder {
|
|
return &webfs{
|
|
directory: http.Dir(dir),
|
|
// default route path is the same as the directory
|
|
requestPath: toWebPath(dir),
|
|
// enable strip path by-default
|
|
stripPath: true,
|
|
// gzip is disabled by default
|
|
gzip: false,
|
|
// list directories disabled by default
|
|
listDirectories: false,
|
|
}
|
|
}
|
|
|
|
// Path sets the request path.
|
|
// Defaults to same as system path
|
|
func (w *webfs) Path(requestRoutePath string) StaticHandlerBuilder {
|
|
w.requestPath = toWebPath(requestRoutePath)
|
|
return w
|
|
}
|
|
|
|
// Gzip if enable is true then gzip compression is enabled for this static directory
|
|
// Defaults to false
|
|
func (w *webfs) Gzip(enable bool) StaticHandlerBuilder {
|
|
w.gzip = enable
|
|
return w
|
|
}
|
|
|
|
// Listing turn on/off the 'show files and directories'.
|
|
// Defaults to false
|
|
func (w *webfs) Listing(listDirectoriesOnOff bool) StaticHandlerBuilder {
|
|
w.listDirectories = listDirectoriesOnOff
|
|
return w
|
|
}
|
|
|
|
func (w *webfs) StripPath(yesNo bool) StaticHandlerBuilder {
|
|
w.stripPath = yesNo
|
|
return w
|
|
}
|
|
|
|
type (
|
|
noListFile struct {
|
|
http.File
|
|
}
|
|
)
|
|
|
|
// Overrides the Readdir of the http.File in order to disable showing a list of the dirs/files
|
|
func (n noListFile) Readdir(count int) ([]os.FileInfo, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
// Implements the http.Filesystem
|
|
// Do not call it.
|
|
func (w *webfs) Open(name string) (http.File, error) {
|
|
info, err := w.filesystem.Open(name)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !w.listDirectories {
|
|
return noListFile{info}, nil
|
|
}
|
|
|
|
return info, nil
|
|
}
|
|
|
|
// Build the handler (once) and returns it
|
|
func (w *webfs) Build() HandlerFunc {
|
|
// we have to ensure that Build is called ONLY one time,
|
|
// one instance per one static directory.
|
|
w.once.Do(func() {
|
|
w.filesystem = http.Dir(w.directory)
|
|
|
|
// set the filesystem to itself in order to be recognised of listing property (can be change at runtime too)
|
|
fileserver := http.FileServer(w)
|
|
fsHandler := fileserver
|
|
if w.stripPath {
|
|
prefix := w.requestPath
|
|
fsHandler = http.StripPrefix(prefix, fileserver)
|
|
}
|
|
|
|
w.handler = func(ctx *Context) {
|
|
writer := ctx.ResponseWriter.ResponseWriter
|
|
|
|
if w.gzip && ctx.clientAllowsGzip() {
|
|
ctx.ResponseWriter.Header().Add(varyHeader, acceptEncodingHeader)
|
|
ctx.SetHeader(contentEncodingHeader, "gzip")
|
|
gzipResWriter := acquireGzipResponseWriter(ctx.ResponseWriter.ResponseWriter)
|
|
writer = gzipResWriter
|
|
defer releaseGzipResponseWriter(gzipResWriter)
|
|
}
|
|
|
|
fsHandler.ServeHTTP(writer, ctx.Request)
|
|
}
|
|
})
|
|
|
|
return w.handler
|
|
}
|