mirror of
https://github.com/kataras/iris.git
synced 2025-03-14 08:16:28 +01:00
Nothing special here, just split the static handler to a package-level func and per-route func (same as before)
Former-commit-id: 1912d85de84856c715dfa7b79d771cada1b638b9
This commit is contained in:
parent
f487cd0029
commit
ac3abca684
|
@ -23,6 +23,18 @@ func main() {
|
||||||
// Serve static files (css)
|
// Serve static files (css)
|
||||||
app.StaticWeb("/static", "./static_files")
|
app.StaticWeb("/static", "./static_files")
|
||||||
|
|
||||||
|
// other solution for both static files and urls in the root path(not recommended but it's here if you ever need it):
|
||||||
|
// fileserver := iris.StaticHandler("./static_files", false, false)
|
||||||
|
// app.Get("/*path", func(ctx *iris.Context) {
|
||||||
|
// fileserver.Serve(ctx)
|
||||||
|
// if ctx.StatusCode() >= 200 && ctx.StatusCode() < 300 {
|
||||||
|
// // then the file found and served correctly.
|
||||||
|
// } else {
|
||||||
|
// // otherwise check for urls....
|
||||||
|
// execShortURL(ctx, ctx.Param("path"))
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
|
||||||
var mu sync.Mutex
|
var mu sync.Mutex
|
||||||
var urls = map[string]string{
|
var urls = map[string]string{
|
||||||
"iris": "http://support.iris-go.com",
|
"iris": "http://support.iris-go.com",
|
||||||
|
@ -53,7 +65,7 @@ func main() {
|
||||||
execShortURL(ctx, ctx.Param("shortkey"))
|
execShortURL(ctx, ctx.Param("shortkey"))
|
||||||
})
|
})
|
||||||
|
|
||||||
// for wildcard subdomain (yeah.. cool) http://dsaoj41u321dsa.localhost:8080
|
// for wildcard subdomain (yeah.. cool) http://dsaoj41u321dsa.localhost:8080
|
||||||
// Note:
|
// Note:
|
||||||
// if you want subdomains (chrome doesn't works on localhost, so you have to define other hostname on app.Listen)
|
// if you want subdomains (chrome doesn't works on localhost, so you have to define other hostname on app.Listen)
|
||||||
// app.Party("*.", func(ctx *iris.Context) {
|
// app.Party("*.", func(ctx *iris.Context) {
|
||||||
|
|
48
adaptors/view/_examples/custom_renderer/main.go
Normal file
48
adaptors/view/_examples/custom_renderer/main.go
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"gopkg.in/kataras/iris.v6"
|
||||||
|
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := iris.New()
|
||||||
|
// output startup banner and error logs on os.Stdout
|
||||||
|
app.Adapt(iris.DevLogger())
|
||||||
|
// set the router, you can choose gorillamux too
|
||||||
|
app.Adapt(httprouter.New())
|
||||||
|
|
||||||
|
// Custom Render Policy to override or create new content-type render
|
||||||
|
// i,e: "text/html" with a prefix,
|
||||||
|
// we will just write to the writer and return false
|
||||||
|
// to continue to the next contentType-matched renderer if any.
|
||||||
|
app.Adapt(iris.RenderPolicy(func(out io.Writer, contentType string, binding interface{}, options ...map[string]interface{}) (bool, error) {
|
||||||
|
|
||||||
|
if contentType == "text/html" {
|
||||||
|
if content, ok := binding.(string); ok {
|
||||||
|
out.Write([]byte("<pre>My Custom prefix</pre><br/>" + content))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// continue to the next, no error
|
||||||
|
// note: if we wanted to stop here we would return true instead of false.
|
||||||
|
return false, nil
|
||||||
|
}))
|
||||||
|
|
||||||
|
app.Get("", func(ctx *iris.Context) {
|
||||||
|
|
||||||
|
// These content-types are not managed by our RenderPolicy:
|
||||||
|
// text, binary and html content-types are
|
||||||
|
// not rendered via serializers, you have to
|
||||||
|
// use the ctx.Render functions instead.
|
||||||
|
// so something like this:
|
||||||
|
// ctx.Text(iris.StatusOK, "my text content body here!")
|
||||||
|
// will NOT work with out custom render policy.
|
||||||
|
ctx.Render("text/html",
|
||||||
|
"my text content body here!")
|
||||||
|
})
|
||||||
|
|
||||||
|
app.Listen(":8080")
|
||||||
|
}
|
|
@ -55,39 +55,5 @@ func main() {
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// ------ first customization without even the need of *Context or a Handler--------
|
|
||||||
//
|
|
||||||
// Custom new content-/type:
|
|
||||||
// app.Adapt(iris.RenderPolicy(func(out io.Writer, name string, binding interface{}, options ...map[string]interface{}) (error, bool) {
|
|
||||||
// if name == "customcontent-type" {
|
|
||||||
//
|
|
||||||
// // some very advanced things here:
|
|
||||||
// out.Write([]byte(binding.(string)))
|
|
||||||
// return nil, true
|
|
||||||
// }
|
|
||||||
// return nil, false
|
|
||||||
// }))
|
|
||||||
//
|
|
||||||
// app.Get("/custom", func(ctx *iris.Context) {
|
|
||||||
// ctx.RenderWithStatus(iris.StatusOK, // or MustRender
|
|
||||||
// "customcontent-type",
|
|
||||||
// "my custom content here!",
|
|
||||||
// )
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// ---- second -----------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Override the defaults (the json,xml,jsonp,text,data and so on), an existing content-type:
|
|
||||||
// app.Adapt(iris.RenderPolicy(func(out io.Writer, name string, binding interface{}, options ...map[string]interface{}) (error, bool) {
|
|
||||||
// if name == "text/plain" {
|
|
||||||
// out.Write([]byte("From the custom text/plain renderer: " + binding.(string)))
|
|
||||||
// return nil, true
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return nil, false
|
|
||||||
// }))
|
|
||||||
// // the context.Text's behaviors was changed now by your custom renderer.
|
|
||||||
//
|
|
||||||
|
|
||||||
app.Listen(":8080")
|
app.Listen(":8080")
|
||||||
}
|
}
|
||||||
|
|
70
fs.go
70
fs.go
|
@ -20,13 +20,35 @@ import (
|
||||||
"github.com/kataras/go-errors"
|
"github.com/kataras/go-errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// StaticHandler returns a new Handler which is ready
|
||||||
|
// to serve all kind of static files.
|
||||||
|
//
|
||||||
|
// Developers can wrap this handler using the `iris.StripPrefix`
|
||||||
|
// for a fixed static path when the result handler is being, finally, registered to a route.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// app := iris.New()
|
||||||
|
// ...
|
||||||
|
// fileserver := iris.StaticHandler("./static_files", false, false)
|
||||||
|
// h := iris.StripPrefix("/static", fileserver)
|
||||||
|
// /* http://mydomain.com/static/css/style.css */
|
||||||
|
// app.Get("/static", h)
|
||||||
|
// ...
|
||||||
|
//
|
||||||
|
func StaticHandler(systemPath string, showList bool, enableGzip bool, exceptRoutes ...RouteInfo) HandlerFunc {
|
||||||
|
return NewStaticHandlerBuilder(systemPath).
|
||||||
|
Listing(showList).
|
||||||
|
Gzip(enableGzip).
|
||||||
|
Except(exceptRoutes...).
|
||||||
|
Build()
|
||||||
|
}
|
||||||
|
|
||||||
// StaticHandlerBuilder is the web file system's Handler builder
|
// StaticHandlerBuilder is the web file system's Handler builder
|
||||||
// use that or the iris.StaticHandler/StaticWeb methods
|
// use that or the iris.StaticHandler/StaticWeb methods
|
||||||
type StaticHandlerBuilder interface {
|
type StaticHandlerBuilder interface {
|
||||||
Path(requestRoutePath string) StaticHandlerBuilder
|
|
||||||
Gzip(enable bool) StaticHandlerBuilder
|
Gzip(enable bool) StaticHandlerBuilder
|
||||||
Listing(listDirectoriesOnOff bool) StaticHandlerBuilder
|
Listing(listDirectoriesOnOff bool) StaticHandlerBuilder
|
||||||
StripPath(yesNo bool) StaticHandlerBuilder
|
|
||||||
Except(r ...RouteInfo) StaticHandlerBuilder
|
Except(r ...RouteInfo) StaticHandlerBuilder
|
||||||
Build() HandlerFunc
|
Build() HandlerFunc
|
||||||
}
|
}
|
||||||
|
@ -40,8 +62,6 @@ type StaticHandlerBuilder interface {
|
||||||
type fsHandler struct {
|
type fsHandler struct {
|
||||||
// user options, only directory is required.
|
// user options, only directory is required.
|
||||||
directory http.Dir
|
directory http.Dir
|
||||||
requestPath string
|
|
||||||
stripPath bool
|
|
||||||
gzip bool
|
gzip bool
|
||||||
listDirectories bool
|
listDirectories bool
|
||||||
// these are init on the Build() call
|
// these are init on the Build() call
|
||||||
|
@ -82,10 +102,6 @@ func abs(path string) string {
|
||||||
func NewStaticHandlerBuilder(dir string) StaticHandlerBuilder {
|
func NewStaticHandlerBuilder(dir string) StaticHandlerBuilder {
|
||||||
return &fsHandler{
|
return &fsHandler{
|
||||||
directory: http.Dir(abs(dir)),
|
directory: http.Dir(abs(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 is disabled by default
|
||||||
gzip: false,
|
gzip: false,
|
||||||
// list directories disabled by default
|
// list directories disabled by default
|
||||||
|
@ -93,13 +109,6 @@ func NewStaticHandlerBuilder(dir string) StaticHandlerBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path sets the request path.
|
|
||||||
// Defaults to same as system path
|
|
||||||
func (w *fsHandler) Path(requestRoutePath string) StaticHandlerBuilder {
|
|
||||||
w.requestPath = toWebPath(requestRoutePath)
|
|
||||||
return w
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gzip if enable is true then gzip compression is enabled for this static directory
|
// Gzip if enable is true then gzip compression is enabled for this static directory
|
||||||
// Defaults to false
|
// Defaults to false
|
||||||
func (w *fsHandler) Gzip(enable bool) StaticHandlerBuilder {
|
func (w *fsHandler) Gzip(enable bool) StaticHandlerBuilder {
|
||||||
|
@ -114,11 +123,6 @@ func (w *fsHandler) Listing(listDirectoriesOnOff bool) StaticHandlerBuilder {
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *fsHandler) StripPath(yesNo bool) StaticHandlerBuilder {
|
|
||||||
w.stripPath = yesNo
|
|
||||||
return w
|
|
||||||
}
|
|
||||||
|
|
||||||
// Except add a route exception,
|
// Except add a route exception,
|
||||||
// gives priority to that Route over the static handler.
|
// gives priority to that Route over the static handler.
|
||||||
func (w *fsHandler) Except(r ...RouteInfo) StaticHandlerBuilder {
|
func (w *fsHandler) Except(r ...RouteInfo) StaticHandlerBuilder {
|
||||||
|
@ -160,7 +164,7 @@ func (w *fsHandler) Build() HandlerFunc {
|
||||||
w.once.Do(func() {
|
w.once.Do(func() {
|
||||||
w.filesystem = w.directory
|
w.filesystem = w.directory
|
||||||
|
|
||||||
hStatic := func(ctx *Context) {
|
fileserver := func(ctx *Context) {
|
||||||
upath := ctx.Request.URL.Path
|
upath := ctx.Request.URL.Path
|
||||||
if !strings.HasPrefix(upath, "/") {
|
if !strings.HasPrefix(upath, "/") {
|
||||||
upath = "/" + upath
|
upath = "/" + upath
|
||||||
|
@ -203,14 +207,6 @@ func (w *fsHandler) Build() HandlerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileserver HandlerFunc
|
|
||||||
|
|
||||||
if w.stripPath {
|
|
||||||
fileserver = StripPrefix(w.requestPath, hStatic)
|
|
||||||
} else {
|
|
||||||
fileserver = hStatic
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(w.exceptions) > 0 {
|
if len(w.exceptions) > 0 {
|
||||||
middleware := make(Middleware, len(w.exceptions)+1)
|
middleware := make(Middleware, len(w.exceptions)+1)
|
||||||
for i := range w.exceptions {
|
for i := range w.exceptions {
|
||||||
|
@ -237,12 +233,26 @@ func (w *fsHandler) Build() HandlerFunc {
|
||||||
// and invoking the handler h. StripPrefix handles a
|
// and invoking the handler h. StripPrefix handles a
|
||||||
// request for a path that doesn't begin with prefix by
|
// request for a path that doesn't begin with prefix by
|
||||||
// replying with an HTTP 404 not found error.
|
// replying with an HTTP 404 not found error.
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// fileserver := iris.StaticHandler("./static_files", false, false)
|
||||||
|
// h := iris.StripPrefix("/static", fileserver)
|
||||||
|
// app.Get("/static", h)
|
||||||
|
//
|
||||||
func StripPrefix(prefix string, h HandlerFunc) HandlerFunc {
|
func StripPrefix(prefix string, h HandlerFunc) HandlerFunc {
|
||||||
if prefix == "" {
|
if prefix == "" {
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
// here we separate the path from the subdomain (if any), we care only for the path
|
||||||
|
// fixes a bug when serving static files via a subdomain
|
||||||
|
fixedPrefix := prefix
|
||||||
|
if dotWSlashIdx := strings.Index(fixedPrefix, subdomainIndicator); dotWSlashIdx > 0 {
|
||||||
|
fixedPrefix = fixedPrefix[dotWSlashIdx+1:]
|
||||||
|
}
|
||||||
|
fixedPrefix = toWebPath(fixedPrefix)
|
||||||
|
|
||||||
return func(ctx *Context) {
|
return func(ctx *Context) {
|
||||||
if p := strings.TrimPrefix(ctx.Request.URL.Path, prefix); len(p) < len(ctx.Request.URL.Path) {
|
if p := strings.TrimPrefix(ctx.Request.URL.Path, fixedPrefix); len(p) < len(ctx.Request.URL.Path) {
|
||||||
ctx.Request.URL.Path = p
|
ctx.Request.URL.Path = p
|
||||||
h(ctx)
|
h(ctx)
|
||||||
} else {
|
} else {
|
||||||
|
|
51
router.go
51
router.go
|
@ -562,22 +562,27 @@ func (router *Router) Favicon(favPath string, requestPath ...string) RouteInfo {
|
||||||
return router.registerResourceRoute(reqPath, h)
|
return router.registerResourceRoute(reqPath, h)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StaticHandler returns a new Handler which serves static files
|
// StaticHandler returns a new Handler which is ready
|
||||||
|
// to serve all kind of static files.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// app := iris.New()
|
||||||
|
// ...
|
||||||
|
// mySubdomainFsServer := app.Party("mysubdomain.")
|
||||||
|
// h := mySubdomainFsServer.StaticHandler("/static", "./static_files", false, false)
|
||||||
|
// /* http://mysubdomain.mydomain.com/static/css/style.css */
|
||||||
|
// mySubdomainFsServer.Get("/static", h)
|
||||||
|
// ...
|
||||||
|
//
|
||||||
func (router *Router) StaticHandler(reqPath string, systemPath string, showList bool, enableGzip bool, exceptRoutes ...RouteInfo) HandlerFunc {
|
func (router *Router) StaticHandler(reqPath string, systemPath string, showList bool, enableGzip bool, exceptRoutes ...RouteInfo) HandlerFunc {
|
||||||
// here we separate the path from the subdomain (if any), we care only for the path
|
return StripPrefix(router.relativePath+reqPath,
|
||||||
// fixes a bug when serving static files via a subdomain
|
StaticHandler(systemPath, showList, enableGzip))
|
||||||
fullpath := router.relativePath + reqPath
|
|
||||||
path := fullpath
|
|
||||||
if dotWSlashIdx := strings.Index(path, subdomainIndicator); dotWSlashIdx > 0 {
|
|
||||||
path = fullpath[dotWSlashIdx+1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
return NewStaticHandlerBuilder(systemPath).
|
|
||||||
Path(path).
|
|
||||||
Listing(showList).
|
|
||||||
Gzip(enableGzip).
|
|
||||||
Except(exceptRoutes...).
|
|
||||||
Build()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// StaticWeb returns a handler that serves HTTP requests
|
// StaticWeb returns a handler that serves HTTP requests
|
||||||
|
@ -602,15 +607,17 @@ func (router *Router) StaticWeb(reqPath string, systemPath string, exceptRoutes
|
||||||
routePath := router.Context.Framework().RouteWildcardPath(reqPath, paramName)
|
routePath := router.Context.Framework().RouteWildcardPath(reqPath, paramName)
|
||||||
handler := func(ctx *Context) {
|
handler := func(ctx *Context) {
|
||||||
h(ctx)
|
h(ctx)
|
||||||
if fname := ctx.Param(paramName); fname != "" {
|
// re-check the content type here for any case,
|
||||||
cType := typeByExtension(fname)
|
// although the new code does it automatically but it's good to have it here.
|
||||||
if cType != contentBinary && !strings.Contains(cType, "charset") {
|
if ctx.StatusCode() >= 200 && ctx.StatusCode() < 400 {
|
||||||
cType += "; charset=" + ctx.framework.Config.Charset
|
if fname := ctx.Param(paramName); fname != "" {
|
||||||
|
cType := typeByExtension(fname)
|
||||||
|
if cType != contentBinary && !strings.Contains(cType, "charset") {
|
||||||
|
cType += "; charset=" + ctx.framework.Config.Charset
|
||||||
|
}
|
||||||
|
ctx.SetContentType(cType)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.SetContentType(cType)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return router.registerResourceRoute(routePath, handler)
|
return router.registerResourceRoute(routePath, handler)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user