mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 10:41:03 +01:00
This commit is contained in:
parent
889b7942d3
commit
227170fd33
|
@ -43,7 +43,7 @@ func createRoot(redirectTo string) *iris.Application {
|
||||||
fullScheme = "https://"
|
fullScheme = "https://"
|
||||||
}
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, fullScheme+redirectTo, iris.StatusMovedPermanently)
|
http.Redirect(w, r, fullScheme+redirectTo+r.URL.RequestURI(), iris.StatusMovedPermanently)
|
||||||
})
|
})
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
2
cli.go
2
cli.go
|
@ -115,6 +115,6 @@ func injectLiveReload(contextPool *context.Pool, router *router.Router) (bool, e
|
||||||
contextPool.Release(ctx)
|
contextPool.Release(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
router.WrapRouter(wrapper)
|
router.AddRouterWrapper(wrapper)
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,14 @@ type Router struct {
|
||||||
requestHandler RequestHandler // build-accessible, can be changed to define a custom router or proxy, used on RefreshRouter too.
|
requestHandler RequestHandler // build-accessible, can be changed to define a custom router or proxy, used on RefreshRouter too.
|
||||||
mainHandler http.HandlerFunc // init-accessible
|
mainHandler http.HandlerFunc // init-accessible
|
||||||
wrapperFunc WrapperFunc
|
wrapperFunc WrapperFunc
|
||||||
|
// wrappers to be built on BuildRouter state,
|
||||||
|
// first is executed first at this case.
|
||||||
|
// Case:
|
||||||
|
// - SubdomainRedirect on user call, registers a wrapper, on design state
|
||||||
|
// - i18n,if loaded and Subdomain or PathRedirect is true, registers a wrapper too, on build state
|
||||||
|
// the SubdomainRedirect should be the first(subdomainWrap(i18nWrap)) wrapper
|
||||||
|
// to be executed instead of last(i18nWrap(subdomainWrap)).
|
||||||
|
wrapperFuncs []WrapperFunc
|
||||||
|
|
||||||
cPool *context.Pool // used on RefreshRouter
|
cPool *context.Pool // used on RefreshRouter
|
||||||
routesProvider RoutesProvider
|
routesProvider RoutesProvider
|
||||||
|
@ -216,6 +224,14 @@ func (router *Router) BuildRouter(cPool *context.Pool, requestHandler RequestHan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i := len(router.wrapperFuncs) - 1; i >= 0; i-- {
|
||||||
|
w := router.wrapperFuncs[i]
|
||||||
|
if w == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
router.WrapRouter(w)
|
||||||
|
}
|
||||||
|
|
||||||
if router.wrapperFunc != nil { // if wrapper used then attach that as the router service
|
if router.wrapperFunc != nil { // if wrapper used then attach that as the router service
|
||||||
router.mainHandler = newWrapper(router.wrapperFunc, router.mainHandler).ServeHTTP
|
router.mainHandler = newWrapper(router.wrapperFunc, router.mainHandler).ServeHTTP
|
||||||
}
|
}
|
||||||
|
@ -268,9 +284,35 @@ func (router *Router) Downgraded() bool {
|
||||||
//
|
//
|
||||||
// Before build.
|
// Before build.
|
||||||
func (router *Router) WrapRouter(wrapperFunc WrapperFunc) {
|
func (router *Router) WrapRouter(wrapperFunc WrapperFunc) {
|
||||||
|
// logger := context.DefaultLogger("router wrapper")
|
||||||
|
// file, line := context.HandlerFileLineRel(wrapperFunc)
|
||||||
|
// if router.wrapperFunc != nil {
|
||||||
|
// wrappedFile, wrappedLine := context.HandlerFileLineRel(router.wrapperFunc)
|
||||||
|
// logger.Infof("%s:%d wraps %s:%d", file, line, wrappedFile, wrappedLine)
|
||||||
|
// } else {
|
||||||
|
// logger.Infof("%s:%d wraps the main router", file, line)
|
||||||
|
// }
|
||||||
router.wrapperFunc = makeWrapperFunc(router.wrapperFunc, wrapperFunc)
|
router.wrapperFunc = makeWrapperFunc(router.wrapperFunc, wrapperFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddRouterWrapper adds a router wrapper.
|
||||||
|
// Unlike `WrapRouter` the first registered will be executed first
|
||||||
|
// so a wrapper wraps its next not the previous one.
|
||||||
|
// it defers the wrapping until the `BuildRouter`.
|
||||||
|
// Redirection wrappers should be added using this method
|
||||||
|
// e.g. SubdomainRedirect.
|
||||||
|
func (router *Router) AddRouterWrapper(wrapperFunc WrapperFunc) {
|
||||||
|
router.wrapperFuncs = append(router.wrapperFuncs, wrapperFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrependRouterWrapper like `AddRouterWrapper` but this wrapperFunc
|
||||||
|
// will always be executed before the previous `AddRouterWrapper`.
|
||||||
|
// Path form (no modification) wrappers should be added using this method
|
||||||
|
// e.g. ForceLowercaseRouting.
|
||||||
|
func (router *Router) PrependRouterWrapper(wrapperFunc WrapperFunc) {
|
||||||
|
router.wrapperFuncs = append([]WrapperFunc{wrapperFunc}, router.wrapperFuncs...)
|
||||||
|
}
|
||||||
|
|
||||||
// ServeHTTPC serves the raw context, useful if we have already a context, it by-pass the wrapper.
|
// ServeHTTPC serves the raw context, useful if we have already a context, it by-pass the wrapper.
|
||||||
func (router *Router) ServeHTTPC(ctx *context.Context) {
|
func (router *Router) ServeHTTPC(ctx *context.Context) {
|
||||||
router.requestHandler.HandleRequest(ctx)
|
router.requestHandler.HandleRequest(ctx)
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
"github.com/kataras/iris/v12/context"
|
"github.com/kataras/iris/v12/context"
|
||||||
"github.com/kataras/iris/v12/core/netutil"
|
"github.com/kataras/iris/v12/core/netutil"
|
||||||
|
@ -42,7 +44,7 @@ func pathIsWildcard(partyRelPath string) bool {
|
||||||
//
|
//
|
||||||
// Usage(package-level):
|
// Usage(package-level):
|
||||||
// sd := NewSubdomainRedirectWrapper(func() string { return "mydomain.com" }, ".", "www.")
|
// sd := NewSubdomainRedirectWrapper(func() string { return "mydomain.com" }, ".", "www.")
|
||||||
// router.WrapRouter(sd)
|
// router.AddRouterWrapper(sd)
|
||||||
//
|
//
|
||||||
// Usage(high-level using `iris#Application.SubdomainRedirect`)
|
// Usage(high-level using `iris#Application.SubdomainRedirect`)
|
||||||
// www := app.Subdomain("www")
|
// www := app.Subdomain("www")
|
||||||
|
@ -56,12 +58,12 @@ func pathIsWildcard(partyRelPath string) bool {
|
||||||
// One or more subdomain redirect wrappers can be used to the same router instance.
|
// One or more subdomain redirect wrappers can be used to the same router instance.
|
||||||
//
|
//
|
||||||
// NewSubdomainRedirectWrapper may return nil if not allowed input arguments values were received
|
// NewSubdomainRedirectWrapper may return nil if not allowed input arguments values were received
|
||||||
// but in that case, the `WrapRouter` will, simply, ignore that wrapper.
|
// but in that case, the `AddRouterWrapper` will, simply, ignore that wrapper.
|
||||||
//
|
//
|
||||||
// Example: https://github.com/kataras/iris/tree/master/_examples/routing/subdomains/redirect
|
// Example: https://github.com/kataras/iris/tree/master/_examples/routing/subdomains/redirect
|
||||||
func NewSubdomainRedirectWrapper(rootDomainGetter func() string, from, to string) WrapperFunc {
|
func NewSubdomainRedirectWrapper(rootDomainGetter func() string, from, to string) WrapperFunc {
|
||||||
// we can return nil,
|
// we can return nil,
|
||||||
// because if wrapper is nil then it's not be used on the `router#WrapRouter`.
|
// because if wrapper is nil then it's not be used on the `router#AddRouterWrapper`.
|
||||||
if from == to {
|
if from == to {
|
||||||
// cannot redirect to the same location, cycle.
|
// cannot redirect to the same location, cycle.
|
||||||
return nil
|
return nil
|
||||||
|
@ -109,7 +111,6 @@ func (s *subdomainRedirectWrapper) Wrapper(w http.ResponseWriter, r *http.Reques
|
||||||
// because older browsers may not be able to recognise that status code (the RFC 7538, is not so old)
|
// because older browsers may not be able to recognise that status code (the RFC 7538, is not so old)
|
||||||
// although note that move is not the same thing as redirect: move reminds a specific address or location moved while
|
// although note that move is not the same thing as redirect: move reminds a specific address or location moved while
|
||||||
// redirect is a new location.
|
// redirect is a new location.
|
||||||
|
|
||||||
host := context.GetHost(r)
|
host := context.GetHost(r)
|
||||||
root := s.root()
|
root := s.root()
|
||||||
if loopback := netutil.GetLoopbackSubdomain(root); loopback != "" {
|
if loopback := netutil.GetLoopbackSubdomain(root); loopback != "" {
|
||||||
|
@ -117,7 +118,6 @@ func (s *subdomainRedirectWrapper) Wrapper(w http.ResponseWriter, r *http.Reques
|
||||||
}
|
}
|
||||||
|
|
||||||
hasSubdomain := host != root
|
hasSubdomain := host != root
|
||||||
|
|
||||||
if !hasSubdomain && !s.isFromRoot {
|
if !hasSubdomain && !s.isFromRoot {
|
||||||
// if the current endpoint is not a subdomain
|
// if the current endpoint is not a subdomain
|
||||||
// and the redirect is not configured to be used from root domain to a subdomain.
|
// and the redirect is not configured to be used from root domain to a subdomain.
|
||||||
|
@ -142,14 +142,25 @@ func (s *subdomainRedirectWrapper) Wrapper(w http.ResponseWriter, r *http.Reques
|
||||||
resturi := r.URL.RequestURI()
|
resturi := r.URL.RequestURI()
|
||||||
if s.isToRoot {
|
if s.isToRoot {
|
||||||
// from a specific subdomain or any subdomain to the root domain.
|
// from a specific subdomain or any subdomain to the root domain.
|
||||||
http.Redirect(w, r, getFullScheme(r)+root+resturi, http.StatusMovedPermanently)
|
redirectAbsolute(w, r, getFullScheme(r)+root+resturi, http.StatusMovedPermanently)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// from a specific subdomain or any subdomain to a specific subdomain.
|
// from a specific subdomain or any subdomain to a specific subdomain.
|
||||||
http.Redirect(w, r, getFullScheme(r)+s.to+root+resturi, http.StatusMovedPermanently)
|
redirectAbsolute(w, r, getFullScheme(r)+s.to+root+resturi, http.StatusMovedPermanently)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.isFromRoot && !s.isFromAny {
|
||||||
|
// Then we must not continue,
|
||||||
|
// the subdomain didn't match the "to" but the from
|
||||||
|
// was the application root itself, which is not a wildcard
|
||||||
|
// so it shouldn't accept any subdomain, we must fire 404 here.
|
||||||
|
// Something like:
|
||||||
|
// http://registered_host_but_not_in_app.your.mydomain.com
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
// the from subdomain is not matched and it's not from root.
|
// the from subdomain is not matched and it's not from root.
|
||||||
router(w, r)
|
router(w, r)
|
||||||
return
|
return
|
||||||
|
@ -159,9 +170,30 @@ func (s *subdomainRedirectWrapper) Wrapper(w http.ResponseWriter, r *http.Reques
|
||||||
resturi := r.URL.RequestURI()
|
resturi := r.URL.RequestURI()
|
||||||
// we are not inside a subdomain, so we are in the root domain
|
// we are not inside a subdomain, so we are in the root domain
|
||||||
// and the redirect is configured to be used from root domain to a subdomain.
|
// and the redirect is configured to be used from root domain to a subdomain.
|
||||||
http.Redirect(w, r, getFullScheme(r)+s.to+root+resturi, http.StatusMovedPermanently)
|
redirectAbsolute(w, r, getFullScheme(r)+s.to+root+resturi, http.StatusMovedPermanently)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
router(w, r)
|
router(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func redirectAbsolute(w http.ResponseWriter, r *http.Request, url string, code int) {
|
||||||
|
h := w.Header()
|
||||||
|
|
||||||
|
// RFC 7231 notes that a short HTML body is usually included in
|
||||||
|
// the response because older user agents may not understand 301/307.
|
||||||
|
// Do it only if the request didn't already have a Content-Type header.
|
||||||
|
_, hadCT := h[context.ContentTypeHeaderKey]
|
||||||
|
|
||||||
|
h.Set("Location", url)
|
||||||
|
if !hadCT && (r.Method == http.MethodGet || r.Method == http.MethodHead) {
|
||||||
|
h.Set(context.ContentTypeHeaderKey, "text/html; charset=utf-8")
|
||||||
|
}
|
||||||
|
w.WriteHeader(code)
|
||||||
|
|
||||||
|
// Shouldn't send the body for POST or HEAD; that leaves GET.
|
||||||
|
if !hadCT && r.Method == "GET" {
|
||||||
|
body := "<a href=\"" + template.HTMLEscapeString(url) + "\">" + http.StatusText(code) + "</a>.\n"
|
||||||
|
fmt.Fprintln(w, body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package router_test
|
package router_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/kataras/iris/v12"
|
"github.com/kataras/iris/v12"
|
||||||
"github.com/kataras/iris/v12/context"
|
"github.com/kataras/iris/v12/context"
|
||||||
|
"github.com/kataras/iris/v12/core/router"
|
||||||
"github.com/kataras/iris/v12/httptest"
|
"github.com/kataras/iris/v12/httptest"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -72,3 +74,88 @@ func TestLowercaseRouting(t *testing.T) {
|
||||||
e.GET(strings.ToUpper(tt)).Expect().Status(httptest.StatusOK).Body().Equal(s)
|
e.GET(strings.ToUpper(tt)).Expect().Status(httptest.StatusOK).Body().Equal(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRouterWrapperOrder(t *testing.T) {
|
||||||
|
// last is wrapping the previous.
|
||||||
|
|
||||||
|
// first is executed last.
|
||||||
|
userWrappers := []router.WrapperFunc{
|
||||||
|
func(w http.ResponseWriter, r *http.Request, main http.HandlerFunc) {
|
||||||
|
io.WriteString(w, "6")
|
||||||
|
main(w, r)
|
||||||
|
},
|
||||||
|
func(w http.ResponseWriter, r *http.Request, main http.HandlerFunc) {
|
||||||
|
io.WriteString(w, "5")
|
||||||
|
main(w, r)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// should be executed before userWrappers.
|
||||||
|
redirectionWrappers := []router.WrapperFunc{
|
||||||
|
func(w http.ResponseWriter, r *http.Request, main http.HandlerFunc) {
|
||||||
|
io.WriteString(w, "3")
|
||||||
|
main(w, r)
|
||||||
|
},
|
||||||
|
func(w http.ResponseWriter, r *http.Request, main http.HandlerFunc) {
|
||||||
|
io.WriteString(w, "4")
|
||||||
|
main(w, r)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// should be executed before redirectionWrappers.
|
||||||
|
afterRedirectionWrappers := []router.WrapperFunc{
|
||||||
|
func(w http.ResponseWriter, r *http.Request, main http.HandlerFunc) {
|
||||||
|
io.WriteString(w, "2")
|
||||||
|
main(w, r)
|
||||||
|
},
|
||||||
|
func(w http.ResponseWriter, r *http.Request, main http.HandlerFunc) {
|
||||||
|
io.WriteString(w, "1")
|
||||||
|
main(w, r)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
testOrder1 := iris.New()
|
||||||
|
for _, w := range userWrappers {
|
||||||
|
testOrder1.WrapRouter(w)
|
||||||
|
// this always wraps the previous one, but it's not accessible after Build state,
|
||||||
|
// the below are simulating the SubdomainRedirect and ForceLowercaseRouting.
|
||||||
|
}
|
||||||
|
for _, w := range redirectionWrappers {
|
||||||
|
testOrder1.AddRouterWrapper(w)
|
||||||
|
}
|
||||||
|
for _, w := range afterRedirectionWrappers {
|
||||||
|
testOrder1.PrependRouterWrapper(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
testOrder2 := iris.New()
|
||||||
|
for _, w := range redirectionWrappers {
|
||||||
|
testOrder2.AddRouterWrapper(w)
|
||||||
|
}
|
||||||
|
for _, w := range userWrappers {
|
||||||
|
testOrder2.WrapRouter(w)
|
||||||
|
}
|
||||||
|
for _, w := range afterRedirectionWrappers {
|
||||||
|
testOrder2.PrependRouterWrapper(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
testOrder3 := iris.New()
|
||||||
|
for _, w := range redirectionWrappers {
|
||||||
|
testOrder3.AddRouterWrapper(w)
|
||||||
|
}
|
||||||
|
for _, w := range afterRedirectionWrappers {
|
||||||
|
testOrder3.PrependRouterWrapper(w)
|
||||||
|
}
|
||||||
|
for _, w := range userWrappers {
|
||||||
|
testOrder3.WrapRouter(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
appTests := []*iris.Application{
|
||||||
|
testOrder1, testOrder2, testOrder3,
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedOrderStr := "123456"
|
||||||
|
for _, app := range appTests {
|
||||||
|
app.Get("/", func(ctx iris.Context) {}) // to not append the not found one.
|
||||||
|
|
||||||
|
e := httptest.New(t, app)
|
||||||
|
e.GET("/").Expect().Status(iris.StatusOK).Body().Equal(expectedOrderStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -406,7 +406,7 @@ func (i *I18n) GetMessage(ctx *context.Context, format string, args ...interface
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper returns a new router wrapper.
|
// Wrapper returns a new router wrapper.
|
||||||
// The result function can be passed on `Application.WrapRouter`.
|
// The result function can be passed on `Application.WrapRouter/AddRouterWrapper`.
|
||||||
// It compares the path prefix for translated language and
|
// It compares the path prefix for translated language and
|
||||||
// local redirects the requested path with the selected (from the path) language to the router.
|
// local redirects the requested path with the selected (from the path) language to the router.
|
||||||
//
|
//
|
||||||
|
@ -417,7 +417,10 @@ func (i *I18n) Wrapper() router.WrapperFunc {
|
||||||
}
|
}
|
||||||
return func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
return func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
||||||
found := false
|
found := false
|
||||||
path := r.URL.Path[1:]
|
path := r.URL.Path
|
||||||
|
if len(path) > 0 && path[0] == '/' {
|
||||||
|
path = path[1:]
|
||||||
|
}
|
||||||
|
|
||||||
if idx := strings.IndexByte(path, '/'); idx > 0 {
|
if idx := strings.IndexByte(path, '/'); idx > 0 {
|
||||||
path = path[:idx]
|
path = path[:idx]
|
||||||
|
@ -451,7 +454,6 @@ func (i *I18n) Wrapper() router.WrapperFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next(w, r)
|
next(w, r)
|
||||||
|
|
|
@ -172,6 +172,21 @@ func (l MemoryLocalizer) GetLocale(index int) context.Locale {
|
||||||
// panic(fmt.Sprintf("locale of index [%d] not found", index))
|
// panic(fmt.Sprintf("locale of index [%d] not found", index))
|
||||||
// }
|
// }
|
||||||
// return loc
|
// return loc
|
||||||
|
/* Note(@kataras): the following is allowed as a language index can be higher
|
||||||
|
than the length of the locale files.
|
||||||
|
if index >= len(l) || index < 0 {
|
||||||
|
// 1. language exists in the caller but was not found in files.
|
||||||
|
// 2. language exists in both files and caller but the actual
|
||||||
|
// languages are two, while the registered are 4 (when missing files),
|
||||||
|
// that happens when Strict option is false.
|
||||||
|
// force to the default language but what is the default language if the language index is greater than this length?
|
||||||
|
// That's why it's allowed.
|
||||||
|
index = 0
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if index < 0 {
|
||||||
|
index = 0
|
||||||
|
}
|
||||||
|
|
||||||
return l[index]
|
return l[index]
|
||||||
}
|
}
|
||||||
|
|
12
iris.go
12
iris.go
|
@ -162,9 +162,7 @@ func (app *Application) WWW() router.Party {
|
||||||
// Example: https://github.com/kataras/iris/tree/master/_examples/routing/subdomains/redirect
|
// Example: https://github.com/kataras/iris/tree/master/_examples/routing/subdomains/redirect
|
||||||
func (app *Application) SubdomainRedirect(from, to router.Party) router.Party {
|
func (app *Application) SubdomainRedirect(from, to router.Party) router.Party {
|
||||||
sd := router.NewSubdomainRedirectWrapper(app.ConfigurationReadOnly().GetVHost, from.GetRelPath(), to.GetRelPath())
|
sd := router.NewSubdomainRedirectWrapper(app.ConfigurationReadOnly().GetVHost, from.GetRelPath(), to.GetRelPath())
|
||||||
// TODO: add a debug message here or wait for a response from the issuer
|
app.Router.AddRouterWrapper(sd)
|
||||||
// so we can force these to run on build state (last registered, first executed).
|
|
||||||
app.Router.WrapRouter(sd)
|
|
||||||
return to
|
return to
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,6 +487,7 @@ func (app *Application) Build() error {
|
||||||
if app.builded {
|
if app.builded {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// start := time.Now()
|
// start := time.Now()
|
||||||
app.builded = true // even if fails.
|
app.builded = true // even if fails.
|
||||||
|
|
||||||
|
@ -532,7 +531,7 @@ func (app *Application) Build() error {
|
||||||
if app.I18n.Loaded() {
|
if app.I18n.Loaded() {
|
||||||
// {{ tr "lang" "key" arg1 arg2 }}
|
// {{ tr "lang" "key" arg1 arg2 }}
|
||||||
app.view.AddFunc("tr", app.I18n.Tr)
|
app.view.AddFunc("tr", app.I18n.Tr)
|
||||||
app.Router.WrapRouter(app.I18n.Wrapper())
|
app.Router.AddRouterWrapper(app.I18n.Wrapper())
|
||||||
}
|
}
|
||||||
|
|
||||||
if n := app.view.Len(); n > 0 {
|
if n := app.view.Len(); n > 0 {
|
||||||
|
@ -560,7 +559,10 @@ func (app *Application) Build() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if app.config.ForceLowercaseRouting {
|
if app.config.ForceLowercaseRouting {
|
||||||
app.Router.WrapRouter(func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
// This should always be executed first.
|
||||||
|
app.Router.PrependRouterWrapper(func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
||||||
|
r.Host = strings.ToLower(r.Host)
|
||||||
|
r.URL.Host = strings.ToLower(r.URL.Host)
|
||||||
r.URL.Path = strings.ToLower(r.URL.Path)
|
r.URL.Path = strings.ToLower(r.URL.Path)
|
||||||
next(w, r)
|
next(w, r)
|
||||||
})
|
})
|
||||||
|
|
|
@ -18,7 +18,7 @@ type (
|
||||||
// Config is the configuration for sessions. Please read it before using sessions.
|
// Config is the configuration for sessions. Please read it before using sessions.
|
||||||
Config struct {
|
Config struct {
|
||||||
// Logger instance for sessions usage, e.g. { Logger: app.Logger() }.
|
// Logger instance for sessions usage, e.g. { Logger: app.Logger() }.
|
||||||
// Defauls to a child of "sessions" of the latest Iris Application's main Logger.
|
// Defaults to a child of "sessions" of the latest Iris Application's main Logger.
|
||||||
Logger *golog.Logger
|
Logger *golog.Logger
|
||||||
// Cookie string, the session's client cookie name, for example: "mysessionid"
|
// Cookie string, the session's client cookie name, for example: "mysessionid"
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue
Block a user