mirror of
https://github.com/kataras/iris.git
synced 2026-01-09 13:05:56 +00:00
Update to 7.2.0. Read https://github.com/kataras/iris/blob/master/HISTORY.md#th-15-june-2017--v720
Fix https://github.com/iris-contrib/community-board/issues/12 . Read more: https://github.com/kataras/iris/blob/master/HISTORY.md#th-15-june-2017--v720 Former-commit-id: 398cb69fdc7e5367b147693371287ffb7b912feb
This commit is contained in:
@@ -320,6 +320,7 @@ func (rb *APIBuilder) Any(registeredPath string, handlers ...context.Handler) er
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -353,21 +354,20 @@ func (rb *APIBuilder) registerResourceRoute(reqPath string, h context.Handler) (
|
||||
// Note:
|
||||
// The only difference from package-level `StaticHandler`
|
||||
// is that this `StaticHandler`` receives a request path which
|
||||
// is appended to the party's relative path and stripped here,
|
||||
// so `iris.StripPath` is useless and should not being used here.
|
||||
// is appended to the party's relative path and stripped here.
|
||||
//
|
||||
// Usage:
|
||||
// app := iris.New()
|
||||
// ...
|
||||
// mySubdomainFsServer := app.Party("mysubdomain.")
|
||||
// h := mySubdomainFsServer.StaticHandler("/static", "./static_files", false, false)
|
||||
// h := mySubdomainFsServer.StaticHandler("./static_files", false, false)
|
||||
// /* http://mysubdomain.mydomain.com/static/css/style.css */
|
||||
// mySubdomainFsServer.Get("/static", h)
|
||||
// ...
|
||||
//
|
||||
func (rb *APIBuilder) StaticHandler(reqPath string, systemPath string, showList bool, enableGzip bool, exceptRoutes ...*Route) context.Handler {
|
||||
return StripPrefix(rb.relativePath+reqPath,
|
||||
StaticHandler(systemPath, showList, enableGzip))
|
||||
func (rb *APIBuilder) StaticHandler(systemPath string, showList bool, enableGzip bool, exceptRoutes ...*Route) context.Handler {
|
||||
// Note: this doesn't need to be here but we'll keep it for consistently
|
||||
return StaticHandler(systemPath, showList, enableGzip)
|
||||
}
|
||||
|
||||
// StaticServe serves a directory as web resource
|
||||
@@ -414,14 +414,27 @@ func (rb *APIBuilder) StaticServe(systemPath string, requestPath ...string) (*Ro
|
||||
func (rb *APIBuilder) StaticContent(reqPath string, cType string, content []byte) (*Route, error) {
|
||||
modtime := time.Now()
|
||||
h := func(ctx context.Context) {
|
||||
if err := ctx.WriteWithExpiration(http.StatusOK, content, cType, modtime); err != nil {
|
||||
ctx.Application().Log("error while serving []byte via StaticContent: %s", err.Error())
|
||||
if err := ctx.WriteWithExpiration(content, cType, modtime); err != nil {
|
||||
ctx.NotFound()
|
||||
// ctx.Application().Log("error while serving []byte via StaticContent: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return rb.registerResourceRoute(reqPath, h)
|
||||
}
|
||||
|
||||
// StaticEmbeddedHandler returns a Handler which can serve
|
||||
// embedded into executable files.
|
||||
//
|
||||
//
|
||||
// Examples: https://github.com/kataras/iris/tree/master/_examples/file-server
|
||||
func (rb *APIBuilder) StaticEmbeddedHandler(vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string) context.Handler {
|
||||
// Notes:
|
||||
// This doesn't need to be APIBuilder's scope,
|
||||
// but we'll keep it here for consistently.
|
||||
return StaticEmbeddedHandler(vdir, assetFn, namesFn)
|
||||
}
|
||||
|
||||
// StaticEmbedded used when files are distributed inside the app executable, using go-bindata mostly
|
||||
// First parameter is the request path, the path which the files in the vdir will be served to, for example "/static"
|
||||
// Second parameter is the (virtual) directory path, for example "./assets"
|
||||
@@ -430,78 +443,12 @@ func (rb *APIBuilder) StaticContent(reqPath string, cType string, content []byte
|
||||
//
|
||||
// Returns the GET *Route.
|
||||
//
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/intermediate/serve-embedded-files
|
||||
// Examples: https://github.com/kataras/iris/tree/master/_examples/file-server
|
||||
func (rb *APIBuilder) StaticEmbedded(requestPath string, vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string) (*Route, error) {
|
||||
paramName := "path"
|
||||
|
||||
requestPath = joinPath(requestPath, WildcardParam(paramName))
|
||||
|
||||
if len(vdir) > 0 {
|
||||
if vdir[0] == '.' { // first check for .wrong
|
||||
vdir = vdir[1:]
|
||||
}
|
||||
if vdir[0] == '/' || vdir[0] == os.PathSeparator { // second check for /something, (or ./something if we had dot on 0 it will be removed
|
||||
vdir = vdir[1:]
|
||||
}
|
||||
}
|
||||
|
||||
// collect the names we are care for, because not all Asset used here, we need the vdir's assets.
|
||||
allNames := namesFn()
|
||||
|
||||
var names []string
|
||||
for _, path := range allNames {
|
||||
// check if path is the path name we care for
|
||||
if !strings.HasPrefix(path, vdir) {
|
||||
continue
|
||||
}
|
||||
names = append(names, cleanPath(path))
|
||||
// path = strings.Replace(path, "\\", "/", -1) // replace system paths with double slashes
|
||||
// path = strings.Replace(path, "./", "/", -1) // replace ./assets/favicon.ico to /assets/favicon.ico in order to be ready for compare with the reqPath later
|
||||
// path = path[len(vdir):] // set it as the its 'relative' ( we should re-setted it when assetFn will be used)
|
||||
// names = append(names, path)
|
||||
}
|
||||
|
||||
if len(names) == 0 {
|
||||
return nil, errors.New("unable to locate any embedded files located to the (virtual) directory: " + vdir)
|
||||
}
|
||||
|
||||
modtime := time.Now()
|
||||
h := func(ctx context.Context) {
|
||||
reqPath := ctx.Params().Get(paramName)
|
||||
for _, path := range names {
|
||||
// in order to map "/" as "/index.html"
|
||||
// as requested here: https://github.com/kataras/iris/issues/633#issuecomment-281691851
|
||||
if path == "/index.html" {
|
||||
if reqPath[len(reqPath)-1] == '/' {
|
||||
reqPath = "/index.html"
|
||||
}
|
||||
}
|
||||
|
||||
if path != reqPath {
|
||||
continue
|
||||
}
|
||||
|
||||
cType := TypeByExtension(path)
|
||||
fullpath := vdir + path
|
||||
|
||||
buf, err := assetFn(fullpath)
|
||||
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := ctx.WriteWithExpiration(http.StatusOK, buf, cType, modtime); err != nil {
|
||||
ctx.StatusCode(http.StatusInternalServerError)
|
||||
ctx.StopExecution()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// not found or error
|
||||
ctx.NotFound()
|
||||
|
||||
}
|
||||
fullpath := joinPath(rb.relativePath, requestPath)
|
||||
requestPath = joinPath(fullpath, WildcardParam("file"))
|
||||
|
||||
h := StripPrefix(fullpath, rb.StaticEmbeddedHandler(vdir, assetFn, namesFn))
|
||||
return rb.registerResourceRoute(requestPath, h)
|
||||
}
|
||||
|
||||
@@ -569,7 +516,8 @@ func (rb *APIBuilder) Favicon(favPath string, requestPath ...string) (*Route, er
|
||||
ctx.ResponseWriter().Header().Set(lastModifiedHeaderKey, modtime)
|
||||
ctx.StatusCode(http.StatusOK)
|
||||
if _, err := ctx.Write(cacheFav); err != nil {
|
||||
ctx.Application().Log("error while trying to serve the favicon: %s", err.Error())
|
||||
// ctx.Application().Log("error while trying to serve the favicon: %s", err.Error())
|
||||
ctx.StatusCode(http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,13 +544,17 @@ func (rb *APIBuilder) Favicon(favPath string, requestPath ...string) (*Route, er
|
||||
// ending in "/index.html" to the same path, without the final
|
||||
// "index.html".
|
||||
//
|
||||
// StaticWeb calls the StaticHandler(requestPath, systemPath, listingDirectories: false, gzip: false ).
|
||||
// StaticWeb calls the StaticHandler(systemPath, listingDirectories: false, gzip: false ).
|
||||
//
|
||||
// Returns the GET *Route.
|
||||
func (rb *APIBuilder) StaticWeb(reqPath string, systemPath string, exceptRoutes ...*Route) (*Route, error) {
|
||||
h := rb.StaticHandler(reqPath, systemPath, false, false, exceptRoutes...)
|
||||
func (rb *APIBuilder) StaticWeb(requestPath string, systemPath string, exceptRoutes ...*Route) (*Route, error) {
|
||||
|
||||
paramName := "file"
|
||||
routePath := joinPath(reqPath, WildcardParam(paramName))
|
||||
|
||||
fullpath := joinPath(rb.relativePath, requestPath)
|
||||
|
||||
h := StripPrefix(fullpath, rb.StaticHandler(systemPath, false, false, exceptRoutes...))
|
||||
|
||||
handler := func(ctx context.Context) {
|
||||
h(ctx)
|
||||
// re-check the content type here for any case,
|
||||
@@ -614,8 +566,8 @@ func (rb *APIBuilder) StaticWeb(reqPath string, systemPath string, exceptRoutes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rb.registerResourceRoute(routePath, handler)
|
||||
requestPath = joinPath(fullpath, WildcardParam(paramName))
|
||||
return rb.registerResourceRoute(requestPath, handler)
|
||||
}
|
||||
|
||||
// OnErrorCode registers an error http status code
|
||||
|
||||
@@ -24,6 +24,84 @@ import (
|
||||
"github.com/kataras/iris/core/errors"
|
||||
)
|
||||
|
||||
// StaticEmbeddedHandler returns a Handler which can serve
|
||||
// embedded into executable files.
|
||||
//
|
||||
//
|
||||
// Examples: https://github.com/kataras/iris/tree/master/_examples/file-server
|
||||
func StaticEmbeddedHandler(vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string) context.Handler {
|
||||
// Depends on the command the user gave to the go-bindata
|
||||
// the assset path (names) may be or may not be prepended with a slash.
|
||||
// What we do: we remove the ./ from the vdir which should be
|
||||
// the same with the asset path (names).
|
||||
// we don't pathclean, because that will prepend a slash
|
||||
// go-bindata should give a correct path format.
|
||||
// On serve time we check the "paramName" (which is the path after the "requestPath")
|
||||
// so it has the first directory part missing, we use the "vdir" to complete it
|
||||
// and match with the asset path (names).
|
||||
if len(vdir) > 0 {
|
||||
if vdir[0] == '.' {
|
||||
vdir = vdir[1:]
|
||||
}
|
||||
if vdir[0] == '/' || vdir[0] == os.PathSeparator { // second check for /something, (or ./something if we had dot on 0 it will be removed
|
||||
vdir = vdir[1:]
|
||||
}
|
||||
}
|
||||
|
||||
// collect the names we are care for,
|
||||
// because not all Asset used here, we need the vdir's assets.
|
||||
allNames := namesFn()
|
||||
|
||||
var names []string
|
||||
for _, path := range allNames {
|
||||
// i.e: path = public/css/main.css
|
||||
|
||||
// check if path is the path name we care for
|
||||
if !strings.HasPrefix(path, vdir) {
|
||||
continue
|
||||
}
|
||||
|
||||
names = append(names, path)
|
||||
}
|
||||
|
||||
modtime := time.Now()
|
||||
h := func(ctx context.Context) {
|
||||
reqPath := strings.TrimPrefix(ctx.Request().URL.Path, "/"+vdir)
|
||||
// i.e : /css/main.css
|
||||
|
||||
for _, path := range names {
|
||||
// in order to map "/" as "/index.html"
|
||||
if path == "/index.html" && reqPath == "/" {
|
||||
reqPath = "/index.html"
|
||||
}
|
||||
|
||||
if path != vdir+reqPath {
|
||||
continue
|
||||
}
|
||||
|
||||
cType := TypeByFilename(path)
|
||||
|
||||
buf, err := assetFn(path) // remove the first slash
|
||||
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := ctx.WriteWithExpiration(buf, cType, modtime); err != nil {
|
||||
ctx.StatusCode(http.StatusInternalServerError)
|
||||
ctx.StopExecution()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// not found or error
|
||||
ctx.NotFound()
|
||||
|
||||
}
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
// Prioritize is a middleware which executes a route against this path
|
||||
// when the request's Path has a prefix of the route's STATIC PART
|
||||
// is not executing ExecRoute to determinate if it's valid, for performance reasons
|
||||
@@ -230,6 +308,7 @@ func (w *fsHandler) Build() context.Handler {
|
||||
// headers[contentEncodingHeader] = nil
|
||||
// headers[contentLength] = nil
|
||||
}
|
||||
// ctx.Application().Log(errMsg)
|
||||
ctx.StatusCode(prevStatusCode)
|
||||
return
|
||||
}
|
||||
@@ -741,16 +820,13 @@ func serveFile(ctx context.Context, fs http.FileSystem, name string, redirect bo
|
||||
|
||||
f, err := fs.Open(name)
|
||||
if err != nil {
|
||||
msg, code := toHTTPError(err)
|
||||
return msg, code
|
||||
return err.Error(), 404
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
d, err := f.Stat()
|
||||
if err != nil {
|
||||
msg, code := toHTTPError(err)
|
||||
return msg, code
|
||||
|
||||
return err.Error(), 404
|
||||
}
|
||||
|
||||
if redirect {
|
||||
|
||||
@@ -76,6 +76,15 @@ func (nodes *Nodes) add(path string, paramNames []string, handlers context.Handl
|
||||
// na to kanw na exei to node to diko tou wildcard parameter name
|
||||
// kai sto telos na pernei auto, me vasi to *paramname
|
||||
// alla edw mesa 9a ginete register vasi tou last /
|
||||
|
||||
// set the wildcard param name to the root and its children.
|
||||
wildcardIdx := strings.IndexByte(path, '*')
|
||||
wildcardParamName := ""
|
||||
if wildcardIdx > 0 {
|
||||
wildcardParamName = path[wildcardIdx+1:]
|
||||
path = path[0:wildcardIdx-1] + "/" // replace *paramName with single slash
|
||||
}
|
||||
|
||||
loop:
|
||||
for _, n := range *nodes {
|
||||
|
||||
@@ -97,14 +106,14 @@ loop:
|
||||
children: Nodes{
|
||||
{
|
||||
s: n.s[i:],
|
||||
wildcardParamName: n.wildcardParamName,
|
||||
wildcardParamName: wildcardParamName,
|
||||
paramNames: n.paramNames,
|
||||
children: n.children,
|
||||
handlers: n.handlers,
|
||||
},
|
||||
{
|
||||
s: path[i:],
|
||||
wildcardParamName: n.wildcardParamName,
|
||||
wildcardParamName: wildcardParamName,
|
||||
paramNames: paramNames,
|
||||
handlers: handlers,
|
||||
},
|
||||
@@ -117,12 +126,12 @@ loop:
|
||||
if len(path) < len(n.s) {
|
||||
*n = node{
|
||||
s: n.s[:len(path)],
|
||||
wildcardParamName: n.wildcardParamName,
|
||||
wildcardParamName: wildcardParamName,
|
||||
paramNames: paramNames,
|
||||
children: Nodes{
|
||||
{
|
||||
s: n.s[len(path):],
|
||||
wildcardParamName: n.wildcardParamName,
|
||||
wildcardParamName: wildcardParamName,
|
||||
paramNames: n.paramNames,
|
||||
children: n.children,
|
||||
handlers: n.handlers,
|
||||
@@ -144,7 +153,7 @@ loop:
|
||||
return nil
|
||||
}
|
||||
if len(n.handlers) > 0 { // n.handlers already setted
|
||||
return ErrDublicate
|
||||
return ErrDublicate.Append("for: %s", n.s)
|
||||
}
|
||||
n.paramNames = paramNames
|
||||
n.handlers = handlers
|
||||
@@ -152,15 +161,6 @@ loop:
|
||||
return
|
||||
}
|
||||
|
||||
// set the wildcard param name to the root.
|
||||
|
||||
wildcardIdx := strings.IndexByte(path, '*')
|
||||
wildcardParamName := ""
|
||||
if wildcardIdx > 0 {
|
||||
wildcardParamName = path[wildcardIdx+1:]
|
||||
path = path[0:wildcardIdx-1] + "/" // replace *paramName with single slash
|
||||
}
|
||||
|
||||
n := &node{
|
||||
s: path,
|
||||
wildcardParamName: wildcardParamName,
|
||||
|
||||
@@ -84,20 +84,19 @@ type Party interface {
|
||||
//
|
||||
// Note:
|
||||
// The only difference from package-level `StaticHandler`
|
||||
// is that this `StaticHandler`` receives a request path which
|
||||
// is appended to the party's relative path and stripped here,
|
||||
// so `iris.StripPath` is useless and should not being used here.
|
||||
// is that this `StaticHandler` receives a request path which
|
||||
// is appended to the party's relative path and stripped here.
|
||||
//
|
||||
// Usage:
|
||||
// app := iris.New()
|
||||
// ...
|
||||
// mySubdomainFsServer := app.Party("mysubdomain.")
|
||||
// h := mySubdomainFsServer.StaticHandler("/static", "./static_files", false, false)
|
||||
// h := mySubdomainFsServer.StaticHandler("./static_files", false, false)
|
||||
// /* http://mysubdomain.mydomain.com/static/css/style.css */
|
||||
// mySubdomainFsServer.Get("/static", h)
|
||||
// ...
|
||||
//
|
||||
StaticHandler(requestPath string, systemPath string, showList bool, enableGzip bool, exceptRoutes ...*Route) context.Handler
|
||||
StaticHandler(systemPath string, showList bool, enableGzip bool, exceptRoutes ...*Route) context.Handler
|
||||
|
||||
// StaticServe serves a directory as web resource
|
||||
// it's the simpliest form of the Static* functions
|
||||
@@ -114,6 +113,7 @@ type Party interface {
|
||||
//
|
||||
// Returns the GET *Route.
|
||||
StaticContent(requestPath string, cType string, content []byte) (*Route, error)
|
||||
|
||||
// StaticEmbedded used when files are distributed inside the app executable, using go-bindata mostly
|
||||
// First parameter is the request path, the path which the files in the vdir will be served to, for example "/static"
|
||||
// Second parameter is the (virtual) directory path, for example "./assets"
|
||||
@@ -152,7 +152,7 @@ type Party interface {
|
||||
// ending in "/index.html" to the same path, without the final
|
||||
// "index.html".
|
||||
//
|
||||
// StaticWeb calls the StaticHandler(requestPath, systemPath, listingDirectories: false, gzip: false ).
|
||||
// StaticWeb calls the StaticHandler(systemPath, listingDirectories: false, gzip: false ).
|
||||
//
|
||||
// Returns the GET *Route.
|
||||
StaticWeb(requestPath string, systemPath string, exceptRoutes ...*Route) (*Route, error)
|
||||
|
||||
@@ -47,7 +47,6 @@ func NewRoute(method, subdomain, unparsedPath string,
|
||||
|
||||
path = cleanPath(path) // maybe unnecessary here but who cares in this moment
|
||||
defaultName := method + subdomain + path
|
||||
|
||||
formattedPath := formatPath(path)
|
||||
|
||||
route := &Route{
|
||||
|
||||
@@ -102,6 +102,12 @@ func (router *Router) Downgraded() bool {
|
||||
return router.mainHandler != nil && router.requestHandler == nil
|
||||
}
|
||||
|
||||
// WrapperFunc is used as an expected input parameter signature
|
||||
// for the WrapRouter. It's a "low-level" signature which is compatible
|
||||
// with the net/http.
|
||||
// It's being used to run or no run the router based on a custom logic.
|
||||
type WrapperFunc func(w http.ResponseWriter, r *http.Request, firstNextIsTheRouter http.HandlerFunc)
|
||||
|
||||
// WrapRouter adds a wrapper on the top of the main router.
|
||||
// Usually it's useful for third-party middleware
|
||||
// when need to wrap the entire application with a middleware like CORS.
|
||||
@@ -111,7 +117,7 @@ func (router *Router) Downgraded() bool {
|
||||
// That means that the second wrapper will wrap the first, and so on.
|
||||
//
|
||||
// Before build.
|
||||
func (router *Router) WrapRouter(wrapperFunc func(w http.ResponseWriter, r *http.Request, firstNextIsTheRouter http.HandlerFunc)) {
|
||||
func (router *Router) WrapRouter(wrapperFunc WrapperFunc) {
|
||||
router.mu.Lock()
|
||||
defer router.mu.Unlock()
|
||||
|
||||
|
||||
96
core/router/spa.go
Normal file
96
core/router/spa.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/kataras/iris/context"
|
||||
)
|
||||
|
||||
// AssetValidator returns true if "filename"
|
||||
// is asset, i.e: strings.Contains(filename, ".").
|
||||
type AssetValidator func(filename string) bool
|
||||
|
||||
// SPABuilder helps building a single page application server
|
||||
// which serves both routes and files from the root path.
|
||||
type SPABuilder struct {
|
||||
IndexNames []string
|
||||
AssetHandler context.Handler
|
||||
AssetValidators []AssetValidator
|
||||
}
|
||||
|
||||
// NewSPABuilder returns a new Single Page Application builder
|
||||
// It does what StaticWeb expected to do when serving files and routes at the same time
|
||||
// from the root "/" path.
|
||||
//
|
||||
// Accepts a static asset handler, which can be an app.StaticHandler, app.StaticEmbeddedHandler...
|
||||
func NewSPABuilder(assetHandler context.Handler) *SPABuilder {
|
||||
if assetHandler == nil {
|
||||
assetHandler = func(ctx context.Context) {
|
||||
ctx.Writef("empty asset handler")
|
||||
}
|
||||
}
|
||||
|
||||
return &SPABuilder{
|
||||
IndexNames: []string{"index.html"},
|
||||
AssetHandler: assetHandler,
|
||||
AssetValidators: []AssetValidator{
|
||||
func(path string) bool {
|
||||
return strings.Contains(path, ".")
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SPABuilder) isAsset(reqPath string) bool {
|
||||
for _, v := range s.AssetValidators {
|
||||
if !v(reqPath) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// BuildWrapper returns a wrapper which serves the single page application
|
||||
// with the declared configuration.
|
||||
//
|
||||
// It should be passed to the router's `WrapRouter`:
|
||||
// https://godoc.org/github.com/kataras/iris/core/router#Router.WrapRouter
|
||||
//
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/beginner/file-server/single-page-application-builder
|
||||
func (s *SPABuilder) BuildWrapper(cPool *context.Pool) WrapperFunc {
|
||||
|
||||
fileServer := s.AssetHandler
|
||||
indexNames := s.IndexNames
|
||||
|
||||
wrapper := func(w http.ResponseWriter, r *http.Request, router http.HandlerFunc) {
|
||||
path := r.URL.Path
|
||||
|
||||
if !s.isAsset(path) {
|
||||
// it's not asset, execute the registered route's handlers
|
||||
router(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := cPool.Acquire(w, r)
|
||||
|
||||
for _, index := range indexNames {
|
||||
if strings.HasSuffix(path, index) {
|
||||
localRedirect(ctx, "./")
|
||||
cPool.Release(ctx)
|
||||
// "/" should be manually registered.
|
||||
// We don't setup an index handler here,
|
||||
// let full control to the user
|
||||
// (use middleware, ctx.ServeFile or ctx.View and so on...)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// execute file server for path
|
||||
fileServer(ctx)
|
||||
|
||||
cPool.Release(ctx)
|
||||
}
|
||||
|
||||
return wrapper
|
||||
}
|
||||
Reference in New Issue
Block a user