Thanks goes to all of you you help building this (nice) framework - Update README and add errors on mux entry register

This commit is contained in:
Makis Maropoulos 2016-06-16 05:24:01 +03:00
parent dcded4e400
commit 647f0d704c
5 changed files with 56 additions and 32 deletions

View File

@ -84,7 +84,7 @@ Docs & Community
- Take a look at the [examples](https://github.com/iris-contrib/examples) - Take a look at the [examples](https://github.com/iris-contrib/examples)
- If for some reason your old code doesn't runs, view the [HISTORY](https://github.com//kataras/iris/tree/master/HISTORY.md) - [HISTORY](https://github.com//kataras/iris/tree/master/HISTORY.md) file is your friend.
If you'd like to discuss this package, or ask questions about it, feel free to If you'd like to discuss this package, or ask questions about it, feel free to
@ -150,7 +150,9 @@ If you're willing to donate click [here](DONATIONS.md)
People People
------------ ------------
The author of Iris is [@kataras](https://github.com/kataras) A big thanks goes to [all people](https://github.com/kataras/iris/issues?utf8=%E2%9C%93&q=label%3A%22feature+request%22) who help building this framework with feature-requests, bug reports and more!
The author of Iris is [@kataras](https://github.com/kataras).
License License

72
http.go
View File

@ -11,6 +11,7 @@ import (
"github.com/kataras/iris/config" "github.com/kataras/iris/config"
"github.com/kataras/iris/errors" "github.com/kataras/iris/errors"
"github.com/kataras/iris/logger"
"github.com/kataras/iris/utils" "github.com/kataras/iris/utils"
"github.com/valyala/fasthttp" "github.com/valyala/fasthttp"
"github.com/valyala/fasthttp/fasthttpadaptor" "github.com/valyala/fasthttp/fasthttpadaptor"
@ -567,6 +568,17 @@ type (
} }
) )
var (
errMuxEntryConflictsWildcard = errors.New("Router: Path's part: '%s' conflicts with wildcard '%s' in the route path: '%s' !")
errMuxEntryMiddlewareAlreadyExists = errors.New("Router: Middleware were already registered for the path: '%s' !")
errMuxEntryInvalidWildcard = errors.New("Router: More than one wildcard found in the path part: '%s' in route's path: '%s' !")
errMuxEntryConflictsExistingWildcard = errors.New("Router: Wildcard for route path: '%s' conflicts with existing children in route path: '%s' !")
errMuxEntryWildcardUnnamed = errors.New("Router: Unnamed wildcard found in path: '%s' !")
errMuxEntryWildcardInvalidPlace = errors.New("Router: Wildcard is only allowed at the end of the path, in the route path: '%s' !")
errMuxEntryWildcardConflictsMiddleware = errors.New("Router: Wildcard conflicts with existing middleware for the route path: '%s' !")
errMuxEntryWildcardMissingSlash = errors.New("Router: No slash(/) were found before wildcard in the route path: '%s' !")
)
// Get returns a value from a key inside this Parameters // Get returns a value from a key inside this Parameters
// If no parameter with this key given then it returns an empty string // If no parameter with this key given then it returns an empty string
func (params PathParameters) Get(key string) string { func (params PathParameters) Get(key string) string {
@ -635,7 +647,7 @@ func getParamsLen(path string) uint8 {
} }
// add adds a muxEntry to the existing muxEntry or to the tree if no muxEntry has the prefix of // add adds a muxEntry to the existing muxEntry or to the tree if no muxEntry has the prefix of
func (e *muxEntry) add(path string, middleware Middleware) { func (e *muxEntry) add(path string, middleware Middleware) error {
fullPath := path fullPath := path
e.precedence++ e.precedence++
numParams := getParamsLen(path) numParams := getParamsLen(path)
@ -694,8 +706,7 @@ func (e *muxEntry) add(path string, middleware Middleware) {
continue loop continue loop
} }
} }
return errMuxEntryConflictsWildcard.Format(path, e.part, fullPath)
return
} }
c := path[0] c := path[0]
@ -725,24 +736,25 @@ func (e *muxEntry) add(path string, middleware Middleware) {
e = node e = node
} }
e.addNode(numParams, path, fullPath, middleware) e.addNode(numParams, path, fullPath, middleware)
return return nil
} else if i == len(path) { } else if i == len(path) {
if e.middleware != nil { if e.middleware != nil {
return return errMuxEntryMiddlewareAlreadyExists.Format(fullPath)
} }
e.middleware = middleware e.middleware = middleware
} }
return return nil
} }
} else { } else {
e.addNode(numParams, path, fullPath, middleware) e.addNode(numParams, path, fullPath, middleware)
e.entryCase = isRoot e.entryCase = isRoot
} }
return nil
} }
// addNode adds a muxEntry as children to other muxEntry // addNode adds a muxEntry as children to other muxEntry
func (e *muxEntry) addNode(numParams uint8, path string, fullPath string, middleware Middleware) { func (e *muxEntry) addNode(numParams uint8, path string, fullPath string, middleware Middleware) error {
var offset int var offset int
for i, max := 0, len(path); numParams > 0; i++ { for i, max := 0, len(path); numParams > 0; i++ {
@ -752,21 +764,25 @@ func (e *muxEntry) addNode(numParams uint8, path string, fullPath string, middle
} }
end := i + 1 end := i + 1
for end < max && path[end] != '/' { for end < max && path[end] != slashByte {
switch path[end] { switch path[end] {
case parameterStartByte, matchEverythingByte: case parameterStartByte, matchEverythingByte:
/*
panic("only one wildcard per path segment is allowed, has: '" +
path[i:] + "' in path '" + fullPath + "'")
*/
return errMuxEntryInvalidWildcard.Format(path[i:], fullPath)
default: default:
end++ end++
} }
} }
if len(e.nodes) > 0 { if len(e.nodes) > 0 {
return return errMuxEntryConflictsExistingWildcard.Format(path[i:end], fullPath)
} }
if end-i < 2 { if end-i < 2 {
return return errMuxEntryWildcardUnnamed.Format(fullPath)
} }
if c == parameterStartByte { if c == parameterStartByte {
@ -800,16 +816,16 @@ func (e *muxEntry) addNode(numParams uint8, path string, fullPath string, middle
} else { } else {
if end != max || numParams > 1 { if end != max || numParams > 1 {
return return errMuxEntryWildcardInvalidPlace.Format(fullPath)
} }
if len(e.part) > 0 && e.part[len(e.part)-1] == '/' { if len(e.part) > 0 && e.part[len(e.part)-1] == '/' {
return return errMuxEntryWildcardConflictsMiddleware.Format(fullPath)
} }
i-- i--
if path[i] != '/' { if path[i] != slashByte {
return return errMuxEntryWildcardMissingSlash.Format(fullPath)
} }
e.part = path[offset:i] e.part = path[offset:i]
@ -833,12 +849,14 @@ func (e *muxEntry) addNode(numParams uint8, path string, fullPath string, middle
} }
e.nodes = []*muxEntry{child} e.nodes = []*muxEntry{child}
return return nil
} }
} }
e.part = path[offset:] e.part = path[offset:]
e.middleware = middleware e.middleware = middleware
return nil
} }
// get is used by the Router, it finds and returns the correct muxEntry for a path // get is used by the Router, it finds and returns the correct muxEntry for a path
@ -1081,8 +1099,9 @@ type (
api *muxAPI api *muxAPI
errorHandlers map[int]Handler errorHandlers map[int]Handler
// the main server host, ex: localhost, 127.0.0.1:8080, iris-go.com logger *logger.Logger
host string // the main server host's name, ex: localhost, 127.0.0.1, iris-go.com
hostname string
// if any of the trees contains not empty subdomain // if any of the trees contains not empty subdomain
hosts bool hosts bool
// if false then searching by unescaped path // if false then searching by unescaped path
@ -1095,21 +1114,22 @@ type (
} }
) )
func newServeMux(contextPool sync.Pool) *serveMux { func newServeMux(contextPool sync.Pool, logger *logger.Logger) *serveMux {
mux := &serveMux{ mux := &serveMux{
cPool: &contextPool, cPool: &contextPool,
lookups: make([]*route, 0), lookups: make([]*route, 0),
errorHandlers: make(map[int]Handler, 0), errorHandlers: make(map[int]Handler, 0),
host: config.DefaultServerAddr, hostname: "127.0.0.1",
escapePath: !config.DefaultDisablePathEscape, escapePath: !config.DefaultDisablePathEscape,
correctPath: !config.DefaultDisablePathCorrection, correctPath: !config.DefaultDisablePathCorrection,
logger: logger,
} }
return mux return mux
} }
func (mux *serveMux) setHost(h string) { func (mux *serveMux) setHostname(h string) {
mux.host = h mux.hostname = h
} }
func (mux *serveMux) setEscapePath(b bool) { func (mux *serveMux) setEscapePath(b bool) {
@ -1191,7 +1211,9 @@ func (mux *serveMux) register(method []byte, subdomain string, path string, midd
} }
// I decide that it's better to explicit give subdomain and a path to it than registedPath(mysubdomain./something) now its: subdomain: mysubdomain., path: /something // I decide that it's better to explicit give subdomain and a path to it than registedPath(mysubdomain./something) now its: subdomain: mysubdomain., path: /something
// we have different tree for each of subdomains, now you can use everyting you can use with the normal paths ( before you couldn't set /any/*path) // we have different tree for each of subdomains, now you can use everyting you can use with the normal paths ( before you couldn't set /any/*path)
tree.entry.add(path, middleware) if err := tree.entry.add(path, middleware); err != nil {
mux.logger.Panic(err.Error())
}
// add to the lookups, it's just a collection of routes information // add to the lookups, it's just a collection of routes information
lookup := newRoute(method, subdomain, path, middleware) lookup := newRoute(method, subdomain, path, middleware)
@ -1237,13 +1259,13 @@ func (mux *serveMux) ServeRequest() fasthttp.RequestHandler {
if mux.hosts && tree.subdomain != "" { if mux.hosts && tree.subdomain != "" {
// context.VirtualHost() is a slow method because it makes string.Replaces but user can understand that if subdomain then server will have some nano/or/milleseconds performance cost // context.VirtualHost() is a slow method because it makes string.Replaces but user can understand that if subdomain then server will have some nano/or/milleseconds performance cost
requestHost := context.VirtualHostname() requestHost := context.VirtualHostname()
if requestHost != mux.host { if requestHost != mux.hostname {
// we have a subdomain // we have a subdomain
if strings.Index(tree.subdomain, dynamicSubdomainIndicator) != -1 { if strings.Index(tree.subdomain, dynamicSubdomainIndicator) != -1 {
} else { } else {
// mux.host = iris-go.com:8080, the subdomain for example is api., // mux.host = iris-go.com:8080, the subdomain for example is api.,
// so the host must be api.iris-go.com:8080 // so the host must be api.iris-go.com:8080
if tree.subdomain+mux.host != requestHost { if tree.subdomain+mux.hostname != requestHost {
// go to the next tree, we have a subdomain but it is not the correct // go to the next tree, we have a subdomain but it is not the correct
tree = tree.next tree = tree.next
continue continue

View File

@ -99,7 +99,7 @@ func New(cfg ...config.Iris) *Framework {
// set the websocket server // set the websocket server
s.Websocket = websocket.NewServer(s.Config.Websocket) s.Websocket = websocket.NewServer(s.Config.Websocket)
// set the servemux, which will provide us the public API also, with its context pool // set the servemux, which will provide us the public API also, with its context pool
mux := newServeMux(sync.Pool{New: func() interface{} { return &Context{framework: s} }}) mux := newServeMux(sync.Pool{New: func() interface{} { return &Context{framework: s} }}, s.Logger)
// set the public router API (and party) // set the public router API (and party)
s.muxAPI = &muxAPI{mux: mux, relativePath: "/"} s.muxAPI = &muxAPI{mux: mux, relativePath: "/"}
// set the server // set the server
@ -128,7 +128,7 @@ func (s *Framework) initialize() {
// prepare the mux // prepare the mux
s.mux.setCorrectPath(!s.Config.DisablePathCorrection) s.mux.setCorrectPath(!s.Config.DisablePathCorrection)
s.mux.setEscapePath(!s.Config.DisablePathEscape) s.mux.setEscapePath(!s.Config.DisablePathEscape)
s.mux.setHost(s.HTTPServer.VirtualHostname()) s.mux.setHostname(s.HTTPServer.VirtualHostname())
// set the debug profiling handlers if ProfilePath is setted // set the debug profiling handlers if ProfilePath is setted
if debugPath := s.Config.ProfilePath; debugPath != "" { if debugPath := s.Config.ProfilePath; debugPath != "" {
s.Handle(MethodGet, debugPath+"/*action", profileMiddleware(debugPath)...) s.Handle(MethodGet, debugPath+"/*action", profileMiddleware(debugPath)...)

View File

@ -1042,7 +1042,7 @@ func StaticFS(reqPath string, systemPath string, stripSlashes int) RouteNameFunc
// * stripSlashes = 2, original path: "/foo/bar", result: "" // * stripSlashes = 2, original path: "/foo/bar", result: ""
func (api *muxAPI) StaticFS(reqPath string, systemPath string, stripSlashes int) RouteNameFunc { func (api *muxAPI) StaticFS(reqPath string, systemPath string, stripSlashes int) RouteNameFunc {
if reqPath[len(reqPath)-1] != slashByte { if reqPath[len(reqPath)-1] != slashByte {
reqPath += "/" reqPath += slash
} }
h := api.StaticHandler(systemPath, stripSlashes, true, true, nil) h := api.StaticHandler(systemPath, stripSlashes, true, true, nil)
@ -1074,7 +1074,7 @@ func StaticWeb(reqPath string, systemPath string, stripSlashes int) RouteNameFun
// * if you don't know what to put on stripSlashes just 1 // * if you don't know what to put on stripSlashes just 1
func (api *muxAPI) StaticWeb(reqPath string, systemPath string, stripSlashes int) RouteNameFunc { func (api *muxAPI) StaticWeb(reqPath string, systemPath string, stripSlashes int) RouteNameFunc {
if reqPath[len(reqPath)-1] != slashByte { // if / then /*filepath, if /something then /something/*filepath if reqPath[len(reqPath)-1] != slashByte { // if / then /*filepath, if /something then /something/*filepath
reqPath += "/" reqPath += slash
} }
hasIndex := utils.Exists(systemPath + utils.PathSeparator + "index.html") hasIndex := utils.Exists(systemPath + utils.PathSeparator + "index.html")

View File

@ -110,7 +110,7 @@ func (l *Logger) Fatalf(format string, a ...interface{}) {
// Panic is equivalent to l.Dangerf("%#v",interface{}) followed by a call to panic(). // Panic is equivalent to l.Dangerf("%#v",interface{}) followed by a call to panic().
func (l *Logger) Panic(a interface{}) { func (l *Logger) Panic(a interface{}) {
l.Dangerf("%#v", a) l.Dangerf("%s\n", a)
panic("") panic("")
} }