update Blocks module

This commit is contained in:
Gerasimos (Makis) Maropoulos 2023-09-24 17:35:49 +03:00
parent e0ac28c1bb
commit e7b40398aa
No known key found for this signature in database
GPG Key ID: B9839E9CD30B7B6B
16 changed files with 198 additions and 105 deletions

View File

@ -8,6 +8,7 @@ func main() {
// Note, in Blocks engine, layouts
// are used by their base names, the
// blocks.LayoutDir(layoutDir) defaults to "./layouts".
// .Blocks(...).Layout("main") for default layout for all views, it can be modified through ctx.ViewLayout though.
app.Get("/", index)

View File

@ -1,8 +1,3 @@
<!-- You can define more than one block.
The default one is "content" which should be the main template's body.
So, even if it's missing (see index.html), it's added automatically by the view engine.
When you need to define more than one block, you have to be more specific:
-->
{{ define "content" }}
<h1>Internal Server Error</h1>
{{ end }}

View File

@ -6,8 +6,8 @@
<title>{{.Code}}</title>
</head>
<body>
{{ template "content" .}}
{{ template "content" . }}
{{block "message" .}}{{end}}
{{ block "message" . }}Default Error Message{{ end }}
</body>
</html>

View File

@ -0,0 +1,38 @@
package main
import "github.com/kataras/iris/v12"
// Based on https://github.com/kataras/iris/issues/2214.
func main() {
app := initApp()
app.Listen(":8080")
}
func initApp() *iris.Application {
app := iris.New()
app.Logger().SetLevel("debug")
tmpl := iris.Blocks("./src/public/html", ".html")
tmpl.Layout("main")
app.RegisterView(tmpl)
app.Get("/list", func(ctx iris.Context) {
ctx.View("files/list")
})
app.Get("/menu", func(ctx iris.Context) {
ctx.View("menu/menu")
})
app.Get("/list2", func(ctx iris.Context) {
ctx.ViewLayout("secondary")
ctx.View("files/list")
})
app.Get("/menu2", func(ctx iris.Context) {
ctx.ViewLayout("secondary")
ctx.View("menu/menu")
})
return app
}

View File

@ -0,0 +1,7 @@
{{ define "title"}}
<title>222</title>
{{ end }}
{{ define "content" }}
<h1>List Content</h1>
{{ end }}

View File

@ -0,0 +1,8 @@
<html>
<head>
{{ block "title" .}}<title>Main Default Title</title>{{end}}
</head>
<body>
{{ block "content" .}}<h1>Main Default Content</h1>{{end}}
</body>
</html>

View File

@ -0,0 +1,9 @@
<html>
<head>
{{ block "title" .}}<title>Secondary Default Title</title>{{end}}
</head>
<body>
<h1>Secondary Layout</h1>
{{ block "content" .}}<h1>Secondary Default Content</h1>{{end}}
</body>
</html>

View File

@ -0,0 +1,3 @@
{{ define "title" }} <title>111</title>{{ end }}
{{ define "content" }}<h1>Menu Content</h1>{{ end }}

View File

@ -336,18 +336,18 @@ func ConfigureMiddleware(handlers ...Handler) router.PartyConfigurator {
return &partyConfiguratorMiddleware{handlers: handlers}
}
var (
// Compression is a middleware which enables
// writing and reading using the best offered compression.
// Usage:
// app.Use (for matched routes)
// app.UseRouter (for both matched and 404s or other HTTP errors).
Compression = func(ctx Context) {
ctx.CompressWriter(true)
ctx.CompressReader(true)
ctx.Next()
}
// Compression is a middleware which enables
// writing and reading using the best offered compression.
// Usage:
// app.Use (for matched routes)
// app.UseRouter (for both matched and 404s or other HTTP errors).
func Compression(ctx Context) {
ctx.CompressWriter(true)
ctx.CompressReader(true)
ctx.Next()
}
var (
// AllowQuerySemicolons returns a middleware that serves requests by converting any
// unescaped semicolons(;) in the URL query to ampersands(&).
//

View File

@ -754,6 +754,13 @@ func (api *APIBuilder) createRoutes(errorCode int, methods []string, relativePat
mainHandlerFileName, mainHandlerFileNumber := context.HandlerFileLineRel(handlers[mainHandlerIndex])
// TODO: think of it.
if mainHandlerFileName == "<autogenerated>" {
// At PartyConfigure, 2nd+ level of routes it will get <autogenerated> but in reallity will be the same as the caller.
mainHandlerFileName = filename
mainHandlerFileNumber = line
}
// re-calculate mainHandlerIndex in favor of the middlewares.
mainHandlerIndex = len(beginHandlers) + mainHandlerIndex

View File

@ -2,13 +2,11 @@ package router
import (
"errors"
"fmt"
"net/http"
"sort"
"strings"
"sync"
"sync/atomic"
"time"
"github.com/kataras/iris/v12/context"
"github.com/kataras/iris/v12/core/errgroup"
@ -16,7 +14,6 @@ import (
macroHandler "github.com/kataras/iris/v12/macro/handler"
"github.com/kataras/golog"
"github.com/kataras/pio"
)
type (
@ -371,87 +368,7 @@ func (h *routerHandler) Build(provider RoutesProvider) error {
}
}
// TODO: move this and make it easier to read when all cases are, visually, tested.
if logger := h.logger; logger != nil && logger.Level == golog.DebugLevel && noLogCount < len(registeredRoutes) {
// group routes by method and print them without the [DBUG] and time info,
// the route logs are colorful.
// Note: don't use map, we need to keep registered order, use
// different slices for each method.
collect := func(method string) (methodRoutes []*Route) {
for _, r := range registeredRoutes {
if r.NoLog {
continue
}
if r.Method == method {
methodRoutes = append(methodRoutes, r)
}
}
return
}
type MethodRoutes struct {
method string
routes []*Route
}
allMethods := append(AllMethods, []string{MethodNone, ""}...)
methodRoutes := make([]MethodRoutes, 0, len(allMethods))
for _, method := range allMethods {
routes := collect(method)
if len(routes) > 0 {
methodRoutes = append(methodRoutes, MethodRoutes{method, routes})
}
}
if n := len(methodRoutes); n > 0 {
tr := "routes"
if len(registeredRoutes) == 1 {
tr = tr[0 : len(tr)-1]
}
bckpNewLine := logger.NewLine
logger.NewLine = false
debugLevel := golog.Levels[golog.DebugLevel]
// Replace that in order to not transfer it to the log handler (e.g. json)
// logger.Debugf("API: %d registered %s (", len(registeredRoutes), tr)
// with:
pio.WriteRich(logger.Printer, debugLevel.Title, debugLevel.ColorCode, debugLevel.Style...)
fmt.Fprintf(logger.Printer, " %s %sAPI: %d registered %s (", time.Now().Format(logger.TimeFormat), logger.Prefix, len(registeredRoutes)-noLogCount, tr)
//
logger.NewLine = bckpNewLine
for i, m := range methodRoutes {
// @method: @count
if i > 0 {
if i == n-1 {
fmt.Fprint(logger.Printer, " and ")
} else {
fmt.Fprint(logger.Printer, ", ")
}
}
if m.method == "" {
m.method = "ERROR"
}
fmt.Fprintf(logger.Printer, "%d ", len(m.routes))
pio.WriteRich(logger.Printer, m.method, TraceTitleColorCode(m.method))
}
fmt.Fprint(logger.Printer, ")\n")
}
for i, m := range methodRoutes {
for _, r := range m.routes {
r.Trace(logger.Printer, -1)
}
if i != len(allMethods)-1 {
logger.Printer.Write(pio.NewLine)
}
}
}
printRoutesInfo(h.logger, registeredRoutes, noLogCount)
return errgroup.Check(rp)
}

View File

@ -0,0 +1,94 @@
package router
import (
"fmt"
"time"
"github.com/kataras/golog"
"github.com/kataras/pio"
)
func printRoutesInfo(logger *golog.Logger, registeredRoutes []*Route, noLogCount int) {
if !(logger != nil && logger.Level == golog.DebugLevel && noLogCount < len(registeredRoutes)) {
return
}
// group routes by method and print them without the [DBUG] and time info,
// the route logs are colorful.
// Note: don't use map, we need to keep registered order, use
// different slices for each method.
collect := func(method string) (methodRoutes []*Route) {
for _, r := range registeredRoutes {
if r.NoLog {
continue
}
if r.Method == method {
methodRoutes = append(methodRoutes, r)
}
}
return
}
type MethodRoutes struct {
method string
routes []*Route
}
allMethods := append(AllMethods, []string{MethodNone, ""}...)
methodRoutes := make([]MethodRoutes, 0, len(allMethods))
for _, method := range allMethods {
routes := collect(method)
if len(routes) > 0 {
methodRoutes = append(methodRoutes, MethodRoutes{method, routes})
}
}
if n := len(methodRoutes); n > 0 {
tr := "routes"
if len(registeredRoutes) == 1 {
tr = tr[0 : len(tr)-1]
}
bckpNewLine := logger.NewLine
logger.NewLine = false
debugLevel := golog.Levels[golog.DebugLevel]
// Replace that in order to not transfer it to the log handler (e.g. json)
// logger.Debugf("API: %d registered %s (", len(registeredRoutes), tr)
// with:
pio.WriteRich(logger.Printer, debugLevel.Title, debugLevel.ColorCode, debugLevel.Style...)
fmt.Fprintf(logger.Printer, " %s %sAPI: %d registered %s (", time.Now().Format(logger.TimeFormat), logger.Prefix, len(registeredRoutes)-noLogCount, tr)
//
logger.NewLine = bckpNewLine
for i, m := range methodRoutes {
// @method: @count
if i > 0 {
if i == n-1 {
fmt.Fprint(logger.Printer, " and ")
} else {
fmt.Fprint(logger.Printer, ", ")
}
}
if m.method == "" {
m.method = "ERROR"
}
fmt.Fprintf(logger.Printer, "%d ", len(m.routes))
pio.WriteRich(logger.Printer, m.method, TraceTitleColorCode(m.method))
}
fmt.Fprint(logger.Printer, ")\n")
}
for i, m := range methodRoutes {
for _, r := range m.routes {
r.Trace(logger.Printer, -1)
}
if i != len(allMethods)-1 {
logger.Printer.Write(pio.NewLine)
}
}
}

View File

@ -562,6 +562,14 @@ func (r *Route) Trace(w io.Writer, stoppedIndex int) {
file, line = context.HandlerFileLineRel(h)
// If a middleware, e.g (macro) which changes the main handler index,
// skip it.
// TODO: think of it.
if file == "<autogenerated>" {
// At PartyConfigure, 2nd+ level of routes it will get <autogenerated> but in reallity will be the same as the caller.
file = r.RegisterFileName
line = r.RegisterLineNumber
}
if file == r.SourceFileName && line == r.SourceLineNumber {
continue
}

3
go.mod
View File

@ -21,7 +21,7 @@ require (
github.com/iris-contrib/httpexpect/v2 v2.15.2
github.com/iris-contrib/schema v0.0.6
github.com/json-iterator/go v1.1.12
github.com/kataras/blocks v0.0.7
github.com/kataras/blocks v0.0.8
github.com/kataras/golog v0.1.9
github.com/kataras/jwt v0.1.10
github.com/kataras/neffos v0.0.22
@ -107,6 +107,7 @@ require (
github.com/yudai/gojsondiff v1.0.0 // indirect
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
moul.io/http2curl/v2 v2.3.0 // indirect
)

6
go.sum generated
View File

@ -105,8 +105,8 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kataras/blocks v0.0.7 h1:cF3RDY/vxnSRezc7vLFlQFTYXG/yAr1o7WImJuZbzC4=
github.com/kataras/blocks v0.0.7/go.mod h1:UJIU97CluDo0f+zEjbnbkeMRlvYORtmc1304EeyXf4I=
github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM=
github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg=
github.com/kataras/golog v0.1.9 h1:vLvSDpP7kihFGKFAvBSofYo7qZNULYSHOH2D7rPTKJk=
github.com/kataras/golog v0.1.9/go.mod h1:jlpk/bOaYCyqDqH18pgDHdaJab72yBE6i0O3s30hpWY=
github.com/kataras/jwt v0.1.10 h1:GBXOF9RVInDPhCFBiDumRG9Tt27l7ugLeLo8HL5SeKQ=
@ -263,6 +263,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=

View File

@ -46,6 +46,9 @@ type (
// Expires the duration of which the cookie must expires (created_time.Add(Expires)).
// If you want to delete the cookie when the browser closes, set it to -1.
// However, if you use a database storage setting this value to -1 may
// cause you problems because of the fact that the database
// may has its own expiration mechanism and value will be expired and removed immediately.
//
// 0 means no expire, (24 years)
// -1 means when browser closes