func (api *APIBuilder) OnAnyErrorCode(handlers ...context.Handler) {
	for code := 100; code <= 511; code++ {
		if context.StatusCodeNotSuccessful(code) {
			api.OnErrorCode(code, handlers...)
		}
	}
}
OnAnyErrorCode registers a handler which called when error status code written.
Same as `OnErrorCode` but registers all http error codes based on the `context.StatusCodeNotSuccessful`
which defaults to < 200 || >= 400 for an error code, any previous error code will be overridden,
so call it first if you want to use any custom handler for a specific error status code.

Read more at: http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
package router
import (
	"net/http"
	"os"
	"path"
	"strings"
	"time"
	"github.com/kataras/iris/context"
	"github.com/kataras/iris/core/errors"
	"github.com/kataras/iris/core/router/macro"
)
const (
	MethodNone = "NONE"
)
var (
	AllMethods = [...]string{
		"GET",
		"POST",
		"PUT",
		"DELETE",
		"CONNECT",
		"HEAD",
		"PATCH",
		"OPTIONS",
		"TRACE",
	}
)
type repository struct {
	routes []*Route
}
func (r *repository) register(route *Route) {
	for _, r := range r.routes {
		if r.String() == route.String() {
			return  
		}
	}
	r.routes = append(r.routes, route)
}
func (r *repository) get(routeName string) *Route {
	for _, r := range r.routes {
		if r.Name == routeName {
			return r
		}
	}
	return nil
}
func (r *repository) getAll() []*Route {
	return r.routes
}
type APIBuilder struct {
	macros *macro.Map
	errorCodeHandlers *ErrorCodeHandlers
	routes *repository
	reverser *RoutePathReverser
	reporter *errors.Reporter
	middleware context.Handlers
	beginGlobalHandlers context.Handlers
	doneHandlers context.Handlers
	doneGlobalHandlers context.Handlers
	relativePath string
	allowMethods []string
}
var _ Party = (*APIBuilder)(nil)
var _ RoutesProvider = (*APIBuilder)(nil)  
func NewAPIBuilder() *APIBuilder {
	api := &APIBuilder{
		macros:            defaultMacros(),
		errorCodeHandlers: defaultErrorCodeHandlers(),
		reporter:          errors.NewReporter(),
		relativePath:      "/",
		routes:            new(repository),
	}
	return api
}
func (api *APIBuilder) GetRelPath() string {
	return api.relativePath
}
func (api *APIBuilder) GetReport() error {
	return api.reporter.Return()
}
func (api *APIBuilder) GetReporter() *errors.Reporter {
	return api.reporter
}
func (api *APIBuilder) AllowMethods(methods ...string) Party {
	api.allowMethods = methods
	return api
}
func (api *APIBuilder) Handle(method string, relativePath string, handlers ...context.Handler) *Route {
	if method == "" || method == "ALL" || method == "ANY" {  
		return api.Any(relativePath, handlers...)[0]
	}
	if api.relativePath[len(api.relativePath)-1] == '/' {
		if relativePath[0] == '/' {
			relativePath = relativePath[1:]
		}
	}
	fullpath := api.relativePath + relativePath  
	if len(handlers) == 0 {
		api.reporter.Add("missing handlers for route %s: %s", method, fullpath)
		return nil
	}
	possibleMainHandlerName := context.HandlerName(handlers[0])
	routeHandlers := joinHandlers(api.middleware, handlers)
	routeHandlers = joinHandlers(routeHandlers, api.doneHandlers)
	subdomain, path := splitSubdomainAndPath(fullpath)
	methods := append(api.allowMethods, method)
	var (
		route *Route  
		err   error   
	)
	for _, m := range methods {
		route, err = NewRoute(m, subdomain, path, possibleMainHandlerName, routeHandlers, api.macros)
		if err != nil {  
			api.reporter.Add("%v -> %s:%s:%s", err, method, subdomain, path)
			return nil  
		}
		route.use(api.beginGlobalHandlers)
		route.done(api.doneGlobalHandlers)
		api.routes.register(route)
	}
	return route
}
func (api *APIBuilder) HandleMany(methodOrMulti string, relativePathorMulti string, handlers ...context.Handler) (routes []*Route) {
	paths := splitPath(relativePathorMulti)
	methods := splitMethod(methodOrMulti)
	for _, p := range paths {
		if p != "" {
			for _, method := range methods {
				if method == "" {
					method = "ANY"
				}
				if method == "ANY" || method == "ALL" {
					routes = append(routes, api.Any(p, handlers...)...)
					continue
				}
				routes = append(routes, api.Handle(method, p, handlers...))
			}
		}
	}
	return
}
func (api *APIBuilder) Party(relativePath string, handlers ...context.Handler) Party {
	parentPath := api.relativePath
	dot := string(SubdomainPrefix[0])
	if len(parentPath) > 0 && parentPath[0] == '/' && strings.HasSuffix(relativePath, dot) {
		parentPath = parentPath[1:]  
	}
	if api.relativePath[len(api.relativePath)-1] == '/' && relativePath[0] == '/' {
		relativePath = relativePath[1:]  
	}
	if hasSubdomain(parentPath) && hasSubdomain(relativePath) {
		relativePath = relativePath + parentPath
		parentPath = ""
	}
	fullpath := parentPath + relativePath
	middleware := joinHandlers(api.middleware, handlers)
	allowMethods := make([]string, len(api.allowMethods))
	copy(allowMethods, api.allowMethods)
	return &APIBuilder{
		macros:              api.macros,
		routes:              api.routes,
		errorCodeHandlers:   api.errorCodeHandlers,
		beginGlobalHandlers: api.beginGlobalHandlers,
		doneGlobalHandlers:  api.doneGlobalHandlers,
		reporter:            api.reporter,
		middleware:   middleware,
		doneHandlers: api.doneHandlers[0:],
		relativePath: fullpath,
		allowMethods: allowMethods,
	}
}
func (api *APIBuilder) PartyFunc(relativePath string, partyBuilderFunc func(p Party)) Party {
	p := api.Party(relativePath)
	partyBuilderFunc(p)
	return p
}
func (api *APIBuilder) Subdomain(subdomain string, middleware ...context.Handler) Party {
	if api.relativePath == SubdomainWildcardIndicator {
		api.reporter.Add("cannot concat parent wildcard subdomain with anything else ->  %s , %s",
			api.relativePath, subdomain)
		return api
	}
	if l := len(subdomain); l < 1 {
		return api
	} else if subdomain[l-1] != '.' {
		subdomain += "."
	}
	return api.Party(subdomain, middleware...)
}
func (api *APIBuilder) WildcardSubdomain(middleware ...context.Handler) Party {
	if hasSubdomain(api.relativePath) {
		api.reporter.Add("cannot concat static subdomain with a dynamic one. Dynamic subdomains should be at the root level -> %s",
			api.relativePath)
		return api
	}
	return api.Subdomain(SubdomainWildcardIndicator, middleware...)
}
func (api *APIBuilder) Macros() *macro.Map {
	return api.macros
}
func (api *APIBuilder) GetRoutes() []*Route {
	return api.routes.getAll()
}
func (api *APIBuilder) GetRoute(routeName string) *Route {
	return api.routes.get(routeName)
}
func (api *APIBuilder) GetRouteReadOnly(routeName string) context.RouteReadOnly {
	r := api.GetRoute(routeName)
	if r == nil {
		return nil
	}
	return routeReadOnlyWrapper{r}
}
func (api *APIBuilder) Use(handlers ...context.Handler) {
	api.middleware = append(api.middleware, handlers...)
}
func (api *APIBuilder) UseGlobal(handlers ...context.Handler) {
	for _, r := range api.routes.routes {
		r.use(handlers)  
	}
	api.beginGlobalHandlers = append(api.beginGlobalHandlers, handlers...)
}
func (api *APIBuilder) Done(handlers ...context.Handler) {
	api.doneHandlers = append(api.doneHandlers, handlers...)
}
func (api *APIBuilder) DoneGlobal(handlers ...context.Handler) {
	for _, r := range api.routes.routes {
		r.done(handlers)  
	}
	api.doneGlobalHandlers = append(api.doneGlobalHandlers, handlers...)
}
func (api *APIBuilder) Reset() Party {
	api.middleware = api.middleware[0:0]
	api.doneHandlers = api.doneHandlers[0:0]
	return api
}
func (api *APIBuilder) None(relativePath string, handlers ...context.Handler) *Route {
	return api.Handle(MethodNone, relativePath, handlers...)
}
func (api *APIBuilder) Get(relativePath string, handlers ...context.Handler) *Route {
	return api.Handle(http.MethodGet, relativePath, handlers...)
}
func (api *APIBuilder) Post(relativePath string, handlers ...context.Handler) *Route {
	return api.Handle(http.MethodPost, relativePath, handlers...)
}
func (api *APIBuilder) Put(relativePath string, handlers ...context.Handler) *Route {
	return api.Handle(http.MethodPut, relativePath, handlers...)
}
func (api *APIBuilder) Delete(relativePath string, handlers ...context.Handler) *Route {
	return api.Handle(http.MethodDelete, relativePath, handlers...)
}
func (api *APIBuilder) Connect(relativePath string, handlers ...context.Handler) *Route {
	return api.Handle(http.MethodConnect, relativePath, handlers...)
}
func (api *APIBuilder) Head(relativePath string, handlers ...context.Handler) *Route {
	return api.Handle(http.MethodHead, relativePath, handlers...)
}
func (api *APIBuilder) Options(relativePath string, handlers ...context.Handler) *Route {
	return api.Handle(http.MethodOptions, relativePath, handlers...)
}
func (api *APIBuilder) Patch(relativePath string, handlers ...context.Handler) *Route {
	return api.Handle(http.MethodPatch, relativePath, handlers...)
}
func (api *APIBuilder) Trace(relativePath string, handlers ...context.Handler) *Route {
	return api.Handle(http.MethodTrace, relativePath, handlers...)
}
func (api *APIBuilder) Any(relativePath string, handlers ...context.Handler) (routes []*Route) {
	for _, m := range AllMethods {
		r := api.HandleMany(m, relativePath, handlers...)
		routes = append(routes, r...)
	}
	return
}
func (api *APIBuilder) registerResourceRoute(reqPath string, h context.Handler) *Route {
	api.Head(reqPath, h)
	return api.Get(reqPath, h)
}
func (api *APIBuilder) StaticHandler(systemPath string, showList bool, gzip bool) context.Handler {
	return StaticHandler(systemPath, showList, gzip)
}
func (api *APIBuilder) StaticServe(systemPath string, requestPath ...string) *Route {
	var reqPath string
	if len(requestPath) == 0 {
		reqPath = strings.Replace(systemPath, string(os.PathSeparator), "/", -1)  
		reqPath = strings.Replace(reqPath, "//", "/", -1)                         
		reqPath = strings.Replace(reqPath, ".", "", -1)                           
	} else {
		reqPath = requestPath[0]
	}
	return api.StaticWeb(reqPath, systemPath)
}
func (api *APIBuilder) StaticContent(reqPath string, cType string, content []byte) *Route {
	modtime := time.Now()
	h := func(ctx context.Context) {
		ctx.ContentType(cType)
		if _, err := ctx.WriteWithExpiration(content, modtime); err != nil {
			ctx.StatusCode(http.StatusInternalServerError)
		}
	}
	return api.registerResourceRoute(reqPath, h)
}
func (api *APIBuilder) StaticEmbedded(requestPath string, vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string) *Route {
	return api.staticEmbedded(requestPath, vdir, assetFn, namesFn, false)
}
func (api *APIBuilder) StaticEmbeddedGzip(requestPath string, vdir string, gzipAssetFn func(name string) ([]byte, error), gzipNamesFn func() []string) *Route {
	return api.staticEmbedded(requestPath, vdir, gzipAssetFn, gzipNamesFn, true)
}
func (api *APIBuilder) staticEmbedded(requestPath string, vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string, assetsGziped bool) *Route {
	fullpath := joinPath(api.relativePath, requestPath)
	_, fullpath = splitSubdomainAndPath(fullpath)
	paramName := "file"
	requestPath = joinPath(requestPath, WildcardParam(paramName))
	h := StaticEmbeddedHandler(vdir, assetFn, namesFn, assetsGziped)
	if fullpath != "/" {
		h = StripPrefix(fullpath, h)
	}
	return api.registerResourceRoute(requestPath, h)
}
var errDirectoryFileNotFound = errors.New("Directory or file %s couldn't found. Trace: %s")
func (api *APIBuilder) Favicon(favPath string, requestPath ...string) *Route {
	favPath = Abs(favPath)
	f, err := os.Open(favPath)
	if err != nil {
		api.reporter.AddErr(errDirectoryFileNotFound.Format(favPath, err.Error()))
		return nil
	}
	defer f.Close()
	fi, _ := f.Stat()
	if fi.IsDir() {  
		return api.Favicon(path.Join(favPath, "favicon.ico"))
	}
	cacheFav := make([]byte, fi.Size())
	if _, err = f.Read(cacheFav); err != nil {
		api.reporter.AddErr(errDirectoryFileNotFound.
			Format(favPath, "favicon: couldn't read the data bytes for file: "+err.Error()))
		return nil
	}
	modtime := time.Now()
	cType := TypeByFilename(favPath)
	h := func(ctx context.Context) {
		ctx.ContentType(cType)
		if _, err := ctx.WriteWithExpiration(cacheFav, modtime); err != nil {
			ctx.StatusCode(http.StatusInternalServerError)
			ctx.Application().Logger().Debugf("while trying to serve the favicon: %s", err.Error())
		}
	}
	reqPath := "/favicon" + path.Ext(fi.Name())  
	if len(requestPath) > 0 && requestPath[0] != "" {
		reqPath = requestPath[0]
	}
	return api.registerResourceRoute(reqPath, h)
}
func (api *APIBuilder) StaticWeb(requestPath string, systemPath string) *Route {
	fullpath := joinPath(api.relativePath, requestPath)
	_, fullpath = splitSubdomainAndPath(fullpath)
	paramName := "file"
	requestPath = joinPath(requestPath, WildcardParam(paramName))
	h := NewStaticHandlerBuilder(systemPath).Listing(false).Build()
	if fullpath != "/" {
		h = StripPrefix(fullpath, h)
	}
	return api.registerResourceRoute(requestPath, h)
}
func (api *APIBuilder) OnErrorCode(statusCode int, handlers ...context.Handler) {
	if len(api.beginGlobalHandlers) > 0 {
		handlers = joinHandlers(api.beginGlobalHandlers, handlers)
	}
	api.errorCodeHandlers.Register(statusCode, handlers...)
}