mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 15:30:36 +01:00
Former-commit-id: 12b75f1e54ebf3d7f78a09b8d5594859a344422d
This commit is contained in:
parent
3fbf15d576
commit
c3543528cf
|
@ -48,5 +48,7 @@ func newApp() *iris.Application {
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := newApp()
|
app := newApp()
|
||||||
|
app.Logger().SetLevel("debug")
|
||||||
|
|
||||||
app.Listen(":8080")
|
app.Listen(":8080")
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ func BenchmarkAPIBuilder(b *testing.B) {
|
||||||
paths := genPaths(routesLength, 15, 42)
|
paths := genPaths(routesLength, 15, 42)
|
||||||
|
|
||||||
api := NewAPIBuilder()
|
api := NewAPIBuilder()
|
||||||
requestHandler := NewDefaultHandler(nil)
|
requestHandler := NewDefaultHandler(nil, nil)
|
||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -11,6 +12,7 @@ import (
|
||||||
macroHandler "github.com/kataras/iris/v12/macro/handler"
|
macroHandler "github.com/kataras/iris/v12/macro/handler"
|
||||||
|
|
||||||
"github.com/kataras/golog"
|
"github.com/kataras/golog"
|
||||||
|
"github.com/kataras/pio"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RequestHandler the middle man between acquiring a context and releasing it.
|
// RequestHandler the middle man between acquiring a context and releasing it.
|
||||||
|
@ -25,13 +27,24 @@ type RequestHandler interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type routerHandler struct {
|
type routerHandler struct {
|
||||||
trees []*trie
|
|
||||||
hosts bool // true if at least one route contains a Subdomain.
|
|
||||||
config context.ConfigurationReadOnly
|
config context.ConfigurationReadOnly
|
||||||
|
logger *golog.Logger
|
||||||
|
|
||||||
|
trees []*trie
|
||||||
|
hosts bool // true if at least one route contains a Subdomain.
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ RequestHandler = &routerHandler{}
|
var _ RequestHandler = &routerHandler{}
|
||||||
|
|
||||||
|
// NewDefaultHandler returns the handler which is responsible
|
||||||
|
// to map the request with a route (aka mux implementation).
|
||||||
|
func NewDefaultHandler(config context.ConfigurationReadOnly, logger *golog.Logger) RequestHandler {
|
||||||
|
return &routerHandler{
|
||||||
|
config: config,
|
||||||
|
logger: logger,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (h *routerHandler) getTree(method, subdomain string) *trie {
|
func (h *routerHandler) getTree(method, subdomain string) *trie {
|
||||||
for i := range h.trees {
|
for i := range h.trees {
|
||||||
t := h.trees[i]
|
t := h.trees[i]
|
||||||
|
@ -66,14 +79,6 @@ func (h *routerHandler) AddRoute(r *Route) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDefaultHandler returns the handler which is responsible
|
|
||||||
// to map the request with a route (aka mux implementation).
|
|
||||||
func NewDefaultHandler(config context.ConfigurationReadOnly) RequestHandler {
|
|
||||||
return &routerHandler{
|
|
||||||
config: config,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RoutesProvider should be implemented by
|
// RoutesProvider should be implemented by
|
||||||
// iteral which contains the registered routes.
|
// iteral which contains the registered routes.
|
||||||
type RoutesProvider interface { // api builder
|
type RoutesProvider interface { // api builder
|
||||||
|
@ -155,13 +160,13 @@ func (h *routerHandler) Build(provider RoutesProvider) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if golog.Default.Level == golog.DebugLevel {
|
if logger := h.logger; logger != nil && logger.Level == golog.DebugLevel {
|
||||||
tr := "routes"
|
tr := "Routes"
|
||||||
if len(registeredRoutes) == 1 {
|
if len(registeredRoutes) == 1 {
|
||||||
tr = tr[0 : len(tr)-1]
|
tr = tr[0 : len(tr)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
golog.Debugf("API: %d registered %s", len(registeredRoutes), tr)
|
// logger.Debugf("%s: %d", tr, len(registeredRoutes))
|
||||||
|
|
||||||
// group routes by method and print them without the [DBUG] and time info,
|
// group routes by method and print them without the [DBUG] and time info,
|
||||||
// the route logs are colorful.
|
// the route logs are colorful.
|
||||||
|
@ -177,24 +182,57 @@ func (h *routerHandler) Build(provider RoutesProvider) error {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
bckpTimeFormat := golog.Default.TimeFormat
|
// bckpTimeFormat := logger.TimeFormat
|
||||||
defer golog.SetTimeFormat(bckpTimeFormat)
|
// defer logger.SetTimeFormat(bckpTimeFormat)
|
||||||
golog.SetTimeFormat("")
|
// logger.SetTimeFormat("")
|
||||||
|
|
||||||
newLine := []byte("\n")
|
type methodCount struct {
|
||||||
|
method string
|
||||||
|
count int
|
||||||
|
}
|
||||||
|
|
||||||
for _, method := range append(AllMethods, MethodNone) {
|
allMethods := append(AllMethods, MethodNone)
|
||||||
|
routeMethodCounts := make([]methodCount, 0, len(allMethods))
|
||||||
|
|
||||||
|
for i, method := range allMethods {
|
||||||
methodRoutes := collect(method)
|
methodRoutes := collect(method)
|
||||||
if len(methodRoutes) == 0 {
|
if len(methodRoutes) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
routeMethodCounts = append(routeMethodCounts, methodCount{method, len(methodRoutes)})
|
||||||
|
|
||||||
for _, r := range methodRoutes {
|
for _, r := range methodRoutes {
|
||||||
r.Trace(golog.Default.Printer)
|
r.Trace(logger.Printer)
|
||||||
}
|
}
|
||||||
|
|
||||||
golog.Default.Printer.Write(newLine)
|
if i != len(allMethods)-1 {
|
||||||
|
logger.Printer.Write(pio.NewLine)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if n := len(routeMethodCounts); n > 0 {
|
||||||
|
tr := "routes"
|
||||||
|
if len(registeredRoutes) == 1 {
|
||||||
|
tr = tr[0 : len(tr)-1]
|
||||||
|
}
|
||||||
|
fmt.Fprintf(logger.Printer, "%s API: %d registered %s (", golog.GetTextForLevel(golog.DebugLevel, true), len(registeredRoutes), tr)
|
||||||
|
for i, mc := range routeMethodCounts {
|
||||||
|
// @method: @count
|
||||||
|
if i > 0 {
|
||||||
|
if i == n-1 {
|
||||||
|
fmt.Fprint(logger.Printer, " and ")
|
||||||
|
} else {
|
||||||
|
fmt.Fprint(logger.Printer, ", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Fprintf(logger.Printer, "%d ", mc.count)
|
||||||
|
pio.WriteRich(logger.Printer, mc.method, traceMethodColor(mc.method))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprint(logger.Printer, ")\n")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return errgroup.Check(rp)
|
return errgroup.Check(rp)
|
||||||
|
|
|
@ -349,7 +349,28 @@ func traceHandlerFile(method, name, line string, number int) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
space := strings.Repeat(" ", len(method)+1)
|
space := strings.Repeat(" ", len(method)+1)
|
||||||
return fmt.Sprintf("\n%s ⬝ %s %s", space, name, file)
|
return fmt.Sprintf("\n%s • %s %s", space, name, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
var methodColors = map[string]int{
|
||||||
|
http.MethodGet: pio.Green,
|
||||||
|
http.MethodPost: pio.Magenta,
|
||||||
|
http.MethodPut: pio.Blue,
|
||||||
|
http.MethodDelete: pio.Red,
|
||||||
|
http.MethodConnect: pio.Green,
|
||||||
|
http.MethodHead: 23,
|
||||||
|
http.MethodPatch: pio.Blue,
|
||||||
|
http.MethodOptions: pio.Gray,
|
||||||
|
http.MethodTrace: pio.Yellow,
|
||||||
|
MethodNone: 203, // orange-red.
|
||||||
|
}
|
||||||
|
|
||||||
|
func traceMethodColor(method string) int {
|
||||||
|
if color, ok := methodColors[method]; ok {
|
||||||
|
return color
|
||||||
|
}
|
||||||
|
|
||||||
|
return pio.Black
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trace prints some debug info about the Route to the "w".
|
// Trace prints some debug info about the Route to the "w".
|
||||||
|
@ -361,39 +382,18 @@ func traceHandlerFile(method, name, line string, number int) string {
|
||||||
// If route and handler line:number locations are equal then the second is ignored.
|
// If route and handler line:number locations are equal then the second is ignored.
|
||||||
func (r *Route) Trace(w io.Writer) {
|
func (r *Route) Trace(w io.Writer) {
|
||||||
// Color the method.
|
// Color the method.
|
||||||
color := pio.Black
|
color := traceMethodColor(r.Method)
|
||||||
switch r.Method {
|
|
||||||
case http.MethodGet:
|
// @method: @path
|
||||||
color = pio.Green
|
// space := strings.Repeat(" ", len(http.MethodConnect)-len(r.Method))
|
||||||
case http.MethodPost:
|
// s := fmt.Sprintf("%s: %s", pio.Rich(r.Method, color), path)
|
||||||
color = pio.Magenta
|
pio.WriteRich(w, r.Method, color)
|
||||||
case http.MethodPut:
|
|
||||||
color = pio.Blue
|
|
||||||
case http.MethodDelete:
|
|
||||||
color = pio.Red
|
|
||||||
case http.MethodConnect:
|
|
||||||
color = pio.Green
|
|
||||||
case http.MethodHead:
|
|
||||||
color = 23
|
|
||||||
case http.MethodPatch:
|
|
||||||
color = pio.Blue
|
|
||||||
case http.MethodOptions:
|
|
||||||
color = pio.Gray
|
|
||||||
case http.MethodTrace:
|
|
||||||
color = pio.Yellow
|
|
||||||
case MethodNone:
|
|
||||||
color = 203 // orange-red.
|
|
||||||
}
|
|
||||||
|
|
||||||
path := r.Tmpl().Src
|
path := r.Tmpl().Src
|
||||||
if path == "" {
|
if path == "" {
|
||||||
path = "/"
|
path = "/"
|
||||||
}
|
}
|
||||||
|
|
||||||
// @method: @path
|
|
||||||
// space := strings.Repeat(" ", len(http.MethodConnect)-len(r.Method))
|
|
||||||
// s := fmt.Sprintf("%s: %s", pio.Rich(r.Method, color), path)
|
|
||||||
pio.WriteRich(w, r.Method, color)
|
|
||||||
fmt.Fprintf(w, ": %s", path)
|
fmt.Fprintf(w, ": %s", path)
|
||||||
|
|
||||||
// (@description)
|
// (@description)
|
||||||
|
|
14
i18n/i18n.go
14
i18n/i18n.go
|
@ -248,6 +248,13 @@ func parsePath(m *Matcher, path string) int {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func reverseStrings(s []string) []string {
|
||||||
|
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
|
||||||
|
s[i], s[j] = s[j], s[i]
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
func parseLanguage(path string) (language.Tag, bool) {
|
func parseLanguage(path string) (language.Tag, bool) {
|
||||||
if idx := strings.LastIndexByte(path, '.'); idx > 0 {
|
if idx := strings.LastIndexByte(path, '.'); idx > 0 {
|
||||||
path = path[0:idx]
|
path = path[0:idx]
|
||||||
|
@ -259,6 +266,8 @@ func parseLanguage(path string) (language.Tag, bool) {
|
||||||
return r == '_' || r == os.PathSeparator || r == '/' || r == '.'
|
return r == '_' || r == os.PathSeparator || r == '/' || r == '.'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
names = reverseStrings(names) // see https://github.com/kataras/i18n/issues/1
|
||||||
|
|
||||||
for _, s := range names {
|
for _, s := range names {
|
||||||
t, err := language.Parse(s)
|
t, err := language.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -303,7 +312,7 @@ func (i *I18n) Tr(lang, format string, args ...interface{}) string {
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf(format, args...)
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
const acceptLanguageHeaderKey = "Accept-Language"
|
const acceptLanguageHeaderKey = "Accept-Language"
|
||||||
|
@ -372,6 +381,7 @@ func (i *I18n) GetLocale(ctx context.Context) context.Locale {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMessage returns the localized text message for this "r" request based on the key "format".
|
// GetMessage returns the localized text message for this "r" request based on the key "format".
|
||||||
|
// It returns an empty string if locale or format not found.
|
||||||
func (i *I18n) GetMessage(ctx context.Context, format string, args ...interface{}) string {
|
func (i *I18n) GetMessage(ctx context.Context, format string, args ...interface{}) string {
|
||||||
loc := i.GetLocale(ctx)
|
loc := i.GetLocale(ctx)
|
||||||
if loc != nil {
|
if loc != nil {
|
||||||
|
@ -382,7 +392,7 @@ func (i *I18n) GetMessage(ctx context.Context, format string, args ...interface{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf(format, args...)
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper returns a new router wrapper.
|
// Wrapper returns a new router wrapper.
|
||||||
|
|
8
iris.go
8
iris.go
|
@ -731,7 +731,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.
|
||||||
|
|
||||||
rp := errgroup.New("Application Builder")
|
rp := errgroup.New("Application Builder")
|
||||||
|
@ -803,7 +803,7 @@ func (app *Application) Build() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the request handler, the default routing handler
|
// create the request handler, the default routing handler
|
||||||
routerHandler := router.NewDefaultHandler(app.config)
|
routerHandler := router.NewDefaultHandler(app.config, app.logger)
|
||||||
err := app.Router.BuildRouter(app.ContextPool, routerHandler, app.APIBuilder, false)
|
err := app.Router.BuildRouter(app.ContextPool, routerHandler, app.APIBuilder, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rp.Err(err)
|
rp.Err(err)
|
||||||
|
@ -813,7 +813,7 @@ func (app *Application) Build() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if end := time.Since(start); end.Seconds() > 5 {
|
// if end := time.Since(start); end.Seconds() > 5 {
|
||||||
app.logger.Debugf("Application: build took %s", time.Since(start))
|
// app.logger.Debugf("Application: build took %s", time.Since(start))
|
||||||
|
|
||||||
return errgroup.Check(rp)
|
return errgroup.Check(rp)
|
||||||
}
|
}
|
||||||
|
@ -1172,7 +1172,7 @@ func (app *Application) tryStartTunneling() {
|
||||||
// to make subdomains resolution still based on this new remote, public addresses.
|
// to make subdomains resolution still based on this new remote, public addresses.
|
||||||
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.Output.Write(directLog)
|
app.Logger().Printer.Output.Write(directLog)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue
Block a user