mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 15:30:36 +01:00
asthetics
Former-commit-id: 1b13823e4e31327dad280a82252be969f845efe8
This commit is contained in:
parent
05ae7792df
commit
07f678eac0
|
@ -258,6 +258,19 @@ func splitSubdomainAndPath(fullUnparsedPath string) (subdomain string, path stri
|
||||||
return // return subdomain without slash, path with slash
|
return // return subdomain without slash, path with slash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func staticPath(src string) string {
|
||||||
|
bidx := strings.IndexByte(src, '{')
|
||||||
|
if bidx == -1 || len(src) <= bidx {
|
||||||
|
return src // no dynamic part found
|
||||||
|
}
|
||||||
|
if bidx <= 1 { // found at first{...} or second index (/{...}),
|
||||||
|
// although first index should never happen because of the prepended slash.
|
||||||
|
return "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
return src[:bidx-1] // (/static/{...} -> /static)
|
||||||
|
}
|
||||||
|
|
||||||
// RoutePathReverserOption option signature for the RoutePathReverser.
|
// RoutePathReverserOption option signature for the RoutePathReverser.
|
||||||
type RoutePathReverserOption func(*RoutePathReverser)
|
type RoutePathReverserOption func(*RoutePathReverser)
|
||||||
|
|
||||||
|
|
|
@ -325,16 +325,7 @@ func (r *Route) IsStatic() bool {
|
||||||
// if /assets/{filepath:path} it will return /assets.
|
// if /assets/{filepath:path} it will return /assets.
|
||||||
func (r *Route) StaticPath() string {
|
func (r *Route) StaticPath() string {
|
||||||
src := r.tmpl.Src
|
src := r.tmpl.Src
|
||||||
bidx := strings.IndexByte(src, '{')
|
return staticPath(src)
|
||||||
if bidx == -1 || len(src) <= bidx {
|
|
||||||
return src // no dynamic part found
|
|
||||||
}
|
|
||||||
if bidx <= 1 { // found at first{...} or second index (/{...}),
|
|
||||||
// although first index should never happen because of the prepended slash.
|
|
||||||
return "/"
|
|
||||||
}
|
|
||||||
|
|
||||||
return src[:bidx-1] // (/static/{...} -> /static)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResolvePath returns the formatted path's %v replaced with the args.
|
// ResolvePath returns the formatted path's %v replaced with the args.
|
||||||
|
|
|
@ -21,7 +21,7 @@ type Router struct {
|
||||||
// not indeed but we don't to risk its usage by third-parties.
|
// not indeed but we don't to risk its usage by third-parties.
|
||||||
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 func(http.ResponseWriter, *http.Request, http.HandlerFunc)
|
wrapperFunc WrapperFunc
|
||||||
|
|
||||||
cPool *context.Pool // used on RefreshRouter
|
cPool *context.Pool // used on RefreshRouter
|
||||||
routesProvider RoutesProvider
|
routesProvider RoutesProvider
|
||||||
|
@ -139,7 +139,7 @@ func (router *Router) BuildRouter(cPool *context.Pool, requestHandler RequestHan
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
// build closest.
|
// build closest.
|
||||||
|
@ -180,12 +180,6 @@ func (router *Router) Downgraded() bool {
|
||||||
return router.mainHandler != nil && router.requestHandler == nil
|
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.
|
// WrapRouter adds a wrapper on the top of the main router.
|
||||||
// Usually it's useful for third-party middleware
|
// Usually it's useful for third-party middleware
|
||||||
// when need to wrap the entire application with a middleware like CORS.
|
// when need to wrap the entire application with a middleware like CORS.
|
||||||
|
@ -196,28 +190,7 @@ type WrapperFunc func(w http.ResponseWriter, r *http.Request, firstNextIsTheRout
|
||||||
//
|
//
|
||||||
// Before build.
|
// Before build.
|
||||||
func (router *Router) WrapRouter(wrapperFunc WrapperFunc) {
|
func (router *Router) WrapRouter(wrapperFunc WrapperFunc) {
|
||||||
if wrapperFunc == nil {
|
router.wrapperFunc = makeWrapperFunc(router.wrapperFunc, wrapperFunc)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
router.mu.Lock()
|
|
||||||
defer router.mu.Unlock()
|
|
||||||
|
|
||||||
if router.wrapperFunc != nil {
|
|
||||||
// wrap into one function, from bottom to top, end to begin.
|
|
||||||
nextWrapper := wrapperFunc
|
|
||||||
prevWrapper := router.wrapperFunc
|
|
||||||
wrapperFunc = func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
|
||||||
if next != nil {
|
|
||||||
nexthttpFunc := http.HandlerFunc(func(_w http.ResponseWriter, _r *http.Request) {
|
|
||||||
prevWrapper(_w, _r, next)
|
|
||||||
})
|
|
||||||
nextWrapper(w, r, nexthttpFunc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
router.wrapperFunc = wrapperFunc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -234,24 +207,3 @@ func (router *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
func (router *Router) RouteExists(ctx context.Context, method, path string) bool {
|
func (router *Router) RouteExists(ctx context.Context, method, path string) bool {
|
||||||
return router.requestHandler.RouteExists(ctx, method, path)
|
return router.requestHandler.RouteExists(ctx, method, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
type wrapper struct {
|
|
||||||
router http.HandlerFunc // http.HandlerFunc to catch the CURRENT state of its .ServeHTTP on case of future change.
|
|
||||||
wrapperFunc func(http.ResponseWriter, *http.Request, http.HandlerFunc)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewWrapper returns a new http.Handler wrapped by the 'wrapperFunc'
|
|
||||||
// the "next" is the final "wrapped" input parameter.
|
|
||||||
//
|
|
||||||
// Application is responsible to make it to work on more than one wrappers
|
|
||||||
// via composition or func clojure.
|
|
||||||
func NewWrapper(wrapperFunc func(w http.ResponseWriter, r *http.Request, routerNext http.HandlerFunc), wrapped http.HandlerFunc) http.Handler {
|
|
||||||
return &wrapper{
|
|
||||||
wrapperFunc: wrapperFunc,
|
|
||||||
router: wrapped,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wr *wrapper) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
||||||
wr.wrapperFunc(w, r, wr.router)
|
|
||||||
}
|
|
||||||
|
|
52
core/router/router_wrapper.go
Normal file
52
core/router/router_wrapper.go
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
package router
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
// 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, router http.HandlerFunc)
|
||||||
|
|
||||||
|
func makeWrapperFunc(original WrapperFunc, wrapperFunc WrapperFunc) WrapperFunc {
|
||||||
|
if wrapperFunc == nil {
|
||||||
|
return original
|
||||||
|
}
|
||||||
|
|
||||||
|
if original != nil {
|
||||||
|
// wrap into one function, from bottom to top, end to begin.
|
||||||
|
nextWrapper := wrapperFunc
|
||||||
|
prevWrapper := original
|
||||||
|
wrapperFunc = func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
||||||
|
if next != nil {
|
||||||
|
nexthttpFunc := http.HandlerFunc(func(_w http.ResponseWriter, _r *http.Request) {
|
||||||
|
prevWrapper(_w, _r, next)
|
||||||
|
})
|
||||||
|
nextWrapper(w, r, nexthttpFunc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return wrapperFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
type wrapper struct {
|
||||||
|
router http.HandlerFunc // http.HandlerFunc to catch the CURRENT state of its .ServeHTTP on case of future change.
|
||||||
|
wrapperFunc WrapperFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
// newWrapper returns a new http.Handler wrapped by the 'wrapperFunc'
|
||||||
|
// the "next" is the final "wrapped" input parameter.
|
||||||
|
//
|
||||||
|
// Application is responsible to make it to work on more than one wrappers
|
||||||
|
// via composition or func clojure.
|
||||||
|
func newWrapper(wrapperFunc WrapperFunc, wrapped http.HandlerFunc) http.Handler {
|
||||||
|
return &wrapper{
|
||||||
|
wrapperFunc: wrapperFunc,
|
||||||
|
router: wrapped,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wr *wrapper) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
wr.wrapperFunc(w, r, wr.router)
|
||||||
|
}
|
51
core/router/router_wrapper_test.go
Normal file
51
core/router/router_wrapper_test.go
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMakeWrapperFunc(t *testing.T) {
|
||||||
|
var (
|
||||||
|
firstBody = []byte("1")
|
||||||
|
secondBody = []byte("2")
|
||||||
|
mainBody = []byte("3")
|
||||||
|
expectedBody = append(firstBody, append(secondBody, mainBody...)...)
|
||||||
|
)
|
||||||
|
|
||||||
|
pre := func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
||||||
|
w.Header().Set("X-Custom", "data")
|
||||||
|
next(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
first := func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
||||||
|
w.Write(firstBody)
|
||||||
|
next(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
second := func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
||||||
|
w.Write(secondBody)
|
||||||
|
next(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
mainHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write(mainBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper := makeWrapperFunc(second, first)
|
||||||
|
wrapper = makeWrapperFunc(wrapper, pre)
|
||||||
|
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
r := httptest.NewRequest("GET", "https://iris-go.com", nil)
|
||||||
|
wrapper(w, r, mainHandler)
|
||||||
|
|
||||||
|
if got := w.Body.Bytes(); !bytes.Equal(expectedBody, got) {
|
||||||
|
t.Fatalf("expected boy: %s but got: %s", string(expectedBody), string(got))
|
||||||
|
}
|
||||||
|
|
||||||
|
if expected, got := "data", w.Header().Get("X-Custom"); expected != got {
|
||||||
|
t.Fatalf("expected x-custom header: %s but got: %s", expected, got)
|
||||||
|
}
|
||||||
|
}
|
14
iris.go
14
iris.go
|
@ -248,7 +248,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())
|
||||||
app.WrapRouter(sd)
|
app.Router.WrapRouter(sd)
|
||||||
return to
|
return to
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,13 +392,13 @@ func (app *Application) RegisterView(viewEngine view.Engine) {
|
||||||
func (app *Application) View(writer io.Writer, filename string, layout string, bindingData interface{}) error {
|
func (app *Application) View(writer io.Writer, filename string, layout string, bindingData interface{}) error {
|
||||||
if app.view.Len() == 0 {
|
if app.view.Len() == 0 {
|
||||||
err := errors.New("view engine is missing, use `RegisterView`")
|
err := errors.New("view engine is missing, use `RegisterView`")
|
||||||
app.Logger().Error(err)
|
app.logger.Error(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err := app.view.ExecuteWriter(writer, filename, layout, bindingData)
|
err := app.view.ExecuteWriter(writer, filename, layout, bindingData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
app.Logger().Error(err)
|
app.logger.Error(err)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1103,7 +1103,7 @@ func (app *Application) Run(serve Runner, withOrWithout ...Configurator) error {
|
||||||
// this will block until an error(unless supervisor's DeferFlow called from a Task).
|
// this will block until an error(unless supervisor's DeferFlow called from a Task).
|
||||||
err := serve(app)
|
err := serve(app)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
app.Logger().Error(err)
|
app.logger.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
@ -1179,7 +1179,7 @@ func (app *Application) tryInjectLiveReload() error {
|
||||||
|
|
||||||
bodyCloseTag := []byte("</body>")
|
bodyCloseTag := []byte("</body>")
|
||||||
|
|
||||||
app.WrapRouter(func(w http.ResponseWriter, r *http.Request, _ http.HandlerFunc) {
|
app.Router.WrapRouter(func(w http.ResponseWriter, r *http.Request, _ http.HandlerFunc) {
|
||||||
ctx := app.ContextPool.Acquire(w, r)
|
ctx := app.ContextPool.Acquire(w, r)
|
||||||
rec := ctx.Recorder() // Record everything and write all in once at the Context release.
|
rec := ctx.Recorder() // Record everything and write all in once at the Context release.
|
||||||
app.ServeHTTPC(ctx) // We directly call request handler with Context.
|
app.ServeHTTPC(ctx) // We directly call request handler with Context.
|
||||||
|
@ -1234,7 +1234,7 @@ func (app *Application) tryStartTunneling() {
|
||||||
var publicAddr string
|
var publicAddr string
|
||||||
err := tc.startTunnel(t, &publicAddr)
|
err := tc.startTunnel(t, &publicAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
app.Logger().Errorf("Host: tunneling error: %v", err)
|
app.logger.Errorf("Host: tunneling error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1242,7 +1242,7 @@ func (app *Application) tryStartTunneling() {
|
||||||
app.config.vhost = publicAddr[strings.Index(publicAddr, "://")+3:]
|
app.config.vhost = publicAddr[strings.Index(publicAddr, "://")+3:]
|
||||||
|
|
||||||
directLog := []byte(fmt.Sprintf("• Public Address: %s\n", publicAddr))
|
directLog := []byte(fmt.Sprintf("• Public Address: %s\n", publicAddr))
|
||||||
app.Logger().Printer.Write(directLog)
|
app.logger.Printer.Write(directLog)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue
Block a user